Completed
Push — master ( 7a567c...8c5683 )
by thomas
19:10 queued 04:46
created

Interpreter::checkExec()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3.0175

Importance

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