Completed
Pull Request — master (#412)
by thomas
246:53 queued 176:30
created

OutputScriptFactory::payToPubKeyHash()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

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