Completed
Pull Request — master (#333)
by thomas
43:53 queued 39:08
created

Interpreter::evaluate()   F

Complexity

Conditions 191
Paths 4962

Size

Total Lines 631
Code Lines 435

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 435
CRAP Score 192.347

Importance

Changes 12
Bugs 2 Features 0
Metric Value
cc 191
eloc 435
c 12
b 2
f 0
nc 4962
nop 5
dl 0
loc 631
ccs 435
cts 450
cp 0.9667
crap 192.347
rs 2

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
        $character = $value->getBinary();
0 ignored issues
show
Unused Code introduced by
$character is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
69 2646
        $characters = array_values(unpack("C*", $value->getBinary()));
70 2646
        $size = count($characters);
71
72 2646
        for ($i = 0; $i < $size; $i++) {
73 2439
            $chr = ord($characters[$i]);
74 2439
            if ($chr !== 0) {
75 2439
                if ($i === ($size - 1) && $chr === 0x80) {
76
                    return false;
77
                }
78
79 2439
                return true;
80
            }
81
        }
82
83 591
        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 1140
            return false;
245
        }
246
247 2340
        if ($stack->isEmpty()) {
248 36
            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 556
                $ret++;
351 314
            }
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 2604
                    var_dump($minimal);
0 ignored issues
show
Security Debugging Code introduced by
var_dump($minimal); looks like debug code. Are you sure you do not want to remove it? This might expose sensitive data.
Loading history...
400
                    // In range of a pushdata opcode
401 2604
                    if ($minimal && !$this->checkMinimalPush($opCode, $pushData)) {
402 66
                        throw new ScriptRuntimeException(self::VERIFY_MINIMALDATA, 'Minimal pushdata required');
403
                    }
404
405 2538
                    $mainStack->push($pushData);
406 2538
                     echo " - [pushed '" . $pushData->getHex() . "']\n";
407 3549
                } elseif ($fExec || (Opcodes::OP_IF <= $opCode && $opCode <= Opcodes::OP_ENDIF)) {
408 3513
                     echo "OPCODE - " . $script->getOpcodes()->getOp($opCode) . "\n";
409
                    switch ($opCode) {
410 3513
                        case Opcodes::OP_1NEGATE:
411 3513
                        case Opcodes::OP_1:
412 3490
                        case Opcodes::OP_2:
413 3486
                        case Opcodes::OP_3:
414 3486
                        case Opcodes::OP_4:
415 3486
                        case Opcodes::OP_5:
416 3486
                        case Opcodes::OP_6:
417 3486
                        case Opcodes::OP_7:
418 3485
                        case Opcodes::OP_8:
419 3485
                        case Opcodes::OP_9:
420 3485
                        case Opcodes::OP_10:
421 3485
                        case Opcodes::OP_11:
422 3484
                        case Opcodes::OP_12:
423 3484
                        case Opcodes::OP_13:
424 3484
                        case Opcodes::OP_14:
425 3484
                        case Opcodes::OP_15:
426 3484
                        case Opcodes::OP_16:
427 2088
                            $num = Number::int((int) $opCode - (Opcodes::OP_1 - 1))->getBuffer();
428 2088
                            $mainStack->push($num);
429 2088
                            break;
430
431 3426
                        case Opcodes::OP_CHECKLOCKTIMEVERIFY:
432 18
                            if (!($flags & self::VERIFY_CHECKLOCKTIMEVERIFY)) {
433 18
                                if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
434 3
                                    throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
435
                                }
436 15
                                break;
437
                            }
438
439
                            if ($mainStack->isEmpty()) {
440
                                throw new \RuntimeException('Invalid stack operation - CLTV');
441
                            }
442
443
                            $lockTime = Number::buffer($mainStack[-1], $minimal, 5, $this->math);
444
                            if (!$checker->checkLockTime($lockTime)) {
445
                                throw new ScriptRuntimeException(self::VERIFY_CHECKLOCKTIMEVERIFY, 'Unsatisfied locktime');
446
                            }
447
448
                            break;
449
450 3423
                        case Opcodes::OP_CHECKSEQUENCEVERIFY:
451 36
                            if (!($flags & self::VERIFY_CHECKSEQUENCEVERIFY)) {
452 18
                                if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
453 3
                                    throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
454
                                }
455 15
                                break;
456
                            }
