Completed
Pull Request — master (#248)
by thomas
58:32 queued 33:01
created

Multisig::__construct()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 30
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 6.1215

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 30
ccs 17
cts 20
cp 0.85
rs 8.439
cc 6
eloc 18
nc 6
nop 1
crap 6.1215
1
<?php
2
3
namespace BitWasp\Bitcoin\Script\ScriptInfo;
4
5
use BitWasp\Bitcoin\Crypto\EcAdapter\Key\PublicKeyInterface;
6
use BitWasp\Bitcoin\Key\PublicKeyFactory;
7
use BitWasp\Bitcoin\Script\Classifier\OutputClassifier;
8
use BitWasp\Bitcoin\Script\Opcodes;
9
use BitWasp\Bitcoin\Script\Script;
10
use BitWasp\Bitcoin\Script\ScriptFactory;
11
use BitWasp\Bitcoin\Script\ScriptInterface;
12
use BitWasp\Bitcoin\Signature\TransactionSignatureInterface;
13
14
class Multisig implements ScriptInfoInterface
15
{
16
    /**
17
     * @var int
18
     */
19
    private $m;
20
21
    /**
22
     * @var int
23
     */
24
    private $n;
25
26
    /**
27
     * @var ScriptInterface
28
     */
29
    private $script;
30
31
    /**
32
     * @var PublicKeyInterface[]
33
     */
34
    private $keys = [];
35
36
    /**
37
     * @param ScriptInterface $script
38
     */
39 66
    public function __construct(ScriptInterface $script)
40
    {
41 66
        $publicKeys = [];
42 66
        $parse = $script->getScriptParser()->decode();
43 66
        if (count($parse) < 4) {
44
            throw new \InvalidArgumentException('Malformed multisig script');
45
        }
46
47 66
        $mCode = $parse[0]->getOp();
48 66
        $nCode = $parse[count($parse) - 2]->getOp();
49
50 66
        $this->m = (int) $mCode - Opcodes::OP_1 + 1 ;
0 ignored issues
show
Documentation Bug introduced by
The property $m was declared of type integer, but (int) $mCode - \BitWasp\...cript\Opcodes::OP_1 + 1 is of type double. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
51 66
        foreach (array_slice($parse, 1, -2) as $key) {
52
            /** @var \BitWasp\Bitcoin\Script\Parser\Operation $key */
53 66
            if (!$key->isPush()) {
54
                throw new \RuntimeException('Malformed multisig script');
55
            }
56
57 66
            $publicKeys[] = PublicKeyFactory::fromHex($key->getData());
58 66
        }
59
60 66
        $n = (int) $nCode - Opcodes::OP_1 + 1 ;
61 66
        $this->n = count($publicKeys);
62 66
        if ($this->n === 0 || $this->n !== $n) {
63
            throw new \LogicException('No public keys found in script');
64
        }
65
66 66
        $this->script = $script;
67 66
        $this->keys = $publicKeys;
68 66
    }
69
70
    /**
71
     * @return int
72
     */
73 36
    public function getRequiredSigCount()
74
    {
75 36
        return $this->m;
76
    }
77
78
    /**
79
     * @return int
80
     */
81 30
    public function getKeyCount()
82
    {
83 30
        return $this->n;
84
    }
85
86
    /**
87
     * @return string
88
     */
89 36
    public function classification()
90
    {
91 36
        return OutputClassifier::MULTISIG;
92
    }
93
94
    /**
95
     * @param PublicKeyInterface $publicKey
96
     * @return bool
97
     */
98
    public function checkInvolvesKey(PublicKeyInterface $publicKey)
99
    {
100
        $binary = $publicKey->getBinary();
101
        foreach ($this->keys as $key) {
102
            if ($key->getBinary() === $binary) {
103
                return true;
104
            }
105
        }
106
107
        return false;
108
    }
109
110
    /**
111
     * @return \BitWasp\Bitcoin\Crypto\EcAdapter\Key\PublicKeyInterface[]
112
     */
113 66
    public function getKeys()
114
    {
115 66
        return $this->keys;
116
    }
117
118
    /**
119
     * @param TransactionSignatureInterface[] $signatures
120
     * @param PublicKeyInterface[] $publicKeys
121
     * @return Script|ScriptInterface
122
     */
123 18
    public function makeScriptSig(array $signatures = [], array $publicKeys = [])
124
    {
125 18
        $newScript = new Script();
126 18
        if (count($signatures) > 0) {
127 18
            $sequence = [Opcodes::OP_0];
128 18
            foreach ($signatures as $sig) {
129 18
                $sequence[] = $sig->getBuffer();
130 18
            }
131
132 18
            $newScript = ScriptFactory::sequence($sequence);
133 18
        }
134
135 18
        return $newScript;
136
    }
137
}
138