Completed
Pull Request — master (#759)
by thomas
25:10
created

ScriptFactory::getBitcoinConsensus()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BitWasp\Bitcoin\Script;
6
7
use BitWasp\Bitcoin\Bitcoin;
8
use BitWasp\Bitcoin\Crypto\EcAdapter\Adapter\EcAdapterInterface;
9
use BitWasp\Bitcoin\Math\Math;
10
use BitWasp\Bitcoin\Script\Consensus\BitcoinConsensus;
11
use BitWasp\Bitcoin\Script\Consensus\ConsensusInterface;
12
use BitWasp\Bitcoin\Script\Consensus\NativeConsensus;
13
use BitWasp\Bitcoin\Script\Factory\OutputScriptFactory;
14
use BitWasp\Bitcoin\Script\Factory\ScriptCreator;
15
use BitWasp\Bitcoin\Script\Parser\Operation;
16
use BitWasp\Buffertools\Buffer;
17
use BitWasp\Buffertools\BufferInterface;
18
19
class ScriptFactory
20
{
21
    /**
22
     * @var OutputScriptFactory
23
     */
24
    private static $outputScriptFactory = null;
25
26
    /**
27
     * @var Opcodes|null
28
     */
29
    protected static $opcodes = null;
30
31 5396
    public static function getOpCodes(): Opcodes
32
    {
33 5396
        if (null === static::$opcodes) {
34
            static::$opcodes = new Opcodes();
35
        }
36 5396
        return static::$opcodes;
37
    }
38
39
    /**
40
     * @param string $string
41
     * @return ScriptInterface
42
     * @throws \Exception
43
     */
44 17
    public static function fromHex(string $string): ScriptInterface
45
    {
46 17
        return self::fromBuffer(Buffer::hex($string));
47
    }
48
49
    /**
50
     * @param BufferInterface $buffer
51
     * @param Opcodes|null $opcodes
52
     * @param Math|null $math
53
     * @return ScriptInterface
54
     */
55 25
    public static function fromBuffer(BufferInterface $buffer, Opcodes $opcodes = null, Math $math = null): ScriptInterface
56
    {
57 25
        return self::create($buffer, $opcodes, $math)->getScript();
58
    }
59
60
    /**
61
     * @param BufferInterface|null $buffer
62
     * @param Opcodes|null $opcodes
63
     * @param Math|null $math
64
     * @return ScriptCreator
65
     */
66 5396
    public static function create(BufferInterface $buffer = null, Opcodes $opcodes = null, Math $math = null): ScriptCreator
67
    {
68 5396
        $opcodes = $opcodes ?: self::getOpCodes();
69 5396
        return new ScriptCreator($math ?: Bitcoin::getMath(), $opcodes, $buffer);
70
    }
71
72
    /**
73
     * Create a script consisting only of push-data operations.
74
     * Suitable for a scriptSig.
75
     *
76
     * @param BufferInterface[] $buffers
77
     * @return ScriptInterface
78
     */
79
    public static function pushAll(array $buffers): ScriptInterface
80
    {
81 93
        return self::sequence(array_map(function ($buffer) {
82 76
            if (!($buffer instanceof BufferInterface)) {
83
                throw new \RuntimeException('Script contained a non-push opcode');
84
            }
85
86 76
            $size = $buffer->getSize();
87 76
            if ($size === 0) {
88 24
                return Opcodes::OP_0;
89
            }
90
91 76
            $first = ord($buffer->getBinary()[0]);
92 76
            if ($size === 1 && $first >= 1 && $first <= 16) {
93 4
                return \BitWasp\Bitcoin\Script\encodeOpN($first);
94
            } else {
95 76
                return $buffer;
96
            }
97 93
        }, $buffers));
98
    }
99
100
    /**
101
     * @param int[]|\BitWasp\Bitcoin\Script\Interpreter\Number[]|BufferInterface[] $sequence
102
     * @return ScriptInterface
103
     */
104 5361
    public static function sequence(array $sequence): ScriptInterface
105
    {
106 5361
        return self::create()->sequence($sequence)->getScript();
107
    }
108
109
    /**
110
     * @param Operation[] $operations
111
     * @return ScriptInterface
112
     */
113 20
    public static function fromOperations(array $operations): ScriptInterface
114
    {
115 20
        $sequence = [];
116 20
        foreach ($operations as $operation) {
117 19
            if (!($operation instanceof Operation)) {
118
                throw new \RuntimeException("Invalid input to fromOperations");
119
            }
120
121 19
            $sequence[] = $operation->encode();
122
        }
123
124 20
        return self::sequence($sequence);
125
    }
126
127
    /**
128
     * @return OutputScriptFactory
129
     */
130 226
    public static function scriptPubKey(): OutputScriptFactory
131
    {
132 226
        if (self::$outputScriptFactory === null) {
133
            self::$outputScriptFactory = new OutputScriptFactory();
134
        }
135
136 226
        return self::$outputScriptFactory;
137
    }
138
139
    /**
140
     * @param EcAdapterInterface|null $ecAdapter
141
     * @return NativeConsensus
142
     */
143 1
    public static function getNativeConsensus(EcAdapterInterface $ecAdapter = null): NativeConsensus
144
    {
145 1
        return new NativeConsensus($ecAdapter ?: Bitcoin::getEcAdapter());
146
    }
147
148
    /**
149
     * @return BitcoinConsensus
150
     */
151 81
    public static function getBitcoinConsensus(): BitcoinConsensus
152
    {
153 81
        return new BitcoinConsensus();
154
    }
155
156
    /**
157
     * @param EcAdapterInterface|null $ecAdapter
158
     * @return ConsensusInterface
159
     */
160 80
    public static function consensus(EcAdapterInterface $ecAdapter = null): ConsensusInterface
161
    {
162 80
        if (extension_loaded('bitcoinconsensus')) {
163 80
            return self::getBitcoinConsensus();
164
        } else {
165
            return self::getNativeConsensus($ecAdapter);
166
        }
167
    }
168
}
169