457
458 18
                            if ($mainStack->isEmpty()) {
459 3
                                throw new \RuntimeException('Invalid stack operation - CSV');
460
                            }
461
462 15
                            $sequence = Number::buffer($mainStack[-1], $minimal, 5, $this->math);
463 12
                            $nSequence = $sequence->getGmp();
464 12
                            if ($this->math->cmp($nSequence, gmp_init(0)) < 0) {
465 3
                                throw new ScriptRuntimeException(self::VERIFY_CHECKSEQUENCEVERIFY, 'Negative locktime');
466
                            }
467
468 9
                            if (($nSequence & TransactionInputInterface::SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0) {
469 3
                                break;
470
                            }
471
472 6
                            if (!$checker->checkSequence($sequence)) {
473 6
                                throw new ScriptRuntimeException(self::VERIFY_CHECKSEQUENCEVERIFY, 'Unsatisfied sequence locks');
474
                            }
475
                            break;
476
477 3402
                        case Opcodes::OP_NOP1:
478 3400
                        case Opcodes::OP_NOP4:
479 3399
                        case Opcodes::OP_NOP5:
480 3398
                        case Opcodes::OP_NOP6:
481 3397
                        case Opcodes::OP_NOP7:
482 3396
                        case Opcodes::OP_NOP8:
483 3395
                        case Opcodes::OP_NOP9:
484 3394
                        case Opcodes::OP_NOP10:
485 84
                            if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
486 33
                                throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
487
                            }
488 51
                            break;
489
490 3369
                        case Opcodes::OP_NOP:
491 258
                            break;
492
493 3294
                        case Opcodes::OP_IF:
494 3204
                        case Opcodes::OP_NOTIF:
495
                            // <expression> if [statements] [else [statements]] endif
496
497 744
                            $value = false;
498 744
                            if ($fExec) {
499 744
                                if ($mainStack->isEmpty()) {
500 9
                                    throw new \RuntimeException('Unbalanced conditional: IF/NOTIF');
501
                                }
502
503 735
                                $value = $this->castToBool($mainStack->pop());
504 735
                                if ($opCode === Opcodes::OP_NOTIF) {
505 51
                                    $value = !$value;
506 34
                                }
507 490
                            }
508
509 735
                            $vfStack->push($value);
510 735
                            break;
511
512
513 3018
                        case Opcodes::OP_ELSE:
514 348
                            if ($vfStack->isEmpty()) {
515 15
                                throw new \RuntimeException('Unbalanced conditional: ELSE');
516
                            }
517
518 339
                            $vfStack->push(!$vfStack->pop());
519 339
                            break;
520
521 3006
                        case Opcodes::OP_ENDIF:
522 444
                            if ($vfStack->isEmpty()) {
523 24
                                throw new \RuntimeException('Unbalanced conditional: ENDIF');
524
                            }
525 429
                            $vfStack->pop();
526 429
                            break;
527
528 2595
                        case Opcodes::OP_VERIFY:
529 102
                            if ($mainStack->isEmpty()) {
530 6
                                throw new \RuntimeException('Invalid stack operation');
531
                            }
532 96
                            $value = $this->castToBool($mainStack[-1]);
533 96
                            if (!$value) {
534 3
                                throw new \RuntimeException('Error: verify');
535
                            }
536 93
                            $mainStack->pop();
537 93
                            break;
538
539 2562
                        case Opcodes::OP_TOALTSTACK:
540 33
                            if ($mainStack->isEmpty()) {
541 6
                                throw new \RuntimeException('Invalid stack operation OP_TOALTSTACK');
542
                            }
543 27
                            $altStack->push($mainStack->pop());
544 27
                            break;
545
546 2553
                        case Opcodes::OP_FROMALTSTACK:
547 21
                            if ($altStack->isEmpty()) {
548 9
                                throw new \RuntimeException('Invalid alt-stack operation OP_FROMALTSTACK');
549
                            }
550 12
                            $mainStack->push($altStack->pop());
551 12
                            break;
552
553 2541
                        case Opcodes::OP_IFDUP:
554
                            // If top value not zero, duplicate it.
