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

Interpreter::verifyWitnessProgram()   C

Complexity

Conditions 12
Paths 22

Size

Total Lines 56
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 31
CRAP Score 12.0988

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