Completed
Pull Request — master (#392)
by thomas
191:09 queued 188:38
created

OutputScriptFactory   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 133
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 7

Test Coverage

Coverage 60%

Importance

Changes 0
Metric Value
dl 0
loc 133
ccs 27
cts 45
cp 0.6
rs 10
c 0
b 0
f 0
wmc 20
lcom 0
cbo 7

8 Methods

Rating   Name   Duplication   Size   Complexity  
A payToAddress() 0 6 2
A payToPubKey() 0 4 1
A payToPubKeyHash() 0 8 2
A payToPubKeyHashFromHash() 0 8 2
A payToScriptHash() 0 8 2
C multisig() 0 31 7
A witnessKeyHash() 0 8 2
A witnessScriptHash() 0 8 2
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 96
    public function payToAddress(AddressInterface $address)
22
    {
23 64
        return $address instanceof ScriptHashAddress
24 40
            ? ScriptFactory::sequence([Opcodes::OP_HASH160, $address->getHash(), Opcodes::OP_EQUAL])
25 96
            : ScriptFactory::sequence([Opcodes::OP_DUP, Opcodes::OP_HASH160, $address->getHash(), Opcodes::OP_EQUALVERIFY, Opcodes::OP_CHECKSIG]);
26
    }
27
28
    /**
29
     * Create a Pay to pubkey output
30
     *
31
     * @param PublicKeyInterface  $publicKey
32
     * @return ScriptInterface
33
     */
34 30
    public function payToPubKey(PublicKeyInterface $publicKey)
35
    {
36 30
        return ScriptFactory::sequence([$publicKey->getBuffer(), Opcodes::OP_CHECKSIG]);
37
    }
38
39
    /**
40
     * Create a P2PKH output script
41
     *
42
     * @param BufferInterface $pubKeyHash
43
     * @return ScriptInterface
44
     */
45 54
    public function payToPubKeyHash(BufferInterface $pubKeyHash)
46
    {
47 54
        if ($pubKeyHash->getSize() !== 20) {
48
            throw new \RuntimeException('Public key hash must be exactly 20 bytes');
49
        }
50
51 54
        return ScriptFactory::sequence([Opcodes::OP_DUP, Opcodes::OP_HASH160, $pubKeyHash, Opcodes::OP_EQUALVERIFY, Opcodes::OP_CHECKSIG]);
52
    }
53
54
    /**
55
     * 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
        }
65
66
        return ScriptFactory::sequence([Opcodes::OP_DUP, Opcodes::OP_HASH160, $hash, Opcodes::OP_EQUALVERIFY, Opcodes::OP_CHECKSIG]);
67
    }
68
69
    /**
70
     * Create a P2SH output script
71
     *
72
     * @param BufferInterface $scriptHash
73
     * @return ScriptInterface
74
     */
75 84
    public function payToScriptHash(BufferInterface $scriptHash)
76
    {
77 84
        if ($scriptHash->getSize() !== 20) {
78
            throw new \RuntimeException('P2SH scriptHash must be exactly 20 bytes');
79
        }
80
81 84
        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 72
    public function multisig($m, array $keys = [], $sort = true)
91
    {
92 72
        $n = count($keys);
93 72
        if ($m < 0) {
94
            throw new \LogicException('Number of signatures cannot be less than zero');
95
        }
96
97 72
        if ($m > $n) {
98
            throw new \LogicException('Required number of sigs exceeds number of public keys');
99
        }
100
101 72
        if ($n > 20) {
102
            throw new \LogicException('Number of public keys is greater than 16');
103
        }
104
105 72
        if ($sort) {
106 36
            $keys = Buffertools::sort($keys);
107 12
        }
108
109 72
        $new = ScriptFactory::create();
110 72
        $new->int($m);
111 72
        foreach ($keys as $key) {
112 72
            if (!$key instanceof PublicKeyInterface) {
113
                throw new \LogicException('Values in $keys[] must be a PublicKey');
114
            }
115
116 72
            $new->push($key->getBuffer());
117 24
        }
118
119 72
        return $new->int($n)->op('OP_CHECKMULTISIG')->getScript();
120
    }
121
122
    /**
123
     * @param BufferInterface $keyHash
124
     * @return ScriptInterface
125
     */
126
    public function witnessKeyHash(BufferInterface $keyHash)
127
    {
128
        if ($keyHash->getSize() !== 20) {
129
            throw new \RuntimeException('witness key-hash should be 20 bytes');
130
        }
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