Completed
Pull Request — master (#334)
by thomas
81:34 queued 77:32
created

Interpreter   F

Complexity

Total Complexity 259

Size/Duplication

Total Lines 974
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 21

Test Coverage

Coverage 95.54%

Importance

Changes 14
Bugs 3 Features 0
Metric Value
c 14
b 3
f 0
dl 0
loc 974
ccs 579
cts 606
cp 0.9554
rs 1.263
wmc 259
lcom 1
cbo 21

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A isValidSignatureEncoding() 0 11 2
C checkMinimalPush() 0 24 9
A checkOpcodeCount() 0 8 2
C verifyWitnessProgram() 0 56 12
F verify() 0 122 35
A checkExec() 0 11 3
B castToBool() 0 19 5
F evaluate() 0 630 190

How to fix   Complexity   

Complex Class

Complex classes like Interpreter often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Interpreter, and based on these observations, apply Extract Interface, too.

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