Completed
Push — master ( 9369e3...7c941d )
by thomas
33:44 queued 16:13
created

Interpreter::verifyWitnessProgram()   C

Complexity

Conditions 12
Paths 22

Size

Total Lines 57
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 31
CRAP Score 12.0988

Importance

Changes 0
Metric Value
cc 12
eloc 33
c 0
b 0
f 0
nc 22
nop 4
dl 0
loc 57
ccs 31
cts 34
cp 0.9118
crap 12.0988
rs 6.62

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace BitWasp\Bitcoin\Script\Interpreter;
4
5
use BitWasp\Bitcoin\Crypto\EcAdapter\Adapter\EcAdapterInterface;
6
use BitWasp\Bitcoin\Crypto\Hash;
7
use BitWasp\Bitcoin\Exceptions\SignatureNotCanonical;
8
use BitWasp\Bitcoin\Exceptions\ScriptRuntimeException;
9
use BitWasp\Bitcoin\Script\Classifier\OutputClassifier;
10
use BitWasp\Bitcoin\Script\Opcodes;
11
use BitWasp\Bitcoin\Script\Script;
12
use BitWasp\Bitcoin\Script\ScriptFactory;
13
use BitWasp\Bitcoin\Script\ScriptInterface;
14
use BitWasp\Bitcoin\Script\ScriptWitness;
15
use BitWasp\Bitcoin\Script\ScriptWitnessInterface;
16
use BitWasp\Bitcoin\Script\WitnessProgram;
17
use BitWasp\Bitcoin\Signature\TransactionSignature;
18
use BitWasp\Bitcoin\Transaction\TransactionInputInterface;
19
use BitWasp\Buffertools\Buffer;
20
use BitWasp\Buffertools\BufferInterface;
21
22
class Interpreter implements InterpreterInterface
23
{
24
25
    /**
26
     * @var \BitWasp\Bitcoin\Math\Math
27
     */
28
    private $math;
29
30
    /**
31
     * @var BufferInterface
32
     */
33
    private $vchFalse;
34
35
    /**
36
     * @var BufferInterface
37
     */
38
    private $vchTrue;
39
40
    /**
41
     * @var array
42
     */
43
    private $disabledOps = [
44
        Opcodes::OP_CAT,    Opcodes::OP_SUBSTR, Opcodes::OP_LEFT,  Opcodes::OP_RIGHT,
45
        Opcodes::OP_INVERT, Opcodes::OP_AND,    Opcodes::OP_OR,    Opcodes::OP_XOR,
46
        Opcodes::OP_2MUL,   Opcodes::OP_2DIV,   Opcodes::OP_MUL,   Opcodes::OP_DIV,
47
        Opcodes::OP_MOD,    Opcodes::OP_LSHIFT, Opcodes::OP_RSHIFT
48
    ];
49
50
    /**
51
     * @param EcAdapterInterface $ecAdapter
52
     */
53 63
    public function __construct(EcAdapterInterface $ecAdapter)
54
    {
55 63
        $this->math = $ecAdapter->getMath();
56 63
        $this->vchFalse = new Buffer("", 0, $this->math);
57 63
        $this->vchTrue = new Buffer("\x01", 1, $this->math);
58 63
    }
59
60
    /**
61
     * Cast the value to a boolean
62
     *
63
     * @param BufferInterface $value
64
     * @return bool
65
     */
66 1647
    public function castToBool(BufferInterface $value)
67
    {
68 1647
        $val = $value->getBinary();
69 1647
        for ($i = 0, $size = strlen($val); $i < $size; $i++) {
70 1511
            $chr = ord($val[$i]);
71 1511
            if ($chr != 0) {
72 1508
                if (($i == ($size - 1)) && $chr == 0x80) {
73
                    return false;
74
                }
75 1508
                return true;
76
            }
77 4
        }
78 395
        return false;
79
    }
80
81
    /**
82
     * @param BufferInterface $signature
83
     * @return bool
84
     */
85
    public function isValidSignatureEncoding(BufferInterface $signature)
86
    {
87
        try {
88
            TransactionSignature::isDERSignature($signature);
89
            return true;
90
        } catch (SignatureNotCanonical $e) {
91
            /* In any case, we will return false outside this block */
92
        }
93
94
        return false;
95
    }
96
97
    /**
98
     * @param int $opCode
99
     * @param BufferInterface $pushData
100
     * @return bool
101
     * @throws \Exception
102
     */
103 233
    public function checkMinimalPush($opCode, BufferInterface $pushData)
104
    {
105 233
        $pushSize = $pushData->getSize();
106 233
        $binary = $pushData->getBinary();
107
108 233
        if ($pushSize === 0) {
109 111
            return $opCode === Opcodes::OP_0;
110 191
        } elseif ($pushSize === 1) {
111 47
            $first = ord($binary[0]);
112
113 47
            if ($first >= 1 && $first <= 16) {
114 35
                return $opCode === (Opcodes::OP_1 + ($first - 1));
115 15
            } elseif ($first === 0x81) {
116 10
                return $opCode === Opcodes::OP_1NEGATE;
117
            }
118 152
        } elseif ($pushSize <= 75) {
119 143
            return $opCode === $pushSize;
120 7
        } elseif ($pushSize <= 255) {
121 5
            return $opCode === Opcodes::OP_PUSHDATA1;
122 5
        } elseif ($pushSize <= 65535) {
123 5
            return $opCode === Opcodes::OP_PUSHDATA2;
124
        }
125
126 13
        return true;
127
    }
128
129
    /**
130
     * @param int $count
131
     * @return $this
132
     */
133 2117
    private function checkOpcodeCount($count)
134
    {
135 2117
        if ($count > 201) {
136 10
            throw new \RuntimeException('Error: Script op code count');
137
        }
138
139 2117
        return $this;
140
    }
141
142
    /**
143
     * @param WitnessProgram $witnessProgram
144
     * @param ScriptWitnessInterface $scriptWitness
145
     * @param int $flags
146
     * @param Checker $checker
147
     * @return bool
148
     */
149 53
    private function verifyWitnessProgram(WitnessProgram $witnessProgram, ScriptWitnessInterface $scriptWitness, $flags, Checker $checker)
150
    {
151 53
        $witnessCount = count($scriptWitness);
152
153 53
        if ($witnessProgram->getVersion() == 0) {
154 51
            $buffer = $witnessProgram->getProgram();
155 51
            if ($buffer->getSize() === 32) {
156
                // Version 0 segregated witness program: SHA256(Script) in program, Script + inputs in witness
157 29
                if ($witnessCount === 0) {
158
                    // Must contain script at least
159 2
                    return false;
160
                }
161
162 27
                $scriptPubKey = new Script($scriptWitness[$witnessCount - 1]);
163 27
                $stackValues = $scriptWitness->slice(0, -1);
164 27
                $hashScriptPubKey = Hash::sha256($scriptPubKey->getBuffer());
165
166 27
                if (!$hashScriptPubKey->equals($buffer)) {
167 14
                    return false;
168 2
                }
169 35
            } elseif ($buffer->getSize() === 20) {
170
                // Version 0 special case for pay-to-pubkeyhash
171 20
                if ($witnessCount !== 2) {
172
                    // 2 items in witness - <signature> <pubkey>
173 2
                    return false;
174
                }
175
176 18
                $scriptPubKey = ScriptFactory::create()->sequence([Opcodes::OP_DUP, Opcodes::OP_HASH160, $buffer, Opcodes::OP_EQUALVERIFY, Opcodes::OP_CHECKSIG])->getScript();
177 18
                $stackValues = $scriptWitness;
178 10
            } else {
179 20
                return false;
180
            }
181 25
        } elseif ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM) {
182 2
            return false;
183
        } else {
184
            return false;
185
        }
186
187 41
        $mainStack = new Stack();
188 41
        foreach ($stackValues as $value) {
189 39
            $mainStack->push($value);
190 23
        }
191
192 41
        if (!$this->evaluate($scriptPubKey, $mainStack, 1, $flags, $checker)) {
193
            return false;
194
        }
195
196 41
        if ($mainStack->count() !== 1) {
197
            return false;
198
        }
199
200 41
        if (!$this->castToBool($mainStack->bottom())) {
201 18
            return false;
202
        }
203
204 23
        return true;
205
    }