555 24
                            if ($mainStack->isEmpty()) {
556 9
                                throw new \RuntimeException('Invalid stack operation OP_IFDUP');
557
                            }
558 15
                            $vch = $mainStack[-1];
559 15
                            if ($this->castToBool($vch)) {
560 12
                                $mainStack->push($vch);
561 8
                            }
562 15
                            break;
563
564 2529
                        case Opcodes::OP_DEPTH:
565 270
                            $num = count($mainStack);
566 270
                            $depth = Number::int($num)->getBuffer();
567 270
                            $mainStack->push($depth);
568 270
                            break;
569
570 2499
                        case Opcodes::OP_DROP:
571 147
                            if ($mainStack->isEmpty()) {
572 9
                                throw new \RuntimeException('Invalid stack operation OP_DROP');
573
                            }
574 138
                            $mainStack->pop();
575 138
                            break;
576
577 2487
                        case Opcodes::OP_DUP:
578 105
                            if ($mainStack->isEmpty()) {
579 9
                                throw new \RuntimeException('Invalid stack operation OP_DUP');
580
                            }
581 96
                            $vch = $mainStack[-1];
582 96
                            $mainStack->push($vch);
583 96
                            break;
584
585 2457
                        case Opcodes::OP_NIP:
586 27
                            if (count($mainStack) < 2) {
587 12
                                throw new \RuntimeException('Invalid stack operation OP_NIP');
588
                            }
589 15
                            unset($mainStack[-2]);
590 15
                            break;
591
592 2436
                        case Opcodes::OP_OVER:
593 27
                            if (count($mainStack) < 2) {
594 12
                                throw new \RuntimeException('Invalid stack operation OP_OVER');
595
                            }
596 15
                            $vch = $mainStack[-2];
597 15
                            $mainStack->push($vch);
598 15
                            break;
599
600 2421
                        case Opcodes::OP_ROT:
601 42
                            if (count($mainStack) < 3) {
602 15
                                throw new \RuntimeException('Invalid stack operation OP_ROT');
603
                            }
604 27
                            $mainStack->swap(-3, -2);
605 27
                            $mainStack->swap(-2, -1);
606 27
                            break;
607
608 2400
                        case Opcodes::OP_SWAP:
609 36
                            if (count($mainStack) < 2) {
610 12
                                throw new \RuntimeException('Invalid stack operation OP_SWAP');
611
                            }
612 24
                            $mainStack->swap(-2, -1);
613 24
                            break;
614
615 2385
                        case Opcodes::OP_TUCK:
616 24
                            if (count($mainStack) < 2) {
617 12
                                throw new \RuntimeException('Invalid stack operation OP_TUCK');
618
                            }
619 12
                            $vch = $mainStack[-1];
620 12
                            $mainStack->add(count($mainStack) - 2, $vch);
621 12
                            break;
622
623 2370
                        case Opcodes::OP_PICK:
624 2359
                        case Opcodes::OP_ROLL:
625 99
                            if (count($mainStack) < 2) {
626 15
                                throw new \RuntimeException('Invalid stack operation OP_PICK');
627
                            }
628
629 84
                            $n = Number::buffer($mainStack[-1], $minimal, 4)->getGmp();
630 78
                            $mainStack->pop();
631 78
                            if ($this->math->cmp($n, gmp_init(0)) < 0 || $this->math->cmp($n, gmp_init(count($mainStack))) >= 0) {
632 18
                                throw new \RuntimeException('Invalid stack operation OP_PICK');
633
                            }
634
635 60
                            $pos = (int) gmp_strval($this->math->sub($this->math->sub(gmp_init(0), $n), gmp_init(1)), 10);
636 60
                            $vch = $mainStack[$pos];
637 60
                            if ($opCode === Opcodes::OP_ROLL) {
638 30
                                unset($mainStack[$pos]);
639 20
                            }
640 60
                            $mainStack->push($vch);
641 60
                            break;
642
643 2313
                        case Opcodes::OP_2DROP:
644 33
                            if (count($mainStack) < 2) {
645 6
                                throw new \RuntimeException('Invalid stack operation OP_2DROP');
646
                            }
647 27
                            $mainStack->pop();
648 27
                            $mainStack->pop();
649 27
                            break;
650
651 2304
                        case Opcodes::OP_2DUP:
