Completed
Pull Request — master (#387)
by thomas
247:48 queued 175:25
created

Hasher::calculate()   C

Complexity

Conditions 11
Paths 14

Size

Total Lines 61
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 31
CRAP Score 11

Importance

Changes 0
Metric Value
cc 11
eloc 32
nc 14
nop 3
dl 0
loc 61
ccs 31
cts 31
cp 1
crap 11
rs 6.2318
c 0
b 0
f 0

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\Transaction\SignatureHash;
4
5
use BitWasp\Bitcoin\Bitcoin;
6
use BitWasp\Bitcoin\Crypto\Hash;
7
use BitWasp\Bitcoin\Transaction\Mutator\TxMutator;
8
use BitWasp\Buffertools\Buffer;
9
use BitWasp\Buffertools\BufferInterface;
10
use BitWasp\Buffertools\Buffertools;
11
use BitWasp\Bitcoin\Script\Script;
12
use BitWasp\Bitcoin\Script\ScriptInterface;
13
14
class Hasher extends SigHash
15
{
16
    /**
17
     * Calculate the hash of the current transaction, when you are looking to
18
     * spend $txOut, and are signing $inputToSign. The SigHashType defaults to
19
     * SIGHASH_ALL, though SIGHASH_SINGLE, SIGHASH_NONE, SIGHASH_ANYONECANPAY
20
     * can be used.
21
     *
22
     * @param ScriptInterface $txOutScript
23
     * @param int $inputToSign
24
     * @param int $sighashType
25 260
     * @return BufferInterface
26
     * @throws \Exception
27 260
     */
28 260
    public function calculate(ScriptInterface $txOutScript, $inputToSign, $sighashType = SigHashInterface::ALL)
29
    {
30
        $math = Bitcoin::getMath();
31
        $tx = new TxMutator($this->tx);
32
        $inputs = $tx->inputsMutator();
33
        $outputs = $tx->outputsMutator();
34
35
        // Default SIGHASH_ALL procedure: null all input scripts
36
        foreach ($inputs as $input) {
37
            $input->script(new Script);
38
        }
39
40
        $inputs[$inputToSign]->script($txOutScript);
41
42 254
        if (($sighashType & 31) === SigHashInterface::NONE) {
43
            // Set outputs to empty vector, and set sequence number of inputs to 0.
44 254
            $outputs->null();
45 254
46 254
            // Let the others update at will. Set sequence of inputs we're not signing to 0.
47 254
            foreach ($inputs as $i => $input) {
48
                if ($i !== $inputToSign) {
49
                    $input->sequence(0);
50 254
                }
51 254
            }
52 114
        } elseif (($sighashType & 31) === SigHashInterface::SINGLE) {
53
            // Resize output array to $inputToSign + 1, set remaining scripts to null,
54 254
            // and set sequence's to zero.
55
            $nOutput = $inputToSign;
56 248
            if ($nOutput >= count($this->tx->getOutputs())) {
57
                return Buffer::hex('0100000000000000000000000000000000000000000000000000000000000000', 32, $math);
58 6
            }
59
60
            // Resize, set to null
61 6
            $outputs->slice(0, $nOutput + 1);
62 6
            for ($i = 0; $i < $nOutput; $i++) {
63 6
                $outputs[$i]->null();
64 2
            }
65 2
66 248
            // Let the others update at will. Set sequence of inputs we're not signing to 0
67
            foreach ($inputs as $i => $input) {
68
                if ($i !== $inputToSign) {
69 12
                    $input->sequence(0);
70 12
                }
71 6
            }
72
        }
73
74
        // This can happen regardless of whether it's ALL, NONE, or SINGLE
75 12
        if (($sighashType & SigHashInterface::ANYONECANPAY) > 0) {
76 12
            $input = $inputs[$inputToSign]->done();
77 6
            $inputs->null()->add($input);
78 2
        }
79
80
        return Hash::sha256d(
81 12
            Buffertools::concat(
82 12
                $tx
83 10
                    ->done()
84 2
                    ->getBuffer(),
85 4
                Buffertools::flipBytes(Buffer::int($sighashType, 4, $math))
0 ignored issues
show
Bug introduced by
It seems like \BitWasp\Buffertools\Buf...sighashType, 4, $math)) targeting BitWasp\Buffertools\Buffertools::flipBytes() can also be of type string; however, BitWasp\Buffertools\Buffertools::concat() does only seem to accept object<BitWasp\Buffertools\BufferInterface>, maybe add an additional type check?

This check looks at variables that 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...
86 4
            )
87
        );
88
    }
89
}
90