Completed
Pull Request — 0.0.35 (#657)
by thomas
18:35 queued 01:31
created

OutputScriptFactory::witnessKeyHash()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 8
ccs 2
cts 2
cp 1
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace BitWasp\Bitcoin\Script\Factory;
4
5
use BitWasp\Bitcoin\Address\AddressInterface;
6
use BitWasp\Bitcoin\Address\ScriptHashAddress;
7
use BitWasp\Bitcoin\Crypto\EcAdapter\Impl\PhpEcc\Key\PublicKey;
8
use BitWasp\Bitcoin\Crypto\EcAdapter\Key\PublicKeyInterface;
9
use BitWasp\Bitcoin\Script\Opcodes;
10
use BitWasp\Bitcoin\Script\ScriptFactory;
11
use BitWasp\Bitcoin\Script\ScriptInterface;
12
use BitWasp\Buffertools\Buffer;
13
use BitWasp\Buffertools\BufferInterface;
14
use BitWasp\Buffertools\Buffertools;
15
16
class OutputScriptFactory
17
{
18
    /**
19
     * @param PublicKeyInterface $publicKey
20
     * @return ScriptInterface
21
     */
22 7
    public function p2pk(PublicKeyInterface $publicKey)
23
    {
24 7
        return $this->payToPubKey($publicKey);
25 2
    }
26 7
27
    /**
28
     * @param BufferInterface $pubKeyHash
29
     * @return ScriptInterface
30
     */
31
    public function p2pkh(BufferInterface $pubKeyHash)
32
    {
33 1
        return $this->payToPubKeyHash($pubKeyHash);
34
    }
35 1
36
    /**
37
     * @param BufferInterface $scriptHash
38
     * @return ScriptInterface
39
     */
40
    public function p2sh(BufferInterface $scriptHash)
41
    {
42 3
        return $this->payToScriptHash($scriptHash);
43
    }
44 3
45
    /**
46
     * @param BufferInterface $witnessScriptHash
47
     * @return ScriptInterface
48
     */
49
    public function p2wsh(BufferInterface $witnessScriptHash)
50
    {
51 22
        return $this->witnessScriptHash($witnessScriptHash);
52
    }
53 22
54
    /**
55
     * @param BufferInterface $witnessKeyHash
56
     * @return ScriptInterface
57
     */
58
    public function p2wkh(BufferInterface $witnessKeyHash)
59
    {
60 4
        return $this->witnessKeyHash($witnessKeyHash);
61
    }
62 4
    /**
63
     * Create a Pay to pubkey output
64
     *
65
     * @param PublicKeyInterface  $publicKey
66
     * @return ScriptInterface
67
     */
68
    public function payToPubKey(PublicKeyInterface $publicKey)
69 2
    {
70
        return ScriptFactory::sequence([$publicKey->getBuffer(), Opcodes::OP_CHECKSIG]);
71 2
    }
72
73
    /**
74
     * Create a P2PKH output script
75
     *
76
     * @param BufferInterface $pubKeyHash
77
     * @return ScriptInterface
78
     */
79 5
    public function payToPubKeyHash(BufferInterface $pubKeyHash)
80
    {
81 5
        if ($pubKeyHash->getSize() !== 20) {
82
            throw new \RuntimeException('Public key hash must be exactly 20 bytes');
83
        }
84
85
        return ScriptFactory::sequence([Opcodes::OP_DUP, Opcodes::OP_HASH160, $pubKeyHash, Opcodes::OP_EQUALVERIFY, Opcodes::OP_CHECKSIG]);
86
    }
87
88
    /**
89
    /**
90 49
     * Create a P2SH output script
91
     *
92 49
     * @param BufferInterface $scriptHash
93
     * @return ScriptInterface
94
     */
95
    public function payToScriptHash(BufferInterface $scriptHash)
96 49
    {
97
        if ($scriptHash->getSize() !== 20) {
98
            throw new \RuntimeException('P2SH scriptHash must be exactly 20 bytes');
99
        }
100
101
        return ScriptFactory::sequence([Opcodes::OP_HASH160, $scriptHash, Opcodes::OP_EQUAL]);
102
    }
103
104
    /**
105
     * @param int $m
106 31
     * @param PublicKeyInterface[] $keys
107
     * @param bool|true $sort
108 31
     * @return ScriptInterface
109
     */
110
    public function multisig($m, array $keys = [], $sort = true)
111
    {
112 31
        return self::multisigKeyBuffers($m, array_map(function (PublicKeyInterface $key) {
113
            return $key->getBuffer();
114
        }, $keys), $sort);
115
    }
116
117
    /**
118
     * @param int $m
119
     * @param BufferInterface[] $keys
120
     * @param bool|true $sort
121
     * @return ScriptInterface
122
     */
123 16
    public function multisigKeyBuffers($m, array $keys = [], $sort = true)
124 16
    {
125 16
        $n = count($keys);
126
        if ($m < 0) {
127
            throw new \LogicException('Number of signatures cannot be less than zero');
128
        }
129
130
        if ($m > $n) {
131
            throw new \LogicException('Required number of sigs exceeds number of public keys');
132
        }
133
134 20
        if ($n > 20) {
135
            throw new \LogicException('Number of public keys is greater than 16');
136 20
        }
137 20
138
        if ($sort) {
139
            $keys = Buffertools::sort($keys);
140
        }
141 20
142
        $new = ScriptFactory::create();
143
        $new->int($m);
144
        foreach ($keys as $key) {
145 20
            if ($key->getSize() != PublicKey::LENGTH_COMPRESSED && $key->getSize() != PublicKey::LENGTH_UNCOMPRESSED) {
146
                throw new \RuntimeException("Invalid length for public key buffer");
147
            }
148
149 20
            $new->push($key);
150 6
        }
151
152
        return $new->int($n)->op('OP_CHECKMULTISIG')->getScript();
153 20
    }
154 20
155 20
    /**
156 20
     * @param BufferInterface $keyHash
157
     * @return ScriptInterface
158
     */
159
    public function witnessKeyHash(BufferInterface $keyHash)
160 20
    {
161
        if ($keyHash->getSize() !== 20) {
162
            throw new \RuntimeException('witness key-hash should be 20 bytes');
163 20
        }
164
165
        return ScriptFactory::sequence([Opcodes::OP_0, $keyHash]);
166
    }
167
168
    /**
169
     * @param BufferInterface $scriptHash
170 2
     * @return ScriptInterface
171
     */
172 2
    public function witnessScriptHash(BufferInterface $scriptHash)
173
    {
174
        if ($scriptHash->getSize() !== 32) {
175
            throw new \RuntimeException('witness script-hash should be 32 bytes');
176 2
        }
177
178
        return ScriptFactory::sequence([Opcodes::OP_0, $scriptHash]);
179
    }
180
181
    /**
182
     * @param BufferInterface $commitment
183 5
     * @return ScriptInterface
184
     */
185 5
    public function witnessCoinbaseCommitment(BufferInterface $commitment)
186
    {
187
        if ($commitment->getSize() !== 32) {
188
            throw new \RuntimeException('Witness commitment hash must be exactly 32-bytes');
189 5
        }
190
191
        return ScriptFactory::sequence([
192
            Opcodes::OP_RETURN,
193
            new Buffer("\xaa\x21\xa9\xed" . $commitment->getBinary())
194
        ]);
195
    }
196
}
197