652 27
                            if (count($mainStack) < 2) {
653 12
                                throw new \RuntimeException('Invalid stack operation OP_2DUP');
654
                            }
655 15
                            $string1 = $mainStack[-2];
656 15
                            $string2 = $mainStack[-1];
657 15
                            $mainStack->push($string1);
658 15
                            $mainStack->push($string2);
659 15
                            break;
660
661 2289
                        case Opcodes::OP_3DUP:
662 42
                            if (count($mainStack) < 3) {
663 15
                                throw new \RuntimeException('Invalid stack operation OP_3DUP');
664
                            }
665 27
                            $string1 = $mainStack[-3];
666 27
                            $string2 = $mainStack[-2];
667 27
                            $string3 = $mainStack[-1];
668 27
                            $mainStack->push($string1);
669 27
                            $mainStack->push($string2);
670 27
                            $mainStack->push($string3);
671 27
                            break;
672
673 2256
                        case Opcodes::OP_2OVER:
674 24
                            if (count($mainStack) < 4) {
675 12
                                throw new \RuntimeException('Invalid stack operation OP_2OVER');
676
                            }
677 12
                            $string1 = $mainStack[-4];
678 12
                            $string2 = $mainStack[-3];
679 12
                            $mainStack->push($string1);
680 12
                            $mainStack->push($string2);
681 12
                            break;
682
683 2241
                        case Opcodes::OP_2ROT:
684 36
                            if (count($mainStack) < 6) {
685 6
                                throw new \RuntimeException('Invalid stack operation OP_2ROT');
686
                            }
687 30
                            $string1 = $mainStack[-6];
688 30
                            $string2 = $mainStack[-5];
689 30
                            unset($mainStack[-6], $mainStack[-5]);
690 30
                            $mainStack->push($string1);
691 30
                            $mainStack->push($string2);
692 30
                            break;
693
694 2232
                        case Opcodes::OP_2SWAP:
695 21
                            if (count($mainStack) < 4) {
696 12
                                throw new \RuntimeException('Invalid stack operation OP_2SWAP');
697
                            }
698 9
                            $mainStack->swap(-3, -1);
699 9
                            $mainStack->swap(-4, -2);
700 9
                            break;
701
702 2217
                        case Opcodes::OP_SIZE:
703 99
                            if ($mainStack->isEmpty()) {
704 9
                                throw new \RuntimeException('Invalid stack operation OP_SIZE');
705
                            }
706 90
                            $size = Number::int($mainStack[-1]->getSize());
707 90
                            $mainStack->push($size->getBuffer());
708 90
                            break;
709
710 2205
                        case Opcodes::OP_EQUAL:
711 2080
                        case Opcodes::OP_EQUALVERIFY:
712 1059
                            if (count($mainStack) < 2) {
713 15
                                throw new \RuntimeException('Invalid stack operation OP_EQUAL');
714
                            }
715
716 1044
                            $equal = $mainStack[-2]->equals($mainStack[-1]);
717 1044
                            $mainStack->pop();
718 1044
                            $mainStack->pop();
719 1044
                            $mainStack->push($equal ? $this->vchTrue : $this->vchFalse);
720 1044
                            if ($opCode === Opcodes::OP_EQUALVERIFY) {
721 207
                                if ($equal) {
722 174
                                    $mainStack->pop();
723 116
                                } else {
724 36
                                    throw new \RuntimeException('Error EQUALVERIFY');
725
                                }
726 116
                            }
727
728 1014
                            break;
729
730
                        // Arithmetic operations
731 1683
                        case $opCode >= Opcodes::OP_1ADD && $opCode <= Opcodes::OP_0NOTEQUAL:
732 336
                            if ($mainStack->isEmpty()) {
733 21
                                throw new \Exception('Invalid stack operation 1ADD-OP_0NOTEQUAL');
734
                            }
735
736 315
                            $num = Number::buffer($mainStack[-1], $minimal)->getGmp();
