Completed
Pull Request — master (#446)
by thomas
228:15 queued 224:06
created

TransactionSerializer::serialize()   C

Complexity

Conditions 8
Paths 32

Size

Total Lines 35
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 8

Importance

Changes 0
Metric Value
cc 8
eloc 20
nc 32
nop 2
dl 0
loc 35
ccs 23
cts 23
cp 1
crap 8
rs 5.3846
c 0
b 0
f 0
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\Parser;
11
12
class TransactionSerializer implements TransactionSerializerInterface
13
{
14
    const NO_WITNESS = 1;
15
16
    /**
17
     * @var \BitWasp\Buffertools\Types\Int32
18
     */
19
    private $int32le;
20
21
    /**
22
     * @var \BitWasp\Buffertools\Types\Uint32
23
     */
24
    private $uint32le;
25
26
    /**
27
     * @var \BitWasp\Buffertools\Types\VarInt
28
     */
29
    private $varint;
30
31
    /**
32
     * @var TransactionInputSerializer
33
     */
34
    private $inputSerializer;
35
36 270
    /**
37
     * @var TransactionOutputSerializer
38 270
     */
39 270
    private $outputSerializer;
40 270
41 270
    /**
42
     * @var ScriptWitnessSerializer
43
     */
44
    private $witnessSerializer;
45
46
    public function __construct(TransactionInputSerializer $inputSerializer = null, TransactionOutputSerializer $outputSerializer = null, ScriptWitnessSerializer $witnessSerializer = null)
47 186
    {
48
        $this->int32le = Types::int32le();
49 186
        $this->uint32le = Types::uint32le();
50 186
        $this->varint = Types::varint();
51 186
52 186
        $this->inputSerializer = $inputSerializer ?: new TransactionInputSerializer(new OutPointSerializer());
53
        $this->outputSerializer = $outputSerializer ?: new TransactionOutputSerializer;
54 186
        $this->witnessSerializer = $witnessSerializer ?: new ScriptWitnessSerializer();
55
    }
56 186
57 186
    /**
58 186
     * @param Parser $parser
59 186
     * @return TransactionInterface
60 93
     */
61
    public function fromParser(Parser $parser)
62 186
    {
63 186
        $version = $this->int32le->read($parser);
64 186
65
        $vin = [];
66
        $vinCount = $this->varint->read($parser);
67
        for ($i = 0; $i < $vinCount; $i++) {
68
            $vin[] = $this->inputSerializer->fromParser($parser);
69
        }
70
71
        $vout = [];
72
        $flags = 0;
73
        if (count($vin) === 0) {
74
            $flags = (int) $this->varint->read($parser);
75
            if ($flags !== 0) {
76
                $vinCount = $this->varint->read($parser);
77
                for ($i = 0; $i < $vinCount; $i++) {
78 186
                    $vin[] = $this->inputSerializer->fromParser($parser);
79 186
                }
80 186
81 93
                $voutCount = $this->varint->read($parser);
82
                for ($i = 0; $i < $voutCount; $i++) {
83
                    $vout[] = $this->outputSerializer->fromParser($parser);
84 186
                }
85 186
            }
86
        } else {
87
            $voutCount = $this->varint->read($parser);
88
            for ($i = 0; $i < $voutCount; $i++) {
89
                $vout[] = $this->outputSerializer->fromParser($parser);
90
            }
91
        }
92
93
        $vwit = [];
94 186
        if (($flags & 1)) {
95
            $flags ^= 1;
96
            $witCount = count($vin);
97
            for ($i = 0; $i < $witCount; $i++) {
98 186
                $vectorCount = $this->varint->read($parser);
99
                $vwit[] = $this->witnessSerializer->fromParser($parser, $vectorCount);
100 186
            }
101 93
        }
102 93
103 93
        if ($flags) {
104 93
            throw new \RuntimeException('Flags byte was 0');
105
        }
106 93
107
        $lockTime = $this->uint32le->read($parser);
108
109
        return new Transaction($version, $vin, $vout, $vwit, $lockTime);
110
    }
111
112
    /**
113 120
     * @param string|BufferInterface $data
114
     * @return TransactionInterface
115 120
     */
116
    public function parse($data)
117
    {
118
        return $this->fromParser(new Parser($data));
119
    }
120
121
    /**
122 66
     * @param TransactionInterface $transaction
123
     * @param int $opt
124 66
     * @return BufferInterface
125 66
     */
126 66
    public function serialize(TransactionInterface $transaction, $opt = 0)
127 66
    {
128 66
        $parser = new Parser();
129 66
        $parser->appendBinary($this->int32le->write($transaction->getVersion()));
0 ignored issues
show
Bug introduced by
The method appendBinary() 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...
130 66
131
        $flags = 0;
132 66
        $allowWitness = !($opt & self::NO_WITNESS);
133 66
        if ($allowWitness && $transaction->hasWitness()) {
134
            $flags |= 1;
135 66
        }
136 66
137 33
        if ($flags) {
138
            $parser->appendBinary(pack("CC", 0, $flags));
0 ignored issues
show
Bug introduced by
The method appendBinary() 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...
139 66
        }
140 66
141 66
        $parser->appendBinary($this->varint->write(count($transaction->getInputs())), true);
0 ignored issues
show
Bug introduced by
The method appendBinary() 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...
142 33
        foreach ($transaction->getInputs() as $input) {
143
            $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...
144 66
        }
145 66
146
        $parser->appendBinary($this->varint->write(count($transaction->getOutputs())), true);
0 ignored issues
show
Bug introduced by
The method appendBinary() 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...
147 66
        foreach ($transaction->getOutputs() as $output) {
148 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...
149 66
        }
150 33
151 33
        if ($flags & 1) {
152
            foreach ($transaction->getWitnesses() as $witness) {
153 66
                $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...
154
            }
155 66
        }
156
157
        $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...
158
159
        return $parser->getBuffer();
160
    }
161
}
162