Completed
Pull Request — master (#348)
by thomas
72:50 queued 67:29
created

TransactionSerializer::fromParser()   C

Complexity

Conditions 10
Paths 24

Size

Total Lines 61
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 28
CRAP Score 17.2354

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 10
eloc 41
c 1
b 0
f 0
nc 24
nop 1
dl 0
loc 61
ccs 28
cts 48
cp 0.5833
crap 17.2354
rs 6.4757

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace BitWasp\Bitcoin\Serializer\Transaction;
4
5
use BitWasp\Bitcoin\Bitcoin;
6
use BitWasp\Bitcoin\Serializer\Script\ScriptWitnessSerializer;
7
use BitWasp\Bitcoin\Transaction\Transaction;
8
use BitWasp\Bitcoin\Transaction\TransactionInterface;
9
use BitWasp\Buffertools\Buffer;
10
use BitWasp\Buffertools\BufferInterface;
11
use BitWasp\Buffertools\ByteOrder;
12
use BitWasp\Buffertools\Parser;
13
use BitWasp\Buffertools\Types\Int32;
14
use BitWasp\Buffertools\Types\Int8;
15
use BitWasp\Buffertools\Types\Uint32;
16
use BitWasp\Buffertools\Types\VarInt;
17
use BitWasp\Buffertools\Types\Vector;
18
19
class TransactionSerializer implements TransactionSerializerInterface
20
{
21
    /**
22
     * @var TransactionInputSerializer
23
     */
24
    private $inputSerializer;
25
26
    /**
27
     * @var TransactionOutputSerializer
28
     */
29
    private $outputSerializer;
30
31
    /**
32
     * @var ScriptWitnessSerializer
33
     */
34
    private $witnessSerializer;
35
36 144
    public function __construct(TransactionInputSerializer $txInSer = null, TransactionOutputSerializer $txOutSer = null, ScriptWitnessSerializer $witSer = null)
37
    {
38 144
        $this->inputSerializer = $txInSer ?: new TransactionInputSerializer(new OutPointSerializer());
39 144
        $this->outputSerializer = $txOutSer ?: new TransactionOutputSerializer;
40 144
        $this->witnessSerializer = $witSer ?: new ScriptWitnessSerializer();
41 144
    }
42
43
    /**
44
     * @param Parser $parser
45
     * @return TransactionInterface
46
     */
47 108
    public function fromParser(Parser $parser)
48
    {
49 108
        $math = Bitcoin::getMath();
50 108
        $int32le = new Int32($math, ByteOrder::LE);
51 108
        $uint32le = new Uint32($math, ByteOrder::LE);
52 108
        $varint = new VarInt($math, ByteOrder::LE);
53
54 108
        $version = $int32le->read($parser);
55
56 108
        $vin = [];
57 108
        $vinCount = $varint->read($parser);
58 108
        for ($i = 0; $i < $vinCount; $i++) {
59 108
            $vin[] = $this->inputSerializer->fromParser($parser);
60 72
        }
61
62 108
        $vout = [];
63 108
        $flags = 0;
64 108
        if (count($vin) == 0) {
65
            $flags = (int) $varint->read($parser);
66
            if ($flags != 0) {
67
                $vinCount = $varint->read($parser);
68
                for ($i = 0; $i < $vinCount; $i++) {
69
                    $vin[] = $this->inputSerializer->fromParser($parser);
70
                }
71
72
                $voutCount = $varint->read($parser);
73
                for ($i = 0; $i < $voutCount; $i++) {
74
                    $vout[] = $this->outputSerializer->fromParser($parser);
75
                }
76
            }
77
        } else {
78 108
            $voutCount = $varint->read($parser);
79 108
            for ($i = 0; $i < $voutCount; $i++) {
80 108
                $vout[] = $this->outputSerializer->fromParser($parser);
81 72
            }
82
        }
83
84 108
        $vwit = [];
85 108
        if (($flags & 1)) {
86
            $flags ^= 1;
87
            $witCount = count($vin);
88
            for ($i = 0; $i < $witCount; $i++) {
89
                $vectorCount = $varint->read($parser);
90
                $vwit[] = $this->witnessSerializer->fromParser($parser, $vectorCount);
91
            }
92
        }
93
94 108
        if ($flags) {
95
            throw new \RuntimeException('Flags byte was 0');
96
        }
97
98 108
        $lockTime = $uint32le->read($parser);
99
100 108
        return new Transaction(
101 72
            $version,
102 72
            $vin,
103 72
            $vout,
104 72
            $vwit,
105
            $lockTime
106 72
        );
107
    }
108
109
    /**
110
     * @param string|BufferInterface $data
111
     * @return TransactionInterface
112
     */
113 75
    public function parse($data)
114
    {
115 75
        return $this->fromParser(new Parser($data));
116
    }
117
118
    /**
119
     * @param TransactionInterface $transaction
120
     * @return BufferInterface
121
     */
122 27
    public function serialize(TransactionInterface $transaction)
123
    {
124 27
        $math = Bitcoin::getMath();
125 27
        $int8le = new Int8($math, ByteOrder::LE);
126 27
        $int32le = new Int32($math, ByteOrder::LE);
127 27
        $uint32le = new Uint32($math, ByteOrder::LE);
128 27
        $varint = new VarInt($math, ByteOrder::LE);
129 27
        $vector = new Vector($varint, function () {
130 27
        });
131
132 27
        $binary = $int32le->write($transaction->getVersion());
133 27
        $flags = 0;
134
135 27
        if (!empty($transaction->getWitnesses())) {
136 27
            $flags |= 1;
137 18
        }
138
139 27
        if ($flags) {
140 27
            $binary .= $int8le->write(0);
141 27
            $binary .= $int8le->write($flags);
142 18
        }
143
144 27
        $binary .= $vector->write($transaction->getInputs());
145 27
        $binary .= $vector->write($transaction->getOutputs());
146
147 27
        if ($flags & 1) {
148 27
            foreach ($transaction->getWitnesses() as $witness) {
149 27
                $binary .= $witness->getBuffer()->getBinary();
150 18
            }
151 18
        }
152
153 27
        $binary .= $uint32le->write($transaction->getLockTime());
154
155 27
        return new Buffer($binary);
156
    }
157
}
158