737
738 246
                            if ($opCode === Opcodes::OP_1ADD) {
739 24
                                $num = $this->math->add($num, gmp_init(1));
740 238
                            } elseif ($opCode === Opcodes::OP_1SUB) {
741 12
                                $num = $this->math->sub($num, gmp_init(1));
742 218
                            } elseif ($opCode === Opcodes::OP_2MUL) {
743
                                $num = $this->math->mul(gmp_init(2), $num);
744 210
                            } elseif ($opCode === Opcodes::OP_NEGATE) {
745 12
                                $num = $this->math->sub(gmp_init(0), $num);
746 207
                            } elseif ($opCode === Opcodes::OP_ABS) {
747 15
                                if ($this->math->cmp($num, gmp_init(0)) < 0) {
748 9
                                    $num = $this->math->sub(gmp_init(0), $num);
749 4
                                }
750 196
                            } elseif ($opCode === Opcodes::OP_NOT) {
751 162
                                $num = gmp_init($this->math->cmp($num, gmp_init(0)) == 0 ? 1 : 0);
752 108
                            } else {
753
                                // is OP_0NOTEQUAL
754 24
                                $num = gmp_init($this->math->cmp($num, gmp_init(0)) !== 0 ? 1 : 0);
755
                            }
756
757 246
                            $mainStack->pop();
758
759 246
                            $buffer = Number::int(gmp_strval($num, 10))->getBuffer();
760
761 246
                            $mainStack->push($buffer);
762 246
                            break;
763
764 1482
                        case $opCode >= Opcodes::OP_ADD && $opCode <= Opcodes::OP_MAX:
765 567
                            if (count($mainStack) < 2) {
766 51
                                throw new \Exception('Invalid stack operation (OP_ADD - OP_MAX)');
767
                            }
768
769 516
                            $num1 = Number::buffer($mainStack[-2], $minimal)->getGmp();
770 465
                            $num2 = Number::buffer($mainStack[-1], $minimal)->getGmp();
771
772 426
                            if ($opCode === Opcodes::OP_ADD) {
773 93
                                $num = $this->math->add($num1, $num2);
774 401
                            } else if ($opCode === Opcodes::OP_SUB) {
775 21
                                $num = $this->math->sub($num1, $num2);
776 344
                            } else if ($opCode === Opcodes::OP_BOOLAND) {
777 30
                                $num = $this->math->cmp($num1, gmp_init(0)) !== 0 && $this->math->cmp($num2, gmp_init(0)) !== 0;
778 320
                            } else if ($opCode === Opcodes::OP_BOOLOR) {
779 33
                                $num = $this->math->cmp($num1, gmp_init(0)) !== 0 || $this->math->cmp($num2, gmp_init(0)) !== 0;
780 289
                            } elseif ($opCode === Opcodes::OP_NUMEQUAL) {
781 93
                                $num = $this->math->cmp($num1, $num2) === 0;
782 244
                            } elseif ($opCode === Opcodes::OP_NUMEQUALVERIFY) {
783 12
                                $num = $this->math->cmp($num1, $num2) === 0;
784 194
                            } elseif ($opCode === Opcodes::OP_NUMNOTEQUAL) {
785 18
                                $num = $this->math->cmp($num1, $num2) !== 0;
786 180
                            } elseif ($opCode === Opcodes::OP_LESSTHAN) {
787 30
                                $num = $this->math->cmp($num1, $num2) < 0;
788 158
                            } elseif ($opCode === Opcodes::OP_GREATERTHAN) {
789 30
                                $num = $this->math->cmp($num1, $num2) > 0;
790 128
                            } elseif ($opCode === Opcodes::OP_LESSTHANOREQUAL) {
791 30
                                $num = $this->math->cmp($num1, $num2) <= 0;
792 98
                            } elseif ($opCode === Opcodes::OP_GREATERTHANOREQUAL) {
793 30
                                $num = $this->math->cmp($num1, $num2) >= 0;
794 68
                            } elseif ($opCode === Opcodes::OP_MIN) {
795 24
                                $num = ($this->math->cmp($num1, $num2) <= 0) ? $num1 : $num2;
796 16
                            } else {
797 24
                                $num = ($this->math->cmp($num1, $num2) >= 0) ? $num1 : $num2;
798
                            }
799
800 426
                            $mainStack->pop();
801 426
                            $mainStack->pop();
802 426
                            $buffer = Number::int(gmp_strval($num, 10))->getBuffer();
803 426
                            $mainStack->push($buffer);