206
207
    /**
208
     * @param ScriptInterface $scriptSig
209
     * @param ScriptInterface $scriptPubKey
210
     * @param int $flags
211
     * @param Checker $checker
212
     * @param ScriptWitnessInterface|null $witness
213
     * @return bool
214
     */
215 2251
    public function verify(ScriptInterface $scriptSig, ScriptInterface $scriptPubKey, $flags, Checker $checker, ScriptWitnessInterface $witness = null)
216
    {
217 2251
        static $emptyWitness = null;
218 2251
        if ($emptyWitness === null) {
219 3
            $emptyWitness = new ScriptWitness([]);
220 2
        }
221
222 2251
        $witness = is_null($witness) ? $emptyWitness : $witness;
223
224 2251
        if (($flags & self::VERIFY_SIGPUSHONLY) != 0 && !$scriptSig->isPushOnly()) {
225 4
            return false;
226
        }
227
228 2247
        $stack = new Stack();
229 2247
        if (!$this->evaluate($scriptSig, $stack, 0, $flags, $checker)) {
230 113
            return false;
231
        }
232
233 2134
        $backup = [];
234 2134
        if ($flags & self::VERIFY_P2SH) {
235 1561
            foreach ($stack as $s) {
236 1263
                $backup[] = $s;
237 788
            }
238 788
        }
239
240 2134
        if (!$this->evaluate($scriptPubKey, $stack, 0, $flags, $checker)) {
241 690
            return false;
242
        }
243
244 1444
        if ($stack->isEmpty()) {
245 23
            return false;
246
        }
247
248 1421
        if (false === $this->castToBool($stack[-1])) {
249 97
            return false;
250
        }
251
252 1324
        $program = null;
253 1324
        if ($flags & self::VERIFY_WITNESS) {
254 80
            if ($scriptPubKey->isWitness($program)) {
255
                /** @var WitnessProgram $program */
256 37
                if ($scriptSig->getBuffer()->getSize() !== 0) {
257 2
                    return false;
258
                }
259
260 35
                if (!$this->verifyWitnessProgram($program, $witness, $flags, $checker)) {
261 22
                    return false;
262
                }
263
264 13
                $stack->resize(1);
265 8
            }
266 34
        }
267
268 1300
        if ($flags & self::VERIFY_P2SH && (new OutputClassifier())->isPayToScriptHash($scriptPubKey)) {
269 68
            if (!$scriptSig->isPushOnly()) {
270 9
                return false;
271
            }
272
273 59
            $stack = new Stack();
274 59
            foreach ($backup as $i) {
275 59
                $stack->push($i);
276 32
            }
277
278
            // Restore mainStack to how it was after evaluating scriptSig
279 59
            if ($stack->isEmpty()) {
280
                return false;
281
            }
282
283
            // Load redeemscript as the scriptPubKey
284 59
            $scriptPubKey = new Script($stack->bottom());
285 59
            $stack->pop();
286
287 59
            if (!$this->evaluate($scriptPubKey, $stack, 0, $flags, $checker)) {
288 11
                return false;
289
            }
290
291 48
            if ($stack->isEmpty()) {
292
                return false;
293
            }
294
295 48
            if (!$this->castToBool($stack->bottom())) {
296 2
                return false;
297
            }
298
299 46
            if ($flags & self::VERIFY_WITNESS) {
300 26
                if ($scriptPubKey->isWitness($program)) {
301
                    /** @var WitnessProgram $program */
302 20
                    if ($scriptSig != (ScriptFactory::create()->push($scriptPubKey->getBuffer())->getScript())) {
303 2
                        return false; // SCRIPT_ERR_WITNESS_MALLEATED_P2SH
304
                    }
305
306 18
                    if (!$this->verifyWitnessProgram($program, $witness, $flags, $checker)) {
307 8
                        return false;
308
                    }
309
310 10
                    $stack->resize(1);
311 6
                }
312 10
            }
313 20
        }
314
315 1268
        if ($flags & self::VERIFY_CLEAN_STACK) {
316 15
            if (!($flags & self::VERIFY_P2SH != 0) && ($flags & self::VERIFY_WITNESS != 0)) {
317
                return false; // implied flags required
318
            }
319
320 15
            if (count($stack) != 1) {
321 4
                return false; // Cleanstack
322
            }
323 7
        }
324
325 1264
        if ($flags & self::VERIFY_WITNESS) {
326 46
            if (!$flags & self::VERIFY_P2SH) {
327
                return false; //
328
            }
329
330 46
            if ($program === null && !$witness->isNull()) {
331 2
                return false; // SCRIPT_ERR_WITNESS_UNEXPECTED
332
            }
333 28
        }
334
335 1262
        return true;
336
    }
