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

Interpreter::verifyWitnessProgram()   C

Complexity

Conditions 12
Paths 22

Size

Total Lines 56
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 30
CRAP Score 12.1081

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 33
c 1
b 0
f 0
nc 22
nop 4
dl 0
loc 56
ccs 30
cts 33
cp 0.9091
crap 12.1081
rs 6.7092

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

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