804
805 426
                            if ($opCode === Opcodes::OP_NUMEQUALVERIFY) {
806 12
                                if ($this->castToBool($mainStack[-1])) {
807 12
                                    $mainStack->pop();
808 8
                                } else {
809
                                    throw new \RuntimeException('NUM EQUAL VERIFY error');
810
                                }
811 8
                            }
812 426
                            break;
813
814 915
                        case Opcodes::OP_WITHIN:
815 51
                            if (count($mainStack) < 3) {
816 6
                                throw new \RuntimeException('Invalid stack operation');
817
                            }
818
819 45
                            $num1 = Number::buffer($mainStack[-3], $minimal)->getGmp();
820 42
                            $num2 = Number::buffer($mainStack[-2], $minimal)->getGmp();
821 39
                            $num3 = Number::buffer($mainStack[-1], $minimal)->getGmp();
822
823 36
                            $value = $this->math->cmp($num2, $num1) <= 0 && $this->math->cmp($num1, $num3) < 0;
824 36
                            $mainStack->pop();
825 36
                            $mainStack->pop();
826 36
                            $mainStack->pop();
827 36
                            $mainStack->push($value ? $this->vchTrue : $this->vchFalse);
828 36
                            break;
829
830
                        // Hash operation
831 864
                        case Opcodes::OP_RIPEMD160:
832 856
                        case Opcodes::OP_SHA1:
833 847
                        case Opcodes::OP_SHA256:
834 840
                        case Opcodes::OP_HASH160:
835 816
                        case Opcodes::OP_HASH256:
836 252
                            if ($mainStack->isEmpty()) {
837 36
                                throw new \RuntimeException('Invalid stack operation');
838
                            }
839
840 216
                            $buffer = $mainStack[-1];
841 216
                            if ($opCode === Opcodes::OP_RIPEMD160) {
842 18
                                $hash = Hash::ripemd160($buffer);
843 211
                            } elseif ($opCode === Opcodes::OP_SHA1) {
844 21
                                $hash = Hash::sha1($buffer);
845 194
                            } elseif ($opCode === Opcodes::OP_SHA256) {
846 21
                                $hash = Hash::sha256($buffer);
847 175
                            } elseif ($opCode === Opcodes::OP_HASH160) {
848 147
                                $hash = Hash::sha256ripe160($buffer);
849 98
                            } else {
850 18
                                $hash = Hash::sha256d($buffer);
851
                            }
852
853 216
                            $mainStack->pop();
854 216
                            $mainStack->push($hash);
855 216
                            break;
856
857 696
                        case Opcodes::OP_CODESEPARATOR:
858 3
                            $hashStartPos = $parser->getPosition();
859 3
                            break;
860
861 693
                        case Opcodes::OP_CHECKSIG:
862 603
                        case Opcodes::OP_CHECKSIGVERIFY:
863 270
                            if (count($mainStack) < 2) {
864 9
                                throw new \RuntimeException('Invalid stack operation');
865
                            }
866
867 261
                            $vchPubKey = $mainStack[-1];
868 261
                            $vchSig = $mainStack[-2];
869
870 261
                            $scriptCode = new Script($script->getBuffer()->slice($hashStartPos));
871
872 261
                            $success = $checker->checkSig($scriptCode, $vchSig, $vchPubKey, $sigVersion, $flags);
873
874 186
                            $mainStack->pop();
875 186
                            $mainStack->pop();
876 186
                            $mainStack->push($success ? $this->vchTrue : $this->vchFalse);
877
878 186
                            if ($opCode === Opcodes::OP_CHECKSIGVERIFY) {
879
                                if ($success) {
880
                                    $mainStack->pop();
881
                                } else {
882
                                    throw new \RuntimeException('Checksig verify');
883
                                }
884
                            }
885 186
                            break;
886
887 423
                        case Opcodes::OP_CHECKMULTISIG:
888 346
                        case Opcodes::OP_CHECKMULTISIGVERIFY:
889 327
                            $i = 1;
890 327
                            if (count($mainStack) < $i) {
891 3
                                throw new \RuntimeException('Invalid stack operation');
892
                            }
893
894 324
                            $keyCount = Number::buffer($mainStack[-$i], $minimal)->getInt();