337
338
    /**
339
     * @param Stack $vfStack
340
     * @return bool
341
     */
342 2239
    private function checkExec(Stack $vfStack, $value)
343
    {
344 2239
        $ret = 0;
345 2239
        foreach ($vfStack as $item) {
346 484
            if ($item == $value) {
347 400
                $ret++;
348 158
            }
349 1142
        }
350
351 2239
        return $ret;
352
    }
353
354
    /**
355
     * @param ScriptInterface $script
356
     * @param Stack $mainStack
357
     * @param int $sigVersion
358
     * @param int $flags
359
     * @param Checker $checker
360
     * @return bool
361
     */
362 2250
    public function evaluate(ScriptInterface $script, Stack $mainStack, $sigVersion, $flags, Checker $checker)
363
    {
364 2250
        $hashStartPos = 0;
365 2250
        $opCount = 0;
366 2250
        $altStack = new Stack();
367 2250
        $vfStack = new Stack();
368 2250
        $minimal = ($flags & self::VERIFY_MINIMALDATA) != 0;
369 2250
        $parser = $script->getScriptParser();
370
371 2250
        if ($script->getBuffer()->getSize() > 10000) {
372 2
            return false;
373
        }
374
375
        try {
376 2250
            foreach ($parser as $operation) {
377 2239
                $opCode = $operation->getOp();
378 2239
                $pushData = $operation->getData();
379 2239
                $fExec = !$this->checkExec($vfStack, false);
380
381
                // If pushdata was written to
382 2239
                if ($operation->isPush() && $operation->getDataSize() > InterpreterInterface::MAX_SCRIPT_ELEMENT_SIZE) {
383 7
                    throw new \RuntimeException('Error - push size');
384
                }
385
386
                // OP_RESERVED should not count towards opCount
387 2236
                if ($opCode > Opcodes::OP_16 && ++$opCount) {
388 2117
                    $this->checkOpcodeCount($opCount);
389 1080
                }
390
391 2236
                if (in_array($opCode, $this->disabledOps, true)) {
392 48
                    throw new \RuntimeException('Disabled Opcode');
393
                }
394
395 2236
                if ($fExec && $operation->isPush()) {
396
                    // In range of a pushdata opcode
397 1642
                    if ($minimal && !$this->checkMinimalPush($opCode, $pushData)) {
398 42
                        throw new ScriptRuntimeException(self::VERIFY_MINIMALDATA, 'Minimal pushdata required');
399
                    }
400
401 1600
                    $mainStack->push($pushData);
402
                    // echo " - [pushed '" . $pushData->getHex() . "']\n";
403 2179
                } elseif ($fExec || (Opcodes::OP_IF <= $opCode && $opCode <= Opcodes::OP_ENDIF)) {
404
                    // echo "OPCODE - " . $script->getOpcodes()->getOp($opCode) . "\n";
405
                    switch ($opCode) {
406 2163
                        case Opcodes::OP_1NEGATE:
407 2163
                        case Opcodes::OP_1:
408 2141
                        case Opcodes::OP_2:
409 2137
                        case Opcodes::OP_3:
410 2137
                        case Opcodes::OP_4:
411 2137
                        case Opcodes::OP_5:
412 2137
                        case Opcodes::OP_6:
413 2137
                        case Opcodes::OP_7:
414 2136
                        case Opcodes::OP_8:
415 2136
                        case Opcodes::OP_9:
416 2136
                        case Opcodes::OP_10:
417 2136
                        case Opcodes::OP_11:
418 2135
                        case Opcodes::OP_12:
419 2135
                        case Opcodes::OP_13:
420 2135
                        case Opcodes::OP_14:
421 2135
                        case Opcodes::OP_15:
422 2135
                        case Opcodes::OP_16:
423 1335
                            $num = \BitWasp\Bitcoin\Script\decodeOpN($opCode);
424 1335
                            $mainStack->push(Number::int($num)->getBuffer());
425 1335
                            break;
426
427 2107
                        case Opcodes::OP_CHECKLOCKTIMEVERIFY:
428 12
                            if (!($flags & self::VERIFY_CHECKLOCKTIMEVERIFY)) {
429 12
                                if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
430 2
                                    throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
431
                                }
432 10
                                break;
433
                            }
434
435
                            if ($mainStack->isEmpty()) {
436
                                throw new \RuntimeException('Invalid stack operation - CLTV');
437
                            }
438
439
                            $lockTime = Number::buffer($mainStack[-1], $minimal, 5, $this->math);
440
                            if (!$checker->checkLockTime($lockTime)) {
441
                                throw new ScriptRuntimeException(self::VERIFY_CHECKLOCKTIMEVERIFY, 'Unsatisfied locktime');
442
                            }
443
444
                            break;
445
446 2105
                        case Opcodes::OP_CHECKSEQUENCEVERIFY:
447 24
                            if (!($flags & self::VERIFY_CHECKSEQUENCEVERIFY)) {
448 12
                                if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
449 2
                                    throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
450
                                }
451 10
                                break;
452
                            }
453
454 12
                            if ($mainStack->isEmpty()) {
455 2
                                throw new \RuntimeException('Invalid stack operation - CSV');
456
                            }
457
458 10
                            $sequence = Number::buffer($mainStack[-1], $minimal, 5, $this->math);
459 8
                            $nSequence = $sequence->getGmp();
460 8
                            if ($this->math->cmp($nSequence, gmp_init(0)) < 0) {
461 2
                                throw new ScriptRuntimeException(self::VERIFY_CHECKSEQUENCEVERIFY, 'Negative locktime');
462
                            }
463
464 6
                            if ($this->math->cmp($this->math->bitwiseAnd($nSequence, gmp_init(TransactionInputInterface::SEQUENCE_LOCKTIME_DISABLE_FLAG, 10)), gmp_init(0)) !== 0) {
465 2
                                break;
466
                            }
467
468 4
                            if (!$checker->checkSequence($sequence)) {
469 4
                                throw new ScriptRuntimeException(self::VERIFY_CHECKSEQUENCEVERIFY, 'Unsatisfied sequence');
470
                            }
471
                            break;
472
473 2091
                        case Opcodes::OP_NOP1:
474 2090
                        case Opcodes::OP_NOP4:
475 2089
                        case Opcodes::OP_NOP5:
476 2088
                        case Opcodes::OP_NOP6:
477 2087
                        case Opcodes::OP_NOP7:
478 2086
                        case Opcodes::OP_NOP8:
479 2085
                        case Opcodes::OP_NOP9:
480 2084
                        case Opcodes::OP_NOP10:
481 54
                            if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
482 20
                                throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
483
                            }
484 34
                            break;
485
486 2071
                        case Opcodes::OP_NOP:
487 168
                            break;
488
489 2025
                        case Opcodes::OP_IF:
490 2003
                        case Opcodes::OP_NOTIF:
491
                            // <expression> if [statements] [else [statements]] endif
492 494
                            $value = false;
493 494
                            if ($fExec) {
494 494
                                if ($mainStack->isEmpty()) {
495 4
                                    throw new \RuntimeException('Unbalanced conditional');
496
                                }
497
498 490
                                $buffer = Number::buffer($mainStack->pop(), $minimal)->getBuffer();
499 490
                                $value = $this->castToBool($buffer);
500 490
                                if ($opCode === Opcodes::OP_NOTIF) {
501 34
                                    $value = !$value;
502 17
                                }
503 245
                            }
504 490
                            $vfStack->push($value);
505 490
                            break;
506
507 1977
                        case Opcodes::OP_ELSE:
508 230
                            if ($vfStack->isEmpty()) {
509 8
                                throw new \RuntimeException('Unbalanced conditional');
510
                            }
511 226
                            $vfStack->push(!$vfStack->pop());
512 226
                            break;
513
514 1971
                        case Opcodes::OP_ENDIF:
515 294
                            if ($vfStack->isEmpty()) {
516 14
                                throw new \RuntimeException('Unbalanced conditional');
517
                            }
518 286
                            $vfStack->pop();
519 286
                            break;
520
521 1699
                        case Opcodes::OP_VERIFY:
522 60
                            if ($mainStack->isEmpty()) {
523 2
                                throw new \RuntimeException('Invalid stack operation');
524
                            }
525 58
                            $value = $this->castToBool($mainStack[-1]);
526 58
                            if (!$value) {
527 2
                                throw new \RuntimeException('Error: verify');
528
                            }
529 56
                            $mainStack->pop();
530 56
                            break;
531
532 1685
                        case Opcodes::OP_TOALTSTACK:
533 16
                            if ($mainStack->isEmpty()) {
534 2
                                throw new \RuntimeException('Invalid stack operation OP_TOALTSTACK');
535
                            }
536 14
                            $altStack->push($mainStack->pop());
537 14
                            break;
538
539 1681
                        case Opcodes::OP_FROMALTSTACK:
540 10
                            if ($altStack->isEmpty()) {
541 4
                                throw new \RuntimeException('Invalid alt-stack operation OP_FROMALTSTACK');
542
                            }
543 6
                            $mainStack->push($altStack->pop());
544 6
                            break;
545
546 1675
                        case Opcodes::OP_IFDUP:
547
                            // If top value not zero, duplicate it.
548 12
                            if ($mainStack->isEmpty()) {
549 4
                                throw new \RuntimeException('Invalid stack operation OP_IFDUP');
550
                            }
551 8
                            $vch = $mainStack[-1];
552 8
                            if ($this->castToBool($vch)) {
553 6
                                $mainStack->push($vch);
554 3
                            }
555 8
                            break;
556
557 1669
                        case Opcodes::OP_DEPTH:
558 153
                            $num = count($mainStack);
559 153
                            $depth = Number::int($num)->getBuffer();
560 153
                            $mainStack->push($depth);
561 153
                            break;
562
563 1651
                        case Opcodes::OP_DROP:
564 96
                            if ($mainStack->isEmpty()) {
565 4
                                throw new \RuntimeException('Invalid stack operation OP_DROP');
566
                            }
567 92
                            $mainStack->pop();
568 92
                            break;
569
570 1645
                        case Opcodes::OP_DUP:
571 71
                            if ($mainStack->isEmpty()) {
572 4
                                throw new \RuntimeException('Invalid stack operation OP_DUP');
573
                            }
574 67
                            $vch = $mainStack[-1];
575 67
                            $mainStack->push($vch);
576 67
                            break;
577
578 1627
                        case Opcodes::OP_NIP:
579 12
                            if (count($mainStack) < 2) {
580 6
                                throw new \RuntimeException('Invalid stack operation OP_NIP');
581
                            }
582 6
                            unset($mainStack[-2]);
583 6
                            break;
584
585 1615
                        case Opcodes::OP_OVER:
586 12
                            if (count($mainStack) < 2) {
587 6
                                throw new \RuntimeException('Invalid stack operation OP_OVER');
588
                            }
589 6
                            $vch = $mainStack[-2];
590 6
                            $mainStack->push($vch);
591 6
                            break;
592
593 1607
                        case Opcodes::OP_ROT:
594 24
                            if (count($mainStack) < 3) {
595 8
                                throw new \RuntimeException('Invalid stack operation OP_ROT');
596
                            }
597 16
                            $mainStack->swap(-3, -2);
598 16
                            $mainStack->swap(-2, -1);
599 16
                            break;
600
601 1595
                        case Opcodes::OP_SWAP:
602 20
                            if (count($mainStack) < 2) {
603 6
                                throw new \RuntimeException('Invalid stack operation OP_SWAP');
604
                            }
605 14
                            $mainStack->swap(-2, -1);
606 14
                            break;
607
608 1587
                        case Opcodes::OP_TUCK:
609 12
                            if (count($mainStack) < 2) {
610 6
                                throw new \RuntimeException('Invalid stack operation OP_TUCK');
611
                            }
612 6
                            $vch = $mainStack[-1];
613 6
                            $mainStack->add(- 2, $vch);
614 6
                            break;
615
616 1579
                        case Opcodes::OP_PICK:
617 1570
                        case Opcodes::OP_ROLL:
618 58
                            if (count($mainStack) < 2) {
619 8
                                throw new \RuntimeException('Invalid stack operation OP_PICK');
620
                            }
621
622 50
                            $n = Number::buffer($mainStack[-1], $minimal, 4)->getGmp();
623 46
                            $mainStack->pop();
624 46
                            if ($this->math->cmp($n, gmp_init(0)) < 0 || $this->math->cmp($n, gmp_init(count($mainStack))) >= 0) {
625 10
                                throw new \RuntimeException('Invalid stack operation OP_PICK');
626
                            }
627
628 36
                            $pos = (int) gmp_strval($this->math->sub($this->math->sub(gmp_init(0), $n), gmp_init(1)), 10);
629 36
                            $vch = $mainStack[$pos];
630 36
                            if ($opCode === Opcodes::OP_ROLL) {
631 18
                                unset($mainStack[$pos]);
632 9
                            }
633 36
                            $mainStack->push($vch);
634 36
                            break;
635
636 1545
                        case Opcodes::OP_2DROP:
637 18
                            if (count($mainStack) < 2) {
638 2
                                throw new \RuntimeException('Invalid stack operation OP_2DROP');
639
                            }
640 16
                            $mainStack->pop();
641 16
                            $mainStack->pop();
642 16
                            break;
643
644 1541
                        case Opcodes::OP_2DUP:
645 12
                            if (count($mainStack) < 2) {
646 6
                                throw new \RuntimeException('Invalid stack operation OP_2DUP');
647
                            }
648 6
                            $string1 = $mainStack[-2];
649 6
                            $string2 = $mainStack[-1];
650 6
                            $mainStack->push($string1);
651 6
                            $mainStack->push($string2);
652 6
                            break;
653
654 1533
                        case Opcodes::OP_3DUP:
655 22
                            if (count($mainStack) < 3) {
656 8
                                throw new \RuntimeException('Invalid stack operation OP_3DUP');
657
                            }
658 14
                            $string1 = $mainStack[-3];
659 14
                            $string2 = $mainStack[-2];
660 14
                            $string3 = $mainStack[-1];
661 14
                            $mainStack->push($string1);
662 14
                            $mainStack->push($string2);
663 14
                            $mainStack->push($string3);
664 14
                            break;
665
666 1513
                        case Opcodes::OP_2OVER:
667 10
                            if (count($mainStack) < 4) {
668 6
                                throw new \RuntimeException('Invalid stack operation OP_2OVER');
669
                            }
670 4
                            $string1 = $mainStack[-4];
671 4
                            $string2 = $mainStack[-3];
672 4
                            $mainStack->push($string1);
673 4
                            $mainStack->push($string2);
674 4
                            break;
675
676 1505
                        case Opcodes::OP_2ROT:
677 20
                            if (count($mainStack) < 6) {
678 2
                                throw new \RuntimeException('Invalid stack operation OP_2ROT');
679
                            }
680 18
                            $string1 = $mainStack[-6];
681 18
                            $string2 = $mainStack[-5];
682 18
                            unset($mainStack[-6], $mainStack[-5]);
683 18
                            $mainStack->push($string1);
684 18
                            $mainStack->push($string2);
685 18
                            break;
686
687 1501
                        case Opcodes::OP_2SWAP:
688 10
                            if (count($mainStack) < 4) {
689 6
                                throw new \RuntimeException('Invalid stack operation OP_2SWAP');
690
                            }
691 4
                            $mainStack->swap(-3, -1);
692 4
                            $mainStack->swap(-4, -2);
693 4
                            break;
694
695 1493
                        case Opcodes::OP_SIZE:
696 62
                            if ($mainStack->isEmpty()) {
697 4
                                throw new \RuntimeException('Invalid stack operation OP_SIZE');
698
                            }
699 58
                            $size = Number::int($mainStack[-1]->getSize());
700 58
                            $mainStack->push($size->getBuffer());
701 58
                            break;
702
703 1487
                        case Opcodes::OP_EQUAL:
704 1376
                        case Opcodes::OP_EQUALVERIFY:
705 586
                            if (count($mainStack) < 2) {
706 8
                                throw new \RuntimeException('Invalid stack operation OP_EQUAL');
707
                            }
708
709 578
                            $equal = $mainStack[-2]->equals($mainStack[-1]);
710 578
                            $mainStack->pop();
711 578
                            $mainStack->pop();
712 578
                            $mainStack->push($equal ? $this->vchTrue : $this->vchFalse);
713 578
                            if ($opCode === Opcodes::OP_EQUALVERIFY) {
714 105
                                if ($equal) {
715 87
                                    $mainStack->pop();
716 46
                                } else {
717 18
                                    throw new \RuntimeException('Error EQUALVERIFY');
718
                                }
719 46
                            }
720
721 562
                            break;
722
723
                        // Arithmetic operations
724 1203
                        case $opCode >= Opcodes::OP_1ADD && $opCode <= Opcodes::OP_0NOTEQUAL:
725 210
                            if ($mainStack->isEmpty()) {
726 12
                                throw new \Exception('Invalid stack operation 1ADD-OP_0NOTEQUAL');
727
                            }
728
729 198
                            $num = Number::buffer($mainStack[-1], $minimal)->getGmp();
730
731 152
                            if ($opCode === Opcodes::OP_1ADD) {
732 14
                                $num = $this->math->add($num, gmp_init(1));
733 145
                            } elseif ($opCode === Opcodes::OP_1SUB) {
734 6
                                $num = $this->math->sub($num, gmp_init(1));
735 135
                            } elseif ($opCode === Opcodes::OP_2MUL) {
736
                                $num = $this->math->mul(gmp_init(2), $num);
737 132
                            } elseif ($opCode === Opcodes::OP_NEGATE) {
738 8
                                $num = $this->math->sub(gmp_init(0), $num);
739 129
                            } elseif ($opCode === Opcodes::OP_ABS) {
740 10
                                if ($this->math->cmp($num, gmp_init(0)) < 0) {
741 7
                                    $num = $this->math->sub(gmp_init(0), $num);
742 2
                                }
743 121
                            } elseif ($opCode === Opcodes::OP_NOT) {
744 104
                                $num = gmp_init($this->math->cmp($num, gmp_init(0)) == 0 ? 1 : 0);
745 53
                            } else {
746
                                // is OP_0NOTEQUAL
747 12
                                $num = gmp_init($this->math->cmp($num, gmp_init(0)) != 0 ? 1 : 0);
748
                            }
749
750 152
                            $mainStack->pop();
751
752 152
                            $buffer = Number::int(gmp_strval($num, 10))->getBuffer();
753
754 152
                            $mainStack->push($buffer);
755 152
                            break;
756
757 1085
                        case $opCode >= Opcodes::OP_ADD && $opCode <= Opcodes::OP_MAX:
758 328
                            if (count($mainStack) < 2) {
759 26
                                throw new \Exception('Invalid stack operation (OP_ADD - OP_MAX)');
760
                            }
761
762 302
                            $num1 = Number::buffer($mainStack[-2], $minimal)->getGmp();
763 268
                            $num2 = Number::buffer($mainStack[-1], $minimal)->getGmp();
764
765 242
                            if ($opCode === Opcodes::OP_ADD) {
766 60
                                $num = $this->math->add($num1, $num2);
767 218
                            } else if ($opCode === Opcodes::OP_SUB) {
768 12
                                $num = $this->math->sub($num1, $num2);
769 188
                            } else if ($opCode === Opcodes::OP_BOOLAND) {
770 16
                                $num = $this->math->cmp($num1, gmp_init(0)) !== 0 && $this->math->cmp($num2, gmp_init(0)) !== 0;
771 174
                            } else if ($opCode === Opcodes::OP_BOOLOR) {
772 16
                                $num = $this->math->cmp($num1, gmp_init(0)) !== 0 || $this->math->cmp($num2, gmp_init(0)) !== 0;
773 158
                            } elseif ($opCode === Opcodes::OP_NUMEQUAL) {
774 56
                                $num = $this->math->cmp($num1, $num2) === 0;
775 130
                            } elseif ($opCode === Opcodes::OP_NUMEQUALVERIFY) {
776 8
                                $num = $this->math->cmp($num1, $num2) === 0;
777 106
                            } elseif ($opCode === Opcodes::OP_NUMNOTEQUAL) {
778 10
                                $num = $this->math->cmp($num1, $num2) !== 0;
779 97
                            } elseif ($opCode === Opcodes::OP_LESSTHAN) {
780 16
                                $num = $this->math->cmp($num1, $num2) < 0;
781 84
                            } elseif ($opCode === Opcodes::OP_GREATERTHAN) {
782 16
                                $num = $this->math->cmp($num1, $num2) > 0;
783 68
                            } elseif ($opCode === Opcodes::OP_LESSTHANOREQUAL) {
784 16
                                $num = $this->math->cmp($num1, $num2) <= 0;
785 52
                            } elseif ($opCode === Opcodes::OP_GREATERTHANOREQUAL) {
786 16
                                $num = $this->math->cmp($num1, $num2) >= 0;
787 36
                            } elseif ($opCode === Opcodes::OP_MIN) {
788 14
                                $num = ($this->math->cmp($num1, $num2) <= 0) ? $num1 : $num2;
789 7
                            } else {
790 14
                                $num = ($this->math->cmp($num1, $num2) >= 0) ? $num1 : $num2;
791
                            }
792
793 242
                            $mainStack->pop();
794 242
                            $mainStack->pop();
795 242
                            $buffer = Number::int(gmp_strval($num, 10))->getBuffer();
796 242
                            $mainStack->push($buffer);
797
798 242
                            if ($opCode === Opcodes::OP_NUMEQUALVERIFY) {
799 8
                                if ($this->castToBool($mainStack[-1])) {
800 8
                                    $mainStack->pop();
801 4
                                } else {
802
                                    throw new \RuntimeException('NUM EQUAL VERIFY error');
803
                                }
804 4
                            }
805 242
                            break;
806
807 757
                        case Opcodes::OP_WITHIN:
808 30
                            if (count($mainStack) < 3) {
809 2
                                throw new \RuntimeException('Invalid stack operation');
810
                            }
811
812 28
                            $num1 = Number::buffer($mainStack[-3], $minimal)->getGmp();
813 26
                            $num2 = Number::buffer($mainStack[-2], $minimal)->getGmp();
814 24
                            $num3 = Number::buffer($mainStack[-1], $minimal)->getGmp();
815
816 22
                            $value = $this->math->cmp($num2, $num1) <= 0 && $this->math->cmp($num1, $num3) < 0;
817 22
                            $mainStack->pop();
818 22
                            $mainStack->pop();
819 22
                            $mainStack->pop();
820 22
                            $mainStack->push($value ? $this->vchTrue : $this->vchFalse);
821 22
                            break;
822
823
                        // Hash operation
824 727
                        case Opcodes::OP_RIPEMD160:
825 721
                        case Opcodes::OP_SHA1:
826 713
                        case Opcodes::OP_SHA256:
827 707
                        case Opcodes::OP_HASH160:
828 684
                        case Opcodes::OP_HASH256:
829 167
                            if ($mainStack->isEmpty()) {
830 23
                                throw new \RuntimeException('Invalid stack operation');
831
                            }
832
833 144
                            $buffer = $mainStack[-1];
834 144
                            if ($opCode === Opcodes::OP_RIPEMD160) {
835 10
                                $hash = Hash::ripemd160($buffer);
836 140
                            } elseif ($opCode === Opcodes::OP_SHA1) {
837 12
                                $hash = Hash::sha1($buffer);
838 130
                            } elseif ($opCode === Opcodes::OP_SHA256) {
839 12
                                $hash = Hash::sha256($buffer);
840 120
                            } elseif ($opCode === Opcodes::OP_HASH160) {
841 106
                                $hash = Hash::sha256ripe160($buffer);
842 58
                            } else {
843 10
                                $hash = Hash::sha256d($buffer);
844
                            }
845
846 144
                            $mainStack->pop();
847 144
                            $mainStack->push($hash);
848 144
                            break;
849
850 625
                        case Opcodes::OP_CODESEPARATOR:
851 2
                            $hashStartPos = $parser->getPosition();
852 2
                            break;
853
854 623
                        case Opcodes::OP_CHECKSIG:
855 535
                        case Opcodes::OP_CHECKSIGVERIFY:
856 203
                            if (count($mainStack) < 2) {
857 4
                                throw new \RuntimeException('Invalid stack operation');
858
                            }
859
860 199
                            $vchPubKey = $mainStack[-1];
861 199
                            $vchSig = $mainStack[-2];
862
863 199
                            $scriptCode = new Script($script->getBuffer()->slice($hashStartPos));
864
865 199
                            $success = $checker->checkSig($scriptCode, $vchSig, $vchPubKey, $sigVersion, $flags);
866
867 133
                            $mainStack->pop();
868 133
                            $mainStack->pop();
869 133
                            $mainStack->push($success ? $this->vchTrue : $this->vchFalse);
870
871 133
                            if ($opCode === Opcodes::OP_CHECKSIGVERIFY) {
872
                                if ($success) {
873
                                    $mainStack->pop();
874
                                } else {
875
                                    throw new \RuntimeException('Checksig verify');
876
                                }
877
                            }
878 133
                            break;
879
880 420
                        case Opcodes::OP_CHECKMULTISIG:
881 343
                        case Opcodes::OP_CHECKMULTISIGVERIFY:
882 229
                            $i = 1;
883 229
                            if (count($mainStack) < $i) {
884 2
                                throw new \RuntimeException('Invalid stack operation');
885
                            }
886
887 227
                            $keyCount = Number::buffer($mainStack[-$i], $minimal)->getInt();
888 223
                            if ($keyCount < 0 || $keyCount > 20) {
889 4
                                throw new \RuntimeException('OP_CHECKMULTISIG: Public key count exceeds 20');
890
                            }
891
892 219
                            $opCount += $keyCount;
893 219
                            $this->checkOpcodeCount($opCount);
894
895
                            // Extract positions of the keys, and signatures, from the stack.
896 219
                            $ikey = ++$i;
897 219
                            $i += $keyCount; /** @var int $i */
898 219
                            if (count($mainStack) < $i) {
899 2
                                throw new \RuntimeException('Invalid stack operation');
900
                            }
901
902 217
                            $sigCount = Number::buffer($mainStack[-$i], $minimal)->getInt();
903 211
                            if ($sigCount < 0 || $sigCount > $keyCount) {
904 4
                                throw new \RuntimeException('Invalid Signature count');
905
                            }
906
907 207
                            $isig = ++$i;
908 207
                            $i += $sigCount;
909
910
                            // Extract the script since the last OP_CODESEPARATOR
911 207
                            $scriptCode = new Script($script->getBuffer()->slice($hashStartPos));
912
913 207
                            $fSuccess = true;
914 207
                            while ($fSuccess && $sigCount > 0) {
915
                                // Fetch the signature and public key
916 87
                                $sig = $mainStack[-$isig];
917 85
                                $pubkey = $mainStack[-$ikey];
918
919 85
                                if ($checker->checkSig($scriptCode, $sig, $pubkey, $sigVersion, $flags)) {
920 45
                                    $isig++;
921 45
                                    $sigCount--;
922 26
                                }
923
924 71
                                $ikey++;
925 71
                                $keyCount--;
926
927
                                // If there are more signatures left than keys left,
928
                                // then too many signatures have failed. Exit early,
929
                                // without checking any further signatures.
930 71
                                if ($sigCount > $keyCount) {
931 30
                                    $fSuccess = false;
932 16
                                }
933 40
                            }
934
935 185
                            while ($i-- > 1) {
936 185
                                $mainStack->pop();
937 96
                            }
938
939
                            // A bug causes CHECKMULTISIG to consume one extra argument
940
                            // whose contents were not checked in any way.
941
                            //
942
                            // Unfortunately this is a potential source of mutability,
943
                            // so optionally verify it is exactly equal to zero prior
944
                            // to removing it from the stack.
945 185
                            if ($mainStack->isEmpty()) {
946 2
                                throw new \RuntimeException('Invalid stack operation');
947
                            }
948
949 185
                            if ($flags & self::VERIFY_NULL_DUMMY && $mainStack[-1]->getSize() !== 0) {
950 4
                                throw new ScriptRuntimeException(self::VERIFY_NULL_DUMMY, 'Extra P2SH stack value should be OP_0');
951
                            }
952
953 181
                            $mainStack->pop();
954 181
                            $mainStack->push($fSuccess ? $this->vchTrue : $this->vchFalse);
955
956 181
                            if ($opCode === Opcodes::OP_CHECKMULTISIGVERIFY) {
957 60
                                if ($fSuccess) {
958 60
                                    $mainStack->pop();
959 30
                                } else {
960
                                    throw new \RuntimeException('OP_CHECKMULTISIG verify');
961
                                }
962 30
                            }
963 181
                            break;
964
965 97
                        default:
966 191
                            throw new \RuntimeException('Opcode not found');
967 97
                    }
968
969 1938
                    if (count($mainStack) + count($altStack) > 1000) {
970 1066
                        throw new \RuntimeException('Invalid stack size, exceeds 1000');
971
                    }
972 981
                }
973 1117
            }
974
975 2147
            if (count($vfStack) !== 0) {
976 12
                throw new \RuntimeException('Unbalanced conditional at script end');
977
            }
978
979 2137
            return true;
980 815
        } catch (ScriptRuntimeException $e) {
981
            // echo "\n Runtime: " . $e->getMessage() . "\n" . $e->getTraceAsString() . PHP_EOL;
982
            // Failure due to script tags, can access flag: $e->getFailureFlag()
983 162
            return false;
984 653
        } catch (\Exception $e) {
985
            // echo "\n General: " . $e->getMessage()  . PHP_EOL . $e->getTraceAsString() . PHP_EOL;
986 653
            return false;
987
        }
988
    }
989
}
990