Completed
Pull Request — master (#392)
by thomas
190:09 queued 117:15
created

OutputScriptFactory::classify()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 0
cts 2
cp 0
crap 2
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\Classifier\OutputClassifier;
9
use BitWasp\Bitcoin\Script\Opcodes;
10
use BitWasp\Bitcoin\Script\ScriptFactory;
11
use BitWasp\Bitcoin\Script\ScriptInterface;
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
    public function payToAddress(AddressInterface $address)
22
    {
23
        return $address instanceof ScriptHashAddress
24
            ? ScriptFactory::sequence([Opcodes::OP_HASH160, $address->getHash(), Opcodes::OP_EQUAL])
25
            : ScriptFactory::sequence([Opcodes::OP_DUP, Opcodes::OP_HASH160, $address->getHash(), Opcodes::OP_EQUALVERIFY, Opcodes::OP_CHECKSIG]);
26
    }
27
28
    /**
29 96
     * Create a Pay to pubkey output
30
     *
31 64
     * @param PublicKeyInterface  $publicKey
32 40
     * @return ScriptInterface
33 96
     */
34
    public function payToPubKey(PublicKeyInterface $publicKey)
35
    {
36
        return ScriptFactory::sequence([$publicKey->getBuffer(), Opcodes::OP_CHECKSIG]);
37
    }
38
39
    /**
40
     * Create a P2PKH output script
41
     *
42 30
     * @param BufferInterface $pubKeyHash
43
     * @return ScriptInterface
44 30
     */
45
    public function payToPubKeyHash(BufferInterface $pubKeyHash)
46
    {
47
        if ($pubKeyHash->getSize() !== 20) {
48
            throw new \RuntimeException('Public key hash must be exactly 20 bytes');
49
        }
50
51
        return ScriptFactory::sequence([Opcodes::OP_DUP, Opcodes::OP_HASH160, $pubKeyHash, Opcodes::OP_EQUALVERIFY, Opcodes::OP_CHECKSIG]);
52
    }
53 18
54
    /**
55 18
     * Create a P2PKH output script from a hash.
56
     *
57
     * @param BufferInterface $hash
58
     * @return ScriptInterface
59
     */
60
    public function payToPubKeyHashFromHash(BufferInterface $hash)
61
    {
62
        if ($hash->getSize() !== 20) {
63
            throw new \RuntimeException('pub-key-hash should be 20 bytes');
64 36
        }
65
66 36
        return ScriptFactory::sequence([Opcodes::OP_DUP, Opcodes::OP_HASH160, $hash, Opcodes::OP_EQUALVERIFY, Opcodes::OP_CHECKSIG]);
67
    }
68
69
    /**
70 36
     * Create a P2SH output script
71
     *
72
     * @param BufferInterface $scriptHash
73
     * @return ScriptInterface
74
     */
75
    public function payToScriptHash(BufferInterface $scriptHash)
76
    {
77
        if ($scriptHash->getSize() !== 20) {
78
            throw new \RuntimeException('P2SH scriptHash must be exactly 20 bytes');
79 90
        }
80
81 90
        return ScriptFactory::sequence([Opcodes::OP_HASH160, $scriptHash, Opcodes::OP_EQUAL]);
82
    }
83
84
    /**
85
     * @param int $m
86
     * @param PublicKeyInterface[] $keys
87
     * @param bool|true $sort
88
     * @return ScriptInterface
89
     */
90
    public function multisig($m, array $keys = [], $sort = true)
91
    {
92
        $n = count($keys);
93
        if ($m < 0) {
94
            throw new \LogicException('Number of signatures cannot be less than zero');
95
        }
96
97
        if ($m > $n) {
98
            throw new \LogicException('Required number of sigs exceeds number of public keys');
99
        }
100
101
        if ($n > 20) {
102
            throw new \LogicException('Number of public keys is greater than 16');
103
        }
104
105 78
        if ($sort) {
106
            $keys = Buffertools::sort($keys);
107 78
        }
108 78
109
        $new = ScriptFactory::create();
110
        $new->int($m);
111
        foreach ($keys as $key) {
112 78
            if (!$key instanceof PublicKeyInterface) {
113
                throw new \LogicException('Values in $keys[] must be a PublicKey');
114
            }
115
116 78
            $new->push($key->getBuffer());
117 78
        }
118 26
119
        return $new->int($n)->op('OP_CHECKMULTISIG')->getScript();
120 78
    }
121 78
122 78
    /**
123 78
     * @param BufferInterface $keyHash
124
     * @return ScriptInterface
125
     */
126
    public function witnessKeyHash(BufferInterface $keyHash)
127 78
    {
128 26
        if ($keyHash->getSize() !== 20) {
129
            throw new \RuntimeException('witness key-hash should be 20 bytes');
130 78
        }
131
132
        return ScriptFactory::sequence([Opcodes::OP_0, $keyHash]);
133
    }
134
135
    /**
136
     * @param BufferInterface $scriptHash
137
     * @return ScriptInterface
138
     */
139
    public function witnessScriptHash(BufferInterface $scriptHash)
140
    {
141
        if ($scriptHash->getSize() !== 32) {
142
            throw new \RuntimeException('witness script-hash should be 32 bytes');
143
        }
144
145
        return ScriptFactory::sequence([Opcodes::OP_0, $scriptHash]);
146
    }
147
}
148