895 318
                            if ($keyCount < 0 || $keyCount > 20) {
896 6
                                throw new \RuntimeException('OP_CHECKMULTISIG: Public key count exceeds 20');
897
                            }
898
899 312
                            $opCount += $keyCount;
900 312
                            $this->checkOpcodeCount($opCount);
901
902
                            // Extract positions of the keys, and signatures, from the stack.
903 312
                            $ikey = ++$i;
904 312
                            $i += $keyCount; /** @var int $i */
905 312
                            if (count($mainStack) < $i) {
906 3
                                throw new \RuntimeException('Invalid stack operation');
907
                            }
908
909 309
                            $sigCount = Number::buffer($mainStack[-$i], $minimal)->getInt();
910 300
                            if ($sigCount < 0 || $sigCount > $keyCount) {
911 6
                                throw new \RuntimeException('Invalid Signature count');
912
                            }
913
914 294
                            $isig = ++$i;
915 294
                            $i += $sigCount;
916
917
                            // Extract the script since the last OP_CODESEPARATOR
918 294
                            $scriptCode = new Script($script->getBuffer()->slice($hashStartPos));
919
920 294
                            $fSuccess = true;
921 294
                            while ($fSuccess && $sigCount > 0) {
922
                                // Fetch the signature and public key
923 114
                                $sig = $mainStack[-$isig];
924 111
                                $pubkey = $mainStack[-$ikey];
925
926 111
                                if ($checker->checkSig($scriptCode, $sig, $pubkey, $sigVersion, $flags)) {
927 55
                                    $isig++;
928 55
                                    $sigCount--;
929 36
                                }
930
931 93
                                $ikey++;
932 93
                                $keyCount--;
933
934
                                // If there are more signatures left than keys left,
935
                                // then too many signatures have failed. Exit early,
936
                                // without checking any further signatures.
937 93
                                if ($sigCount > $keyCount) {
938 44
                                    $fSuccess = false;
939 30
                                }
940 62
                            }
941
942 267
                            while ($i-- > 1) {
943 267
                                $mainStack->pop();
944 178
                            }
945
946
                            // A bug causes CHECKMULTISIG to consume one extra argument
947
                            // whose contents were not checked in any way.
948
                            //
949
                            // Unfortunately this is a potential source of mutability,
950
                            // so optionally verify it is exactly equal to zero prior
951
                            // to removing it from the stack.
952 267
                            if ($mainStack->isEmpty()) {
953 3
                                throw new \RuntimeException('Invalid stack operation');
954
                            }
955
956 267
                            if ($flags & self::VERIFY_NULL_DUMMY && $mainStack[-1]->getSize() !== 0) {
957 6
                                throw new ScriptRuntimeException(self::VERIFY_NULL_DUMMY, 'Extra P2SH stack value should be OP_0');
958
                            }
959
960 261
                            $mainStack->pop();
961 261
                            $mainStack->push($fSuccess ? $this->vchTrue : $this->vchFalse);
962
963 261
                            if ($opCode === Opcodes::OP_CHECKMULTISIGVERIFY) {
964 90
                                if ($fSuccess) {
965 90
                                    $mainStack->pop();
966 60
                                } else {
967
                                    throw new \RuntimeException('OP_CHECKMULTISIG verify');
968
                                }
969 60
                            }
970 261
                            break;
971
972 64
                        default:
973 96
                            throw new \RuntimeException('Opcode not found');
974 64
                    }
975
976 3087
                    if (count($mainStack) + count($altStack) > 1000) {
977 1153
                        throw new \RuntimeException('Invalid stack size, exceeds 1000');
978
                    }
979 2058
                }
980 2374
            }
981
982 3498
            if (count($vfStack) !== 0) {
983 18
                throw new \RuntimeException('Unbalanced conditional at script end');
984
            }
985
986 3483
            return true;
987 1323
        } catch (ScriptRuntimeException $e) {
988 219
             echo "\n Runtime: " . $e->getMessage() . "\n";
989
            // Failure due to script tags, can access flag: $e->getFailureFlag()
990 219
            return false;
991 1104
        } catch (\Exception $e) {
992 1104
             echo "\n General: " . $e->getMessage()  . PHP_EOL . $e->getTraceAsString();
993 1104
            return false;
994
        }
995
    }
996
}
997