Completed
Pull Request — master (#239)
by thomas
31:39 queued 14:06
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 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 61
ccs 28
cts 48
cp 0.5833
rs 6.4757
cc 10
eloc 41
nc 24
nop 1
crap 17.2354

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\Collection\Transaction\TransactionInputCollection;
7
use BitWasp\Bitcoin\Collection\Transaction\TransactionOutputCollection;
8
use BitWasp\Bitcoin\Collection\Transaction\TransactionWitnessCollection;
9
use BitWasp\Bitcoin\Serializer\Script\ScriptWitnessSerializer;
10
use BitWasp\Bitcoin\Transaction\Transaction;
11
use BitWasp\Bitcoin\Transaction\TransactionInterface;
12
use BitWasp\Buffertools\Buffer;
13
use BitWasp\Buffertools\BufferInterface;
14
use BitWasp\Buffertools\ByteOrder;
15
use BitWasp\Buffertools\Parser;
16
use BitWasp\Buffertools\Types\Int32;
17
use BitWasp\Buffertools\Types\Int8;
18
use BitWasp\Buffertools\Types\Uint32;
19
use BitWasp\Buffertools\Types\VarInt;
20
use BitWasp\Buffertools\Types\Vector;
21
22
class TransactionSerializer
23
{
24
    /**
25
     *
26
     */
27 300
    public function __construct()
28
    {
29 300
        $this->inputSerializer = new TransactionInputSerializer(new OutPointSerializer());
0 ignored issues
show
Bug introduced by
The property inputSerializer does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
30 300
        $this->outputSerializer = new TransactionOutputSerializer;
0 ignored issues
show
Bug introduced by
The property outputSerializer does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
31 300
        $this->witnessSerializer = new ScriptWitnessSerializer();
0 ignored issues
show
Bug introduced by
The property witnessSerializer does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
32 300
    }
33
34
    /**
35
     * @param Parser $parser
36
     * @return Transaction
37
     */
38 228
    public function fromParser(Parser $parser)
39
    {
40 228
        $math = Bitcoin::getMath();
41 228
        $int32le = new Int32($math, ByteOrder::LE);
42 228
        $uint32le = new Uint32($math, ByteOrder::LE);
43 228
        $varint = new VarInt($math, ByteOrder::LE);
44
45 228
        $version = $int32le->read($parser);
46
47 228
        $vin = [];
48 228
        $vinCount = $varint->read($parser);
49 228
        for ($i = 0; $i < $vinCount; $i++) {
50 228
            $vin[] = $this->inputSerializer->fromParser($parser);
51 228
        }
52
53 228
        $vout = [];
54 228
        $flags = 0;
55 228
        if (count($vin) == 0) {
56
            $flags = (int) $varint->read($parser);
57
            if ($flags != 0) {
58
                $vinCount = $varint->read($parser);
59
                for ($i = 0; $i < $vinCount; $i++) {
60
                    $vin[] = $this->inputSerializer->fromParser($parser);
61
                }
62
63
                $voutCount = $varint->read($parser);
64
                for ($i = 0; $i < $voutCount; $i++) {
65
                    $vout[] = $this->outputSerializer->fromParser($parser);
66
                }
67
            }
68
        } else {
69 228
            $voutCount = $varint->read($parser);
70 228
            for ($i = 0; $i < $voutCount; $i++) {
71 228
                $vout[] = $this->outputSerializer->fromParser($parser);
72 228
            }
73
        }
74
75 228
        $vwit = [];
76 228
        if (($flags & 1)) {
77
            $flags ^= 1;
78
            $witCount = count($vin);
79
            for ($i = 0; $i < $witCount; $i++) {
80
                $vectorCount = $varint->read($parser);
81
                $vwit[] = $this->witnessSerializer->fromParser($parser, $vectorCount);
82
            }
83
        }
84
85 228
        if ($flags) {
86
            throw new \RuntimeException('Flags byte was 0');
87
        }
88
89 228
        $lockTime = $uint32le->read($parser);
90
91 228
        return new Transaction(
92 228
            $version,
93 228
            new TransactionInputCollection($vin),
94 228
            new TransactionOutputCollection($vout),
95 228
            new TransactionWitnessCollection($vwit),
96
            $lockTime
97 228
        );
98
    }
99
100
    /**
101
     * @param string|BufferInterface $data
102
     * @return Transaction
103
     */
104 156
    public function parse($data)
105
    {
106 156
        return $this->fromParser(new Parser($data));
0 ignored issues
show
Bug introduced by
It seems like $data defined by parameter $data on line 104 can also be of type object<BitWasp\Buffertools\BufferInterface>; however, BitWasp\Buffertools\Parser::__construct() does only seem to accept null|string|object<BitWasp\Buffertools\Buffer>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
107
    }
108
109
    /**
110
     * @param TransactionInterface $transaction
111
     * @return Buffer
112
     */
113 54
    public function serialize(TransactionInterface $transaction)
114
    {
115 54
        $math = Bitcoin::getMath();
116 54
        $int8le = new Int8($math, ByteOrder::LE);
117 54
        $int32le = new Int32($math, ByteOrder::LE);
118 54
        $uint32le = new Uint32($math, ByteOrder::LE);
119 54
        $varint = new VarInt($math, ByteOrder::LE);
120 54
        $vector = new Vector($varint, function () {
121 54
        });
122
123 54
        $binary = $int32le->write($transaction->getVersion());
124 54
        $flags = 0;
125
126 54
        if (!$transaction->getWitnesses()->isNull()) {
127 54
            $flags |= 1;
128 54
        }
129
130 54
        if ($flags) {
131 54
            $binary .= $int8le->write(0);
132 54
            $binary .= $int8le->write($flags);
133 54
        }
134
135 54
        $binary .= $vector->write($transaction->getInputs()->all());
136 54
        $binary .= $vector->write($transaction->getOutputs()->all());
137
138 54
        if ($flags & 1) {
139 54
            foreach ($transaction->getWitnesses() as $witness) {
140 54
                $binary .= $witness->getBuffer()->getBinary();
141 54
            }
142 54
        }
143
144 54
        $binary .= $uint32le->write($transaction->getLockTime());
145
146 54
        return new Buffer($binary);
147
    }
148
}
149