Completed
Pull Request — master (#333)
by thomas
61:20 queued 57:43
created

Interpreter::checkMinimalPush()   C

Complexity

Conditions 9
Paths 8

Size

Total Lines 24
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 9

Importance

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