Completed
Pull Request — master (#446)
by thomas
105:00 queued 101:56
created

OutputScriptFactory::p2pkh()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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