Completed
Pull Request — master (#403)
by thomas
73:13 queued 70:38
created

Interpreter::checkExec()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 6
c 0
b 0
f 0
nc 3
nop 2
dl 0
loc 11
ccs 8
cts 8
cp 1
crap 3
rs 9.4285
1
<?php
2
3
namespace BitWasp\Bitcoin\Script\Interpreter;
4
5
use BitWasp\Bitcoin\Bitcoin;
6
use BitWasp\Bitcoin\Crypto\EcAdapter\Adapter\EcAdapterInterface;
7
use BitWasp\Bitcoin\Crypto\Hash;
8
use BitWasp\Bitcoin\Exceptions\SignatureNotCanonical;
9
use BitWasp\Bitcoin\Exceptions\ScriptRuntimeException;
10
use BitWasp\Bitcoin\Script\Classifier\OutputClassifier;
11
use BitWasp\Bitcoin\Script\Opcodes;
12
use BitWasp\Bitcoin\Script\Script;
13
use BitWasp\Bitcoin\Script\ScriptFactory;
14
use BitWasp\Bitcoin\Script\ScriptInterface;
15
use BitWasp\Bitcoin\Script\ScriptWitness;
16
use BitWasp\Bitcoin\Script\ScriptWitnessInterface;
17
use BitWasp\Bitcoin\Script\WitnessProgram;
18
use BitWasp\Bitcoin\Signature\TransactionSignature;
19
use BitWasp\Bitcoin\Transaction\SignatureHash\SigHash;
20
use BitWasp\Bitcoin\Transaction\TransactionInputInterface;
21
use BitWasp\Buffertools\Buffer;
22
use BitWasp\Buffertools\BufferInterface;
23
24
class Interpreter implements InterpreterInterface
25
{
26
27
    /**
28
     * @var \BitWasp\Bitcoin\Math\Math
29
     */
30
    private $math;
31
32
    /**
33
     * @var BufferInterface
34
     */
35
    private $vchFalse;
36
37
    /**
38
     * @var BufferInterface
39
     */
40
    private $vchTrue;
41
42
    /**
43
     * @var array
44
     */
45
    private $disabledOps = [
46
        Opcodes::OP_CAT,    Opcodes::OP_SUBSTR, Opcodes::OP_LEFT,  Opcodes::OP_RIGHT,
47
        Opcodes::OP_INVERT, Opcodes::OP_AND,    Opcodes::OP_OR,    Opcodes::OP_XOR,
48
        Opcodes::OP_2MUL,   Opcodes::OP_2DIV,   Opcodes::OP_MUL,   Opcodes::OP_DIV,
49
        Opcodes::OP_MOD,    Opcodes::OP_LSHIFT, Opcodes::OP_RSHIFT
50
    ];
51
52
    /**
53
     * @param EcAdapterInterface $ecAdapter
54
     */
55 288
    public function __construct(EcAdapterInterface $ecAdapter = null)
56
    {
57 288
        $ecAdapter = $ecAdapter ?: Bitcoin::getEcAdapter();
58 288
        $this->math = $ecAdapter->getMath();
59 288
        $this->vchFalse = new Buffer("", 0, $this->math);
60 288
        $this->vchTrue = new Buffer("\x01", 1, $this->math);
61 288
    }
62
63
    /**
64
     * Cast the value to a boolean
65
     *
66
     * @param BufferInterface $value
67
     * @return bool
68
     */
69 3402
    public function castToBool(BufferInterface $value)
70
    {
71 3402
        $val = $value->getBinary();
72 3402
        for ($i = 0, $size = strlen($val); $i < $size; $i++) {
73 3118
            $chr = ord($val[$i]);
74 3118
            if ($chr !== 0) {
75 3112
                if (($i === ($size - 1)) && $chr === 0x80) {
76
                    return false;
77
                }
78 3112
                return true;
79
            }
80 6
        }
81 802
        return false;
82
    }
83
84
    /**
85
     * @param BufferInterface $signature
86
     * @return bool
87
     */
88
    public function isValidSignatureEncoding(BufferInterface $signature)
89
    {
90
        try {
91
            TransactionSignature::isDERSignature($signature);
92
            return true;
93
        } catch (SignatureNotCanonical $e) {
94
            /* In any case, we will return false outside this block */
95
        }
96
97
        return false;
98
    }
99
100
    /**
101
     * @param int $opCode
102
     * @param BufferInterface $pushData
103
     * @return bool
104
     * @throws \Exception
105
     */
106 466
    public function checkMinimalPush($opCode, BufferInterface $pushData)
107
    {
108 466
        $pushSize = $pushData->getSize();
109 466
        $binary = $pushData->getBinary();
110
111 466
        if ($pushSize === 0) {
112 222
            return $opCode === Opcodes::OP_0;
113 382
        } elseif ($pushSize === 1) {
114 94
            $first = ord($binary[0]);
115
116 94
            if ($first >= 1 && $first <= 16) {
117 70
                return $opCode === (Opcodes::OP_1 + ($first - 1));
118 30
            } elseif ($first === 0x81) {
119 20
                return $opCode === Opcodes::OP_1NEGATE;
120
            }
121 304
        } elseif ($pushSize <= 75) {
122 286
            return $opCode === $pushSize;
123 14
        } elseif ($pushSize <= 255) {
124 10
            return $opCode === Opcodes::OP_PUSHDATA1;
125 10
        } elseif ($pushSize <= 65535) {
126 10
            return $opCode === Opcodes::OP_PUSHDATA2;
127
        }
128
129 26
        return true;
130
    }
131
132
    /**
133
     * @param int $count
134
     * @return $this
135
     */
136 4348
    private function checkOpcodeCount($count)
137
    {
138 4348
        if ($count > 201) {
139 20
            throw new \RuntimeException('Error: Script op code count');
140
        }
141
142 4348
        return $this;
143
    }
144
145
    /**
146
     * @param WitnessProgram $witnessProgram
147
     * @param ScriptWitnessInterface $scriptWitness
148
     * @param int $flags
149
     * @param Checker $checker
150
     * @return bool
151
     */
152 109
    private function verifyWitnessProgram(WitnessProgram $witnessProgram, ScriptWitnessInterface $scriptWitness, $flags, Checker $checker)
153
    {
154 109
        $witnessCount = count($scriptWitness);
155
156 109
        if ($witnessProgram->getVersion() === 0) {
157 105
            $buffer = $witnessProgram->getProgram();
158 105
            if ($buffer->getSize() === 32) {
159
                // Version 0 segregated witness program: SHA256(Script) in program, Script + inputs in witness
160 67
                if ($witnessCount === 0) {
161
                    // Must contain script at least
162 4
                    return false;
163
                }
164
165 63
                $scriptPubKey = new Script($scriptWitness[$witnessCount - 1]);
166 63
                $stackValues = $scriptWitness->slice(0, -1);
167 63
                $hashScriptPubKey = Hash::sha256($scriptPubKey->getBuffer());
168
169 63
                if (!$hashScriptPubKey->equals($buffer)) {
0 ignored issues
show
Documentation introduced by
$buffer is of type object<BitWasp\Buffertools\BufferInterface>, but the function expects a object<self>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
170 40
                    return false;
171
                }
172 61
            } elseif ($buffer->getSize() === 20) {
173
                // Version 0 special case for pay-to-pubkeyhash
174 34
                if ($witnessCount !== 2) {
175
                    // 2 items in witness - <signature> <pubkey>
176 12
                    return false;
177
                }
178
179 30
                $scriptPubKey = ScriptFactory::scriptPubKey()->payToPubKeyHash($buffer);
180 32
                $stackValues = $scriptWitness;
181 14
            } else {
182 52
                return false;
183
            }
184 41
        } elseif ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM) {
185 4
            return false;
186
        } else {
187
            return false;
188
        }
189
190 85
        $mainStack = new Stack();
191 85
        foreach ($stackValues as $value) {
192 81
            $mainStack->push($value);
193 37
        }
194
195 85
        if (!$this->evaluate($scriptPubKey, $mainStack, SigHash::V1, $flags, $checker)) {
196 18
            return false;
197
        }
198
199 85
        if ($mainStack->count() !== 1) {
200
            return false;
201
        }
202
203 85
        if (!$this->castToBool($mainStack->bottom())) {
204 36
            return false;
205
        }
206
207 49
        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 4577
    public function verify(ScriptInterface $scriptSig, ScriptInterface $scriptPubKey, $flags, Checker $checker, ScriptWitnessInterface $witness = null)
219
    {
220 4577
        static $emptyWitness = null;
221 4577
        if ($emptyWitness === null) {
222 6
            $emptyWitness = new ScriptWitness([]);
223 2
        }
224
225 4577
        $witness = is_null($witness) ? $emptyWitness : $witness;
226
227 4577
        if (($flags & self::VERIFY_SIGPUSHONLY) !== 0 && !$scriptSig->isPushOnly()) {
228 8
            return false;
229
        }
230
231 4569
        $stack = new Stack();
232 4569
        if (!$this->evaluate($scriptSig, $stack, SigHash::V0, $flags, $checker)) {
233 226
            return false;
234
        }
235
236 4343
        $backup = [];
237 4343
        if ($flags & self::VERIFY_P2SH) {
238 3137
            foreach ($stack as $s) {
239 2538
                $backup[] = $s;
240 1551
            }
241 1551
        }
242
243 4343
        if (!$this->evaluate($scriptPubKey, $stack, SigHash::V0, $flags, $checker)) {
244 1389
            return false;
245
        }
246
247 2963
        if ($stack->isEmpty()) {
248 46
            return false;
249
        }
250
251 2917
        if (false === $this->castToBool($stack[-1])) {
252 200
            return false;
253
        }
254
255 2717
        $program = null;
256 2717
        if ($flags & self::VERIFY_WITNESS) {
257 139
            if ($scriptPubKey->isWitness($program)) {
258
                /** @var WitnessProgram $program */
259 74
                if ($scriptSig->getBuffer()->getSize() !== 0) {
260 4
                    return false;
261
                }
262
263 70
                if (!$this->verifyWitnessProgram($program, $witness, $flags, $checker)) {
264 56
                    return false;
265
                }
266
267 26
                $stack->resize(1);
268 10
            }
269 37
        }
270
271 2669
        if ($flags & self::VERIFY_P2SH && (new OutputClassifier())->isPayToScriptHash($scriptPubKey)) {
272 148
            if (!$scriptSig->isPushOnly()) {
273 18
                return false;
274
            }
275
276 130
            $stack = new Stack();
277 130
            foreach ($backup as $i) {
278 130
                $stack->push($i);
279 58
            }
280
281
            // Restore mainStack to how it was after evaluating scriptSig
282 130
            if ($stack->isEmpty()) {
283
                return false;
284
            }
285
286
            // Load redeemscript as the scriptPubKey
287 130
            $scriptPubKey = new Script($stack->bottom());
288 130
            $stack->pop();
289
290 130
            if (!$this->evaluate($scriptPubKey, $stack, 0, $flags, $checker)) {
291 31
                return false;
292
            }
293
294 108
            if ($stack->isEmpty()) {
295
                return false;
296
            }
297
298 108
            if (!$this->castToBool($stack->bottom())) {
299 4
                return false;
300
            }
301
302 104
            if ($flags & self::VERIFY_WITNESS) {
303 49
                if ($scriptPubKey->isWitness($program)) {
304
                    /** @var WitnessProgram $program */
305 43
                    if (!$scriptSig->equals(ScriptFactory::sequence([$scriptPubKey->getBuffer()]))) {
306 4
                        return false; // SCRIPT_ERR_WITNESS_MALLEATED_P2SH
307
                    }
308
309 39
                    if (!$this->verifyWitnessProgram($program, $witness, $flags, $checker)) {
310 28
                        return false;
311
                    }
312
313 23
                    $stack->resize(1);
314 9
                }
315 11
            }
316 36
        }
317
318 2605
        if ($flags & self::VERIFY_CLEAN_STACK) {
319 30
            if (!($flags & self::VERIFY_P2SH !== 0) && ($flags & self::VERIFY_WITNESS !== 0)) {
320
                return false; // implied flags required
321
            }
322
323 30
            if (count($stack) !== 1) {
324 8
                return false; // Cleanstack
325
            }
326 8
        }
327
328 2597
        if ($flags & self::VERIFY_WITNESS) {
329 71
            if (!$flags & self::VERIFY_P2SH) {
330
                return false; //
331
            }
332
333 71
            if ($program === null && !$witness->isNull()) {
334 4
                return false; // SCRIPT_ERR_WITNESS_UNEXPECTED
335
            }
336 25
        }
337
338 2593
        return true;
339
    }
340
341
    /**
342
     * @param Stack $vfStack
343
     * @param bool $value
344
     * @return bool
345
     */
346 4604
    private function checkExec(Stack $vfStack, $value)
347
    {
348 4604
        $ret = 0;
349 4604
        foreach ($vfStack as $item) {
350 968
            if ($item === $value) {
351 800
                $ret++;
352 316
            }
353 2236
        }
354
355 4604
        return $ret;
356
    }
357
358
    /**
359
     * @param ScriptInterface $script
360
     * @param Stack $mainStack
361
     * @param int $sigVersion
362
     * @param int $flags
363
     * @param Checker $checker
364
     * @return bool
365
     */
366 4638
    public function evaluate(ScriptInterface $script, Stack $mainStack, $sigVersion, $flags, Checker $checker)
367
    {
368 4638
        $hashStartPos = 0;
369 4638
        $opCount = 0;
370 4638
        $zero = gmp_init(0, 10);
371 4638
        $altStack = new Stack();
372 4638
        $vfStack = new Stack();
373 4638
        $minimal = ($flags & self::VERIFY_MINIMALDATA) !== 0;
374 4638
        $parser = $script->getScriptParser();
375
376 4638
        if ($script->getBuffer()->getSize() > 10000) {
377 4
            return false;
378
        }
379
380
        try {
381 4638
            foreach ($parser as $operation) {
382 4604
                $opCode = $operation->getOp();
383 4604
                $pushData = $operation->getData();
384 4604
                $fExec = !$this->checkExec($vfStack, false);
385
386
                // If pushdata was written to
387 4604
                if ($operation->isPush() && $operation->getDataSize() > InterpreterInterface::MAX_SCRIPT_ELEMENT_SIZE) {
388 14
                    throw new \RuntimeException('Error - push size');
389
                }
390
391
                // OP_RESERVED should not count towards opCount
392 4598
                if ($opCode > Opcodes::OP_16 && ++$opCount) {
393 4348
                    $this->checkOpcodeCount($opCount);
394 2112
                }
395
396 4598
                if (in_array($opCode, $this->disabledOps, true)) {
397 96
                    throw new \RuntimeException('Disabled Opcode');
398
                }
399
400 4598
                if ($fExec && $operation->isPush()) {
401
                    // In range of a pushdata opcode
402 3410
                    if ($minimal && !$this->checkMinimalPush($opCode, $pushData)) {
403 84
                        throw new ScriptRuntimeException(self::VERIFY_MINIMALDATA, 'Minimal pushdata required');
404
                    }
405
406 3326
                    $mainStack->push($pushData);
407
                    // echo " - [pushed '" . $pushData->getHex() . "']\n";
408 4474
                } elseif ($fExec || (Opcodes::OP_IF <= $opCode && $opCode <= Opcodes::OP_ENDIF)) {
409
                    // echo "OPCODE - " . $script->getOpcodes()->getOp($opCode) . "\n";
410
                    switch ($opCode) {
411 4440
                        case Opcodes::OP_1NEGATE:
412 4440
                        case Opcodes::OP_1:
413 4396
                        case Opcodes::OP_2:
414 4388
                        case Opcodes::OP_3:
415 4388
                        case Opcodes::OP_4:
416 4388
                        case Opcodes::OP_5:
417 4388
                        case Opcodes::OP_6:
418 4388
                        case Opcodes::OP_7:
419 4386
                        case Opcodes::OP_8:
420 4386
                        case Opcodes::OP_9:
421 4386
                        case Opcodes::OP_10:
422 4386
                        case Opcodes::OP_11:
423 4384
                        case Opcodes::OP_12:
424 4384
                        case Opcodes::OP_13:
425 4384
                        case Opcodes::OP_14:
426 4384
                        case Opcodes::OP_15:
427 4384
                        case Opcodes::OP_16:
428 2670
                            $num = \BitWasp\Bitcoin\Script\decodeOpN($opCode);
429 2670
                            $mainStack->push(Number::int($num)->getBuffer());
430 2670
                            break;
431
432 4328
                        case Opcodes::OP_CHECKLOCKTIMEVERIFY:
433 24
                            if (!($flags & self::VERIFY_CHECKLOCKTIMEVERIFY)) {
434 24
                                if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
435 4
                                    throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
436
                                }
437 20
                                break;
438
                            }
439
440
                            if ($mainStack->isEmpty()) {
441
                                throw new \RuntimeException('Invalid stack operation - CLTV');
442
                            }
443
444
                            $lockTime = Number::buffer($mainStack[-1], $minimal, 5, $this->math);
445
                            if (!$checker->checkLockTime($lockTime)) {
446
                                throw new ScriptRuntimeException(self::VERIFY_CHECKLOCKTIMEVERIFY, 'Unsatisfied locktime');
447
                            }
448
449
                            break;
450
451 4324
                        case Opcodes::OP_CHECKSEQUENCEVERIFY:
452 48
                            if (!($flags & self::VERIFY_CHECKSEQUENCEVERIFY)) {
453 24
                                if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
454 4
                                    throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
455
                                }
456 20
                                break;
457
                            }
458
459 24
                            if ($mainStack->isEmpty()) {
460 4
                                throw new \RuntimeException('Invalid stack operation - CSV');
461
                            }
462
463 20
                            $sequence = Number::buffer($mainStack[-1], $minimal, 5, $this->math);
464 16
                            $nSequence = $sequence->getGmp();
465 16
                            if ($this->math->cmp($nSequence, $zero) < 0) {
466 4
                                throw new ScriptRuntimeException(self::VERIFY_CHECKSEQUENCEVERIFY, 'Negative locktime');
467
                            }
468
469 12
                            if ($this->math->cmp($this->math->bitwiseAnd($nSequence, gmp_init(TransactionInputInterface::SEQUENCE_LOCKTIME_DISABLE_FLAG, 10)), $zero) !== 0) {
470 4
                                break;
471
                            }
472
473 8
                            if (!$checker->checkSequence($sequence)) {
474 8
                                throw new ScriptRuntimeException(self::VERIFY_CHECKSEQUENCEVERIFY, 'Unsatisfied sequence');
475
                            }
476
                            break;
477
478 4296
                        case Opcodes::OP_NOP1:
479 4294
                        case Opcodes::OP_NOP4:
480 4292
                        case Opcodes::OP_NOP5:
481 4290
                        case Opcodes::OP_NOP6:
482 4288
                        case Opcodes::OP_NOP7:
483 4286
                        case Opcodes::OP_NOP8:
484 4284
                        case Opcodes::OP_NOP9:
485 4282
                        case Opcodes::OP_NOP10:
486 108
                            if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
487 40
                                throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
488
                            }
489 68
                            break;
490
491 4256
                        case Opcodes::OP_NOP:
492 336
                            break;
493
494 4164
                        case Opcodes::OP_IF:
495 4120
                        case Opcodes::OP_NOTIF:
496
                            // <expression> if [statements] [else [statements]] endif
497 988
                            $value = false;
498 988
                            if ($fExec) {
499 988
                                if ($mainStack->isEmpty()) {
500 8
                                    throw new \RuntimeException('Unbalanced conditional');
501
                                }
502
503 980
                                $buffer = Number::buffer($mainStack->pop(), $minimal)->getBuffer();
0 ignored issues
show
Bug introduced by
It seems like $mainStack->pop() can be null; however, buffer() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
504 980
                                $value = $this->castToBool($buffer);
505 980
                                if ($opCode === Opcodes::OP_NOTIF) {
506 68
                                    $value = !$value;
507 34
                                }
508 490
                            }
509 980
                            $vfStack->push($value);
510 980
                            break;
511
512 4068
                        case Opcodes::OP_ELSE:
513 460
                            if ($vfStack->isEmpty()) {
514 16
                                throw new \RuntimeException('Unbalanced conditional');
515
                            }
516 452
                            $vfStack->push(!$vfStack->pop());
517 452
                            break;
518
519 4056
                        case Opcodes::OP_ENDIF:
520 588
                            if ($vfStack->isEmpty()) {
521 28
                                throw new \RuntimeException('Unbalanced conditional');
522
                            }
523 572
                            $vfStack->pop();
524 572
                            break;
525
526 3512
                        case Opcodes::OP_VERIFY:
527 120
                            if ($mainStack->isEmpty()) {
528 4
                                throw new \RuntimeException('Invalid stack operation');
529
                            }
530 116
                            $value = $this->castToBool($mainStack[-1]);
531 116
                            if (!$value) {
532 4
                                throw new \RuntimeException('Error: verify');
533
                            }
534 112
                            $mainStack->pop();
535 112
                            break;
536
537 3484
                        case Opcodes::OP_TOALTSTACK:
538 32
                            if ($mainStack->isEmpty()) {
539 4
                                throw new \RuntimeException('Invalid stack operation OP_TOALTSTACK');
540
                            }
541 28
                            $altStack->push($mainStack->pop());
542 28
                            break;
543
544 3476
                        case Opcodes::OP_FROMALTSTACK:
545 20
                            if ($altStack->isEmpty()) {
546 8
                                throw new \RuntimeException('Invalid alt-stack operation OP_FROMALTSTACK');
547
                            }
548 12
                            $mainStack->push($altStack->pop());
549 12
                            break;
550
551 3464
                        case Opcodes::OP_IFDUP:
552
                            // If top value not zero, duplicate it.
553 24
                            if ($mainStack->isEmpty()) {
554 8
                                throw new \RuntimeException('Invalid stack operation OP_IFDUP');
555
                            }
556 16
                            $vch = $mainStack[-1];
557 16
                            if ($this->castToBool($vch)) {
558 12
                                $mainStack->push($vch);
559 6
                            }
560 16
                            break;
561
562 3452
                        case Opcodes::OP_DEPTH:
563 306
                            $num = count($mainStack);
564 306
                            $depth = Number::int($num)->getBuffer();
565 306
                            $mainStack->push($depth);
566 306
                            break;
567
568 3416
                        case Opcodes::OP_DROP:
569 192
                            if ($mainStack->isEmpty()) {
570 8
                                throw new \RuntimeException('Invalid stack operation OP_DROP');
571
                            }
572 184
                            $mainStack->pop();
573 184
                            break;
574
575 3404
                        case Opcodes::OP_DUP:
576 184
                            if ($mainStack->isEmpty()) {
577 20
                                throw new \RuntimeException('Invalid stack operation OP_DUP');
578
                            }
579 176
                            $vch = $mainStack[-1];
580 176
                            $mainStack->push($vch);
581 176
                            break;
582
583 3368
                        case Opcodes::OP_NIP:
584 24
                            if (count($mainStack) < 2) {
585 12
                                throw new \RuntimeException('Invalid stack operation OP_NIP');
586
                            }
587 12
                            unset($mainStack[-2]);
588 12
                            break;
589
590 3344
                        case Opcodes::OP_OVER:
591 24
                            if (count($mainStack) < 2) {
592 12
                                throw new \RuntimeException('Invalid stack operation OP_OVER');
593
                            }
594 12
                            $vch = $mainStack[-2];
595 12
                            $mainStack->push($vch);
596 12
                            break;
597
598 3328
                        case Opcodes::OP_ROT:
599 48
                            if (count($mainStack) < 3) {
600 16
                                throw new \RuntimeException('Invalid stack operation OP_ROT');
601
                            }
602 32
                            $mainStack->swap(-3, -2);
603 32
                            $mainStack->swap(-2, -1);
604 32
                            break;
605
606 3304
                        case Opcodes::OP_SWAP:
607 40
                            if (count($mainStack) < 2) {
608 12
                                throw new \RuntimeException('Invalid stack operation OP_SWAP');
609
                            }
610 28
                            $mainStack->swap(-2, -1);
611 28
                            break;
612
613 3288
                        case Opcodes::OP_TUCK:
614 24
                            if (count($mainStack) < 2) {
615 12
                                throw new \RuntimeException('Invalid stack operation OP_TUCK');
616
                            }
617 12
                            $vch = $mainStack[-1];
618 12
                            $mainStack->add(- 2, $vch);
619 12
                            break;
620
621 3272
                        case Opcodes::OP_PICK:
622 3254
                        case Opcodes::OP_ROLL:
623 116
                            if (count($mainStack) < 2) {
624 16
                                throw new \RuntimeException('Invalid stack operation OP_PICK');
625
                            }
626
627 100
                            $n = Number::buffer($mainStack[-1], $minimal, 4)->getGmp();
628 92
                            $mainStack->pop();
629 92
                            if ($this->math->cmp($n, $zero) < 0 || $this->math->cmp($n, gmp_init(count($mainStack))) >= 0) {
630 20
                                throw new \RuntimeException('Invalid stack operation OP_PICK');
631
                            }
632
633 72
                            $pos = (int) gmp_strval($this->math->sub($this->math->sub($zero, $n), gmp_init(1)), 10);
634 72
                            $vch = $mainStack[$pos];
635 72
                            if ($opCode === Opcodes::OP_ROLL) {
636 36
                                unset($mainStack[$pos]);
637 18
                            }
638 72
                            $mainStack->push($vch);
639 72
                            break;
640
641 3204
                        case Opcodes::OP_2DROP:
642 36
                            if (count($mainStack) < 2) {
643 4
                                throw new \RuntimeException('Invalid stack operation OP_2DROP');
644
                            }
645 32
                            $mainStack->pop();
646 32
                            $mainStack->pop();
647 32
                            break;
648
649 3196
                        case Opcodes::OP_2DUP:
650 24
                            if (count($mainStack) < 2) {
651 12
                                throw new \RuntimeException('Invalid stack operation OP_2DUP');
652
                            }
653 12
                            $string1 = $mainStack[-2];
654 12
                            $string2 = $mainStack[-1];
655 12
                            $mainStack->push($string1);
656 12
                            $mainStack->push($string2);
657 12
                            break;
658
659 3180
                        case Opcodes::OP_3DUP:
660 44
                            if (count($mainStack) < 3) {
661 16
                                throw new \RuntimeException('Invalid stack operation OP_3DUP');
662
                            }
663 28
                            $string1 = $mainStack[-3];
664 28
                            $string2 = $mainStack[-2];
665 28
                            $string3 = $mainStack[-1];
666 28
                            $mainStack->push($string1);
667 28
                            $mainStack->push($string2);
668 28
                            $mainStack->push($string3);
669 28
                            break;
670
671 3140
                        case Opcodes::OP_2OVER:
672 20
                            if (count($mainStack) < 4) {
673 12
                                throw new \RuntimeException('Invalid stack operation OP_2OVER');
674
                            }
675 8
                            $string1 = $mainStack[-4];
676 8
                            $string2 = $mainStack[-3];
677 8
                            $mainStack->push($string1);
678 8
                            $mainStack->push($string2);
679 8
                            break;
680
681 3124
                        case Opcodes::OP_2ROT:
682 40
                            if (count($mainStack) < 6) {
683 4
                                throw new \RuntimeException('Invalid stack operation OP_2ROT');
684
                            }
685 36
                            $string1 = $mainStack[-6];
686 36
                            $string2 = $mainStack[-5];
687 36
                            unset($mainStack[-6], $mainStack[-5]);
688 36
                            $mainStack->push($string1);
689 36
                            $mainStack->push($string2);
690 36
                            break;
691
692 3116
                        case Opcodes::OP_2SWAP:
693 20
                            if (count($mainStack) < 4) {
694 12
                                throw new \RuntimeException('Invalid stack operation OP_2SWAP');
695
                            }
696 8
                            $mainStack->swap(-3, -1);
697 8
                            $mainStack->swap(-4, -2);
698 8
                            break;
699
700 3100
                        case Opcodes::OP_SIZE:
701 124
                            if ($mainStack->isEmpty()) {
702 8
                                throw new \RuntimeException('Invalid stack operation OP_SIZE');
703
                            }
704 116
                            $size = Number::int($mainStack[-1]->getSize());
705 116
                            $mainStack->push($size->getBuffer());
706 116
                            break;
707
708 3088
                        case Opcodes::OP_EQUAL:
709 2866
                        case Opcodes::OP_EQUALVERIFY:
710 1268
                            if (count($mainStack) < 2) {
711 16
                                throw new \RuntimeException('Invalid stack operation OP_EQUAL');
712
                            }
713
714 1252
                            $equal = $mainStack[-2]->equals($mainStack[-1]);
715 1252
                            $mainStack->pop();
716 1252
                            $mainStack->pop();
717 1252
                            $mainStack->push($equal ? $this->vchTrue : $this->vchFalse);
718 1252
                            if ($opCode === Opcodes::OP_EQUALVERIFY) {
719 252
                                if ($equal) {
720 210
                                    $mainStack->pop();
721 94
                                } else {
722 42
                                    throw new \RuntimeException('Error EQUALVERIFY');
723
                                }
724 94
                            }
725
726 1214
                            break;
727
728
                        // Arithmetic operations
729 2520
                        case $opCode >= Opcodes::OP_1ADD && $opCode <= Opcodes::OP_0NOTEQUAL:
730 420
                            if ($mainStack->isEmpty()) {
731 24
                                throw new \Exception('Invalid stack operation 1ADD-OP_0NOTEQUAL');
732
                            }
733
734 396
                            $num = Number::buffer($mainStack[-1], $minimal)->getGmp();
735
736 304
                            if ($opCode === Opcodes::OP_1ADD) {
737 28
                                $num = $this->math->add($num, gmp_init(1));
738 290
                            } elseif ($opCode === Opcodes::OP_1SUB) {
739 12
                                $num = $this->math->sub($num, gmp_init(1));
740 270
                            } elseif ($opCode === Opcodes::OP_2MUL) {
741
                                $num = $this->math->mul(gmp_init(2), $num);
742 264
                            } elseif ($opCode === Opcodes::OP_NEGATE) {
743 16
                                $num = $this->math->sub($zero, $num);
744 258
                            } elseif ($opCode === Opcodes::OP_ABS) {
745 20
                                if ($this->math->cmp($num, $zero) < 0) {
746 14
                                    $num = $this->math->sub($zero, $num);
747 4
                                }
748 242
                            } elseif ($opCode === Opcodes::OP_NOT) {
749 208
                                $num = gmp_init($this->math->cmp($num, $zero) === 0 ? 1 : 0);
750 102
                            } else {
751
                                // is OP_0NOTEQUAL
752 24
                                $num = gmp_init($this->math->cmp($num, $zero) !== 0 ? 1 : 0);
753
                            }
754
755 304
                            $mainStack->pop();
756
757 304
                            $buffer = Number::int(gmp_strval($num, 10))->getBuffer();
758
759 304
                            $mainStack->push($buffer);
760 304
                            break;
761
762 2284
                        case $opCode >= Opcodes::OP_ADD && $opCode <= Opcodes::OP_MAX:
763 656
                            if (count($mainStack) < 2) {
764 52
                                throw new \Exception('Invalid stack operation (OP_ADD - OP_MAX)');
765
                            }
766
767 604
                            $num1 = Number::buffer($mainStack[-2], $minimal)->getGmp();
768 536
                            $num2 = Number::buffer($mainStack[-1], $minimal)->getGmp();
769
770 484
                            if ($opCode === Opcodes::OP_ADD) {
771 120
                                $num = $this->math->add($num1, $num2);
772 436
                            } else if ($opCode === Opcodes::OP_SUB) {
773 24
                                $num = $this->math->sub($num1, $num2);
774 376
                            } else if ($opCode === Opcodes::OP_BOOLAND) {
775 32
                                $num = $this->math->cmp($num1, $zero) !== 0 && $this->math->cmp($num2, $zero) !== 0;
776 348
                            } else if ($opCode === Opcodes::OP_BOOLOR) {
777 32
                                $num = $this->math->cmp($num1, $zero) !== 0 || $this->math->cmp($num2, $zero) !== 0;
778 316
                            } elseif ($opCode === Opcodes::OP_NUMEQUAL) {
779 112
                                $num = $this->math->cmp($num1, $num2) === 0;
780 260
                            } elseif ($opCode === Opcodes::OP_NUMEQUALVERIFY) {
781 16
                                $num = $this->math->cmp($num1, $num2) === 0;
782 212
                            } elseif ($opCode === Opcodes::OP_NUMNOTEQUAL) {
783 20
                                $num = $this->math->cmp($num1, $num2) !== 0;
784 194
                            } elseif ($opCode === Opcodes::OP_LESSTHAN) {
785 32
                                $num = $this->math->cmp($num1, $num2) < 0;
786 168
                            } elseif ($opCode === Opcodes::OP_GREATERTHAN) {
787 32
                                $num = $this->math->cmp($num1, $num2) > 0;
788 136
                            } elseif ($opCode === Opcodes::OP_LESSTHANOREQUAL) {
789 32
                                $num = $this->math->cmp($num1, $num2) <= 0;
790 104
                            } elseif ($opCode === Opcodes::OP_GREATERTHANOREQUAL) {
791 32
                                $num = $this->math->cmp($num1, $num2) >= 0;
792 72
                            } elseif ($opCode === Opcodes::OP_MIN) {
793 28
                                $num = ($this->math->cmp($num1, $num2) <= 0) ? $num1 : $num2;
794 14
                            } else {
795 28
                                $num = ($this->math->cmp($num1, $num2) >= 0) ? $num1 : $num2;
796
                            }
797
798 484
                            $mainStack->pop();
799 484
                            $mainStack->pop();
800 484
                            $buffer = Number::int(gmp_strval($num, 10))->getBuffer();
801 484
                            $mainStack->push($buffer);
802
803 484
                            if ($opCode === Opcodes::OP_NUMEQUALVERIFY) {
804 16
                                if ($this->castToBool($mainStack[-1])) {
805 16
                                    $mainStack->pop();
806 8
                                } else {
807
                                    throw new \RuntimeException('NUM EQUAL VERIFY error');
808
                                }
809 8
                            }
810 484
                            break;
811
812 1628
                        case Opcodes::OP_WITHIN:
813 60
                            if (count($mainStack) < 3) {
814 4
                                throw new \RuntimeException('Invalid stack operation');
815
                            }
816
817 56
                            $num1 = Number::buffer($mainStack[-3], $minimal)->getGmp();
818 52
                            $num2 = Number::buffer($mainStack[-2], $minimal)->getGmp();
819 48
                            $num3 = Number::buffer($mainStack[-1], $minimal)->getGmp();
820
821 44
                            $value = $this->math->cmp($num2, $num1) <= 0 && $this->math->cmp($num1, $num3) < 0;
822 44
                            $mainStack->pop();
823 44
                            $mainStack->pop();
824 44
                            $mainStack->pop();
825 44
                            $mainStack->push($value ? $this->vchTrue : $this->vchFalse);
826 44
                            break;
827
828
                        // Hash operation
829 1568
                        case Opcodes::OP_RIPEMD160:
830 1556
                        case Opcodes::OP_SHA1:
831 1540
                        case Opcodes::OP_SHA256:
832 1528
                        case Opcodes::OP_HASH160:
833 1446
                        case Opcodes::OP_HASH256:
834 430
                            if ($mainStack->isEmpty()) {
835 46
                                throw new \RuntimeException('Invalid stack operation');
836
                            }
837
838 384
                            $buffer = $mainStack[-1];
839 384
                            if ($opCode === Opcodes::OP_RIPEMD160) {
840 20
                                $hash = Hash::ripemd160($buffer);
841 376
                            } elseif ($opCode === Opcodes::OP_SHA1) {
842 24
                                $hash = Hash::sha1($buffer);
843 356
                            } elseif ($opCode === Opcodes::OP_SHA256) {
844 24
                                $hash = Hash::sha256($buffer);
845 336
                            } elseif ($opCode === Opcodes::OP_HASH160) {
846 308
                                $hash = Hash::sha256ripe160($buffer);
847 128
                            } else {
848 20
                                $hash = Hash::sha256d($buffer);
849
                            }
850
851 384
                            $mainStack->pop();
852 384
                            $mainStack->push($hash);
853 384
                            break;
854
855 1316
                        case Opcodes::OP_CODESEPARATOR:
856 4
                            $hashStartPos = $parser->getPosition();
857 4
                            break;
858
859 1312
                        case Opcodes::OP_CHECKSIG:
860 1038
                        case Opcodes::OP_CHECKSIGVERIFY:
861 472
                            if (count($mainStack) < 2) {
862 20
                                throw new \RuntimeException('Invalid stack operation');
863
                            }
864
865 464
                            $vchPubKey = $mainStack[-1];
866 464
                            $vchSig = $mainStack[-2];
867
868 464
                            $scriptCode = new Script($script->getBuffer()->slice($hashStartPos));
869
870 464
                            $success = $checker->checkSig($scriptCode, $vchSig, $vchPubKey, $sigVersion, $flags);
871
872 332
                            $mainStack->pop();
873 332
                            $mainStack->pop();
874 332
                            $mainStack->push($success ? $this->vchTrue : $this->vchFalse);
875
876 332
                            if ($opCode === Opcodes::OP_CHECKSIGVERIFY) {
877
                                if ($success) {
878
                                    $mainStack->pop();
879
                                } else {
880
                                    throw new \RuntimeException('Checksig verify');
881
                                }
882
                            }
883 332
                            break;
884
885 840
                        case Opcodes::OP_CHECKMULTISIG:
886 664
                        case Opcodes::OP_CHECKMULTISIGVERIFY:
887 458
                            $i = 1;
888 458
                            if (count($mainStack) < $i) {
889 4
                                throw new \RuntimeException('Invalid stack operation');
890
                            }
891
892 454
                            $keyCount = Number::buffer($mainStack[-$i], $minimal)->getInt();
893 446
                            if ($keyCount < 0 || $keyCount > 20) {
894 8
                                throw new \RuntimeException('OP_CHECKMULTISIG: Public key count exceeds 20');
895
                            }
896
897 438
                            $opCount += $keyCount;
898 438
                            $this->checkOpcodeCount($opCount);
899
900
                            // Extract positions of the keys, and signatures, from the stack.
901 438
                            $ikey = ++$i;
902 438
                            $i += $keyCount;
903 438
                            if (count($mainStack) < $i) {
904 4
                                throw new \RuntimeException('Invalid stack operation');
905
                            }
906
907 434
                            $sigCount = Number::buffer($mainStack[-$i], $minimal)->getInt();
908 422
                            if ($sigCount < 0 || $sigCount > $keyCount) {
909 8
                                throw new \RuntimeException('Invalid Signature count');
910
                            }
911
912 414
                            $isig = ++$i;
913 414
                            $i += $sigCount;
914
915
                            // Extract the script since the last OP_CODESEPARATOR
916 414
                            $scriptCode = new Script($script->getBuffer()->slice($hashStartPos));
917
918 414
                            $fSuccess = true;
919 414
                            while ($fSuccess && $sigCount > 0) {
920
                                // Fetch the signature and public key
921 174
                                $sig = $mainStack[-$isig];
922 170
                                $pubkey = $mainStack[-$ikey];
923
924 170
                                if ($checker->checkSig($scriptCode, $sig, $pubkey, $sigVersion, $flags)) {
925 90
                                    $isig++;
926 90
                                    $sigCount--;
927 38
                                }
928
929 142
                                $ikey++;
930 142
                                $keyCount--;
931
932
                                // If there are more signatures left than keys left,
933
                                // then too many signatures have failed. Exit early,
934
                                // without checking any further signatures.
935 142
                                if ($sigCount > $keyCount) {
936 72
                                    $fSuccess = false;
937 32
                                }
938 62
                            }
939
940 370
                            while ($i-- > 1) {
941 370
                                $mainStack->pop();
942 178
                            }
943
944
                            // A bug causes CHECKMULTISIG to consume one extra argument
945
                            // whose contents were not checked in any way.
946
                            //
947
                            // Unfortunately this is a potential source of mutability,
948
                            // so optionally verify it is exactly equal to zero prior
949
                            // to removing it from the stack.
950 370
                            if ($mainStack->isEmpty()) {
951 16
                                throw new \RuntimeException('Invalid stack operation');
952
                            }
953
954 370
                            if ($flags & self::VERIFY_NULL_DUMMY && $mainStack[-1]->getSize() !== 0) {
955 8
                                throw new ScriptRuntimeException(self::VERIFY_NULL_DUMMY, 'Extra P2SH stack value should be OP_0');
956
                            }
957
958 362
                            $mainStack->pop();
959 362
                            $mainStack->push($fSuccess ? $this->vchTrue : $this->vchFalse);
960
961 362
                            if ($opCode === Opcodes::OP_CHECKMULTISIGVERIFY) {
962 120
                                if ($fSuccess) {
963 120
                                    $mainStack->pop();
964 60
                                } else {
965
                                    throw new \RuntimeException('OP_CHECKMULTISIG verify');
966
                                }
967 60
                            }
968 362
                            break;
969
970 188
                        default:
971 382
                            throw new \RuntimeException('Opcode not found');
972 188
                    }
973
974 3990
                    if (count($mainStack) + count($altStack) > 1000) {
975 2300
                        throw new \RuntimeException('Invalid stack size, exceeds 1000');
976
                    }
977 1952
                }
978 2190
            }
979
980 4432
            if (count($vfStack) !== 0) {
981 24
                throw new \RuntimeException('Unbalanced conditional at script end');
982
            }
983
984 4412
            return true;
985 1672
        } catch (ScriptRuntimeException $e) {
986
            // echo "\n Runtime: " . $e->getMessage() . "\n" . $e->getTraceAsString() . PHP_EOL;
987
            // Failure due to script tags, can access flag: $e->getFailureFlag()
988 324
            return false;
989 1348
        } catch (\Exception $e) {
990
            // echo "\n General: " . $e->getMessage()  . PHP_EOL . $e->getTraceAsString() . PHP_EOL;
991 1348
            return false;
992
        }
993
    }
994
}
995