Completed
Pull Request — master (#387)
by thomas
249:34 queued 246:57
created

Hasher::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
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
     * @return BufferInterface
26
     * @throws \Exception
27
     */
28 254
    public function calculate(ScriptInterface $txOutScript, $inputToSign, $sighashType = SigHashInterface::ALL)
29
    {
30 254
        $math = Bitcoin::getMath();
31 254
        $tx = new TxMutator($this->tx);
32 254
        $inputs = $tx->inputsMutator();
33 254
        $outputs = $tx->outputsMutator();
34
35
        // Default SIGHASH_ALL procedure: null all input scripts
36 254
        foreach ($inputs as $input) {
37 254
            $input->script(new Script);
38 114
        }
39
40 254
        $inputs[$inputToSign]->script($txOutScript);
41
42 248
        if (($sighashType & 31) === SigHashInterface::NONE) {
43
            // Set outputs to empty vector, and set sequence number of inputs to 0.
44 6
            $outputs->null();
45
46
            // Let the others update at will. Set sequence of inputs we're not signing to 0.
47 6
            foreach ($inputs as $i => $input) {
48 6
                if ($i !== $inputToSign) {
49 6
                    $input->sequence(0);
50 2
                }
51 2
            }
52 248
        } elseif (($sighashType & 31) === SigHashInterface::SINGLE) {
53
            // Resize output array to $inputToSign + 1, set remaining scripts to null,
54
            // and set sequence's to zero.
55 12
            $nOutput = $inputToSign;
56 12
            if ($nOutput >= count($this->tx->getOutputs())) {
57 6
                return Buffer::hex('0100000000000000000000000000000000000000000000000000000000000000', 32, $math);
58
            }
59
60
            // Resize, set to null
61 12
            $outputs->slice(0, $nOutput + 1);
62 12
            for ($i = 0; $i < $nOutput; $i++) {
63 6
                $outputs[$i]->null();
64 2
            }
65
66
            // Let the others update at will. Set sequence of inputs we're not signing to 0
67 12
            foreach ($inputs as $i => $input) {
68 12
                if ($i !== $inputToSign) {
69 10
                    $input->sequence(0);
70 2
                }
71 4
            }
72 4
        }
73
74
        // This can happen regardless of whether it's ALL, NONE, or SINGLE
75 248
        if (($sighashType & SigHashInterface::ANYONECANPAY) > 0) {
76 10
            $input = $inputs[$inputToSign]->done();
77 10
            $inputs->null()->add($input);
78 4
        }
79
80 248
        return Hash::sha256d(
81 248
            Buffertools::concat(
82
                $tx
83 248
                    ->done()
84 248
                    ->getBuffer(),
85 248
                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 112
            )
87 112
        );
88
    }
89
}
90