Completed
Pull Request — master (#348)
by thomas
70:36
created

TransactionSerializer::fromParser()   C

Complexity

Conditions 10
Paths 24

Size

Total Lines 61
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 27
CRAP Score 17.7036

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 27
cts 47
cp 0.5745
crap 17.7036
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
    public function __construct(TransactionInputSerializer $txInSer = null, TransactionOutputSerializer $txOutSer = null, ScriptWitnessSerializer $witSer = null)
37
    {
38
        $this->inputSerializer = $txInSer ?: new TransactionInputSerializer(new OutPointSerializer());
39 144
        $this->outputSerializer = $txOutSer ?: new TransactionOutputSerializer;
40
        $this->witnessSerializer = $witSer ?: new ScriptWitnessSerializer();
41 144
    }
42 144
43 144
    /**
44 144
     * @param Parser $parser
45
     * @return TransactionInterface
46
     */
47
    public function fromParser(Parser $parser)
48
    {
49
        $math = Bitcoin::getMath();
50 108
        $int32le = new Int32($math, ByteOrder::LE);
51
        $uint32le = new Uint32($math, ByteOrder::LE);
52 108
        $varint = new VarInt($math, ByteOrder::LE);
53 108
54 108
        $version = $int32le->read($parser);
55 108
56
        $vin = [];
57 108
        $vinCount = $varint->read($parser);
58
        for ($i = 0; $i < $vinCount; $i++) {
59 108
            $vin[] = $this->inputSerializer->fromParser($parser);
60 108
        }
61 108
62 108
        $vout = [];
63 72
        $flags = 0;
64
        if (count($vin) == 0) {
65 108
            $flags = (int) $varint->read($parser);
66 108
            if ($flags != 0) {
67 108
                $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
            $voutCount = $varint->read($parser);
79
            for ($i = 0; $i < $voutCount; $i++) {
80
                $vout[] = $this->outputSerializer->fromParser($parser);
81 108
            }
82 108
        }
83 108
84 72
        $vwit = [];
85
        if (($flags & 1)) {
86
            $flags ^= 1;
87 108
            $witCount = count($vin);
88 108
            for ($i = 0; $i < $witCount; $i++) {
89
                $vectorCount = $varint->read($parser);
90
                $vwit[] = $this->witnessSerializer->fromParser($parser, $vectorCount);
91
            }
92
        }
93
94
        if ($flags) {
95
            throw new \RuntimeException('Flags byte was 0');
96
        }
97 108
98
        $lockTime = $uint32le->read($parser);
99
100
        return new Transaction(
101 108
            $version,
102
            $vin,
103 108
            $vout,
104 72
            $vwit,
105 108
            $lockTime
106 108
        );
107 108
    }
108
109 72
    /**
110
     * @param string|BufferInterface $data
111
     * @return TransactionInterface
112
     */
113
    public function parse($data)
114
    {
115
        return $this->fromParser(new Parser($data));
116 75
    }
117
118 75
    /**
119
     * @param TransactionInterface $transaction
120
     * @return BufferInterface
121
     */
122
    public function serialize(TransactionInterface $transaction)
123
    {
124
        $math = Bitcoin::getMath();
125 27
        $int8le = new Int8($math, ByteOrder::LE);
126
        $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 27
132 27
        $binary = $int32le->write($transaction->getVersion());
133 27
        $flags = 0;
134
135 27
        if (!empty($transaction->getWitnesses())) {
136 27
            $flags |= 1;
137
        }
138 27
139 27
        if ($flags) {
140 18
            $binary .= $int8le->write(0);
141
            $binary .= $int8le->write($flags);
142 27
        }
143 27
144 27
        $binary .= $vector->write($transaction->getInputs());
145 18
        $binary .= $vector->write($transaction->getOutputs());
146
147 27
        if ($flags & 1) {
148 27
            foreach ($transaction->getWitnesses() as $witness) {
149
                $binary .= $witness->getBuffer()->getBinary();
150 27
            }
151 27
        }
152 27
153 18
        $binary .= $uint32le->write($transaction->getLockTime());
154 18
155
        return new Buffer($binary);
156 27
    }
157
}
158