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

Interpreter::checkOpcodeCount()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

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