Completed
Pull Request — master (#446)
by thomas
157:14 queued 87:18
created

TransactionSerializer::serialize()   C

Complexity

Conditions 8
Paths 32

Size

Total Lines 35
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 8

Importance

Changes 0
Metric Value
cc 8
eloc 20
c 0
b 0
f 0
nc 32
nop 2
dl 0
loc 35
ccs 22
cts 22
cp 1
crap 8
rs 5.3846
1
<?php
2
3
namespace BitWasp\Bitcoin\Serializer\Transaction;
4
5
use BitWasp\Bitcoin\Serializer\Script\ScriptWitnessSerializer;
6
use BitWasp\Bitcoin\Serializer\Types;
7
use BitWasp\Bitcoin\Transaction\Transaction;
8
use BitWasp\Bitcoin\Transaction\TransactionInterface;
9
use BitWasp\Buffertools\BufferInterface;
10
use BitWasp\Buffertools\Buffertools;
11
use BitWasp\Buffertools\Parser;
12
13
class TransactionSerializer implements TransactionSerializerInterface
14
{
15
    const NO_WITNESS = 1;
16
17
    /**
18
     * @var \BitWasp\Buffertools\Types\Int32
19
     */
20
    private $int32le;
21
22
    /**
23
     * @var \BitWasp\Buffertools\Types\Uint32
24
     */
25
    private $uint32le;
26
27
    /**
28
     * @var \BitWasp\Buffertools\Types\VarInt
29
     */
30
    private $varint;
31
32
    /**
33
     * @var TransactionInputSerializer
34
     */
35
    private $inputSerializer;
36 270
37
    /**
38 270
     * @var TransactionOutputSerializer
39 270
     */
40 270
    private $outputSerializer;
41 270
42
    /**
43
     * @var ScriptWitnessSerializer
44
     */
45
    private $witnessSerializer;
46
47 186
    public function __construct(TransactionInputSerializer $inputSerializer = null, TransactionOutputSerializer $outputSerializer = null, ScriptWitnessSerializer $witnessSerializer = null)
48
    {
49 186
        $this->int32le = Types::int32le();
50 186
        $this->uint32le = Types::uint32le();
51 186
        $this->varint = Types::varint();
52 186
53
        $this->inputSerializer = $inputSerializer ?: new TransactionInputSerializer(new OutPointSerializer());
54 186
        $this->outputSerializer = $outputSerializer ?: new TransactionOutputSerializer;
55
        $this->witnessSerializer = $witnessSerializer ?: new ScriptWitnessSerializer();
56 186
    }
57 186
58 186
    /**
59 186
     * @param Parser $parser
60 93
     * @return TransactionInterface
61
     */
62 186
    public function fromParser(Parser $parser)
63 186
    {
64 186
        $version = $this->int32le->read($parser);
65
66
        $vin = [];
67
        $vinCount = $this->varint->read($parser);
68
        for ($i = 0; $i < $vinCount; $i++) {
69
            $vin[] = $this->inputSerializer->fromParser($parser);
70
        }
71
72
        $vout = [];
73
        $flags = 0;
74
        if (count($vin) === 0) {
75
            $flags = (int) $this->varint->read($parser);
76
            if ($flags !== 0) {
77
                $vinCount = $this->varint->read($parser);
78 186
                for ($i = 0; $i < $vinCount; $i++) {
79 186
                    $vin[] = $this->inputSerializer->fromParser($parser);
80 186
                }
81 93
82
                $voutCount = $this->varint->read($parser);
83
                for ($i = 0; $i < $voutCount; $i++) {
84 186
                    $vout[] = $this->outputSerializer->fromParser($parser);
85 186
                }
86
            }
87
        } else {
88
            $voutCount = $this->varint->read($parser);
89
            for ($i = 0; $i < $voutCount; $i++) {
90
                $vout[] = $this->outputSerializer->fromParser($parser);
91
            }
92
        }
93
94 186
        $vwit = [];
95
        if (($flags & 1)) {
96
            $flags ^= 1;
97
            $witCount = count($vin);
98 186
            for ($i = 0; $i < $witCount; $i++) {
99
                $vectorCount = $this->varint->read($parser);
100 186
                $vwit[] = $this->witnessSerializer->fromParser($parser, $vectorCount);
101 93
            }
102 93
        }
103 93
104 93
        if ($flags) {
105
            throw new \RuntimeException('Flags byte was 0');
106 93
        }
107
108
        $lockTime = $this->uint32le->read($parser);
109
110
        return new Transaction($version, $vin, $vout, $vwit, $lockTime);
111
    }
112
113 120
    /**
114
     * @param string|BufferInterface $data
115 120
     * @return TransactionInterface
116
     */
117
    public function parse($data)
118
    {
119
        return $this->fromParser(new Parser($data));
120
    }
121
122 66
    /**
123
     * @param TransactionInterface $transaction
124 66
     * @param int $opt
125 66
     * @return BufferInterface
126 66
     */
127 66
    public function serialize(TransactionInterface $transaction, $opt = 0)
128 66
    {
129 66
        $parser = new Parser();
130 66
        $parser->writeRawBinary(4, $this->int32le->write($transaction->getVersion()));
0 ignored issues
show
Bug introduced by
The method writeRawBinary() does not seem to exist on object<BitWasp\Buffertools\Parser>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
131
132 66
        $flags = 0;
133 66
        $allowWitness = !($opt & self::NO_WITNESS);
134
        if ($allowWitness && $transaction->hasWitness()) {
135 66
            $flags |= 1;
136 66
        }
137 33
138
        if ($flags) {
139 66
            $parser->writeRawBinary(2, "\x00" . chr($flags));
0 ignored issues
show
Bug introduced by
The method writeRawBinary() does not seem to exist on object<BitWasp\Buffertools\Parser>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
140 66
        }
141 66
142 33
        $parser->appendBuffer(Buffertools::numToVarInt(count($transaction->getInputs())), true);
0 ignored issues
show
Bug introduced by
The method appendBuffer() does not seem to exist on object<BitWasp\Buffertools\Parser>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
143
        foreach ($transaction->getInputs() as $input) {
144 66
            $parser->appendBuffer($this->inputSerializer->serialize($input));
0 ignored issues
show
Bug introduced by
The method appendBuffer() does not seem to exist on object<BitWasp\Buffertools\Parser>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
145 66
        }
146
147 66
        $parser->appendBuffer(Buffertools::numToVarInt(count($transaction->getOutputs())), true);
0 ignored issues
show
Bug introduced by
The method appendBuffer() does not seem to exist on object<BitWasp\Buffertools\Parser>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
148 66
        foreach ($transaction->getOutputs() as $output) {
149 66
            $parser->appendBuffer($this->outputSerializer->serialize($output));
0 ignored issues
show
Bug introduced by
The method appendBuffer() does not seem to exist on object<BitWasp\Buffertools\Parser>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
150 33
        }
151 33
152
        if ($flags & 1) {
153 66
            foreach ($transaction->getWitnesses() as $witness) {
154
                $parser->appendBuffer($this->witnessSerializer->serialize($witness));
0 ignored issues
show
Bug introduced by
The method appendBuffer() does not seem to exist on object<BitWasp\Buffertools\Parser>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
155 66
            }
156
        }
157
158
        $parser->writeRawBinary(4, $this->uint32le->write($transaction->getLockTime()));
0 ignored issues
show
Bug introduced by
The method writeRawBinary() does not seem to exist on object<BitWasp\Buffertools\Parser>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
159
160
        return $parser->getBuffer();
161
    }
162
}
163