Completed
Pull Request — master (#403)
by thomas
69:15 queued 66:32
created

Interpreter::checkMinimalPush()   D

Complexity

Conditions 9
Paths 8

Size

Total Lines 25
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 9

Importance

Changes 0
Metric Value
cc 9
eloc 18
nc 8
nop 2
dl 0
loc 25
ccs 18
cts 18
cp 1
crap 9
rs 4.909
c 0
b 0
f 0
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 336
    public function __construct(EcAdapterInterface $ecAdapter = null)
56
    {
57 336
        $ecAdapter = $ecAdapter ?: Bitcoin::getEcAdapter();
58 336
        $this->math = $ecAdapter->getMath();
59 336
        $this->vchFalse = new Buffer("", 0, $this->math);
60 336
        $this->vchTrue = new Buffer("\x01", 1, $this->math);
61 336
    }
62
63
    /**
64
     * Cast the value to a boolean
65
     *
66
     * @param BufferInterface $value
67
     * @return bool
68
     */
69 3450
    public function castToBool(BufferInterface $value)
70
    {
71 3450
        $val = $value->getBinary();
72 3450
        for ($i = 0, $size = strlen($val); $i < $size; $i++) {
73 3166
            $chr = ord($val[$i]);
74 3166
            if ($chr !== 0) {
75 3160
                if (($i === ($size - 1)) && $chr === 0x80) {
76
                    return false;
77
                }
78 3160
                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 4396
    private function checkOpcodeCount($count)
137
    {
138 4396
        if ($count > 201) {
139 20
            throw new \RuntimeException('Error: Script op code count');
140
        }
141
142 4396
        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 4601
    public function verify(ScriptInterface $scriptSig, ScriptInterface $scriptPubKey, $flags, Checker $checker, ScriptWitnessInterface $witness = null)
219
    {
220 4601
        static $emptyWitness = null;
221 4601
        if ($emptyWitness === null) {
222 6
            $emptyWitness = new ScriptWitness([]);
223 2
        }
224
225 4601
        $witness = is_null($witness) ? $emptyWitness : $witness;
226
227 4601
        if (($flags & self::VERIFY_SIGPUSHONLY) !== 0 && !$scriptSig->isPushOnly()) {
228 8
            return false;
229
        }
230
231 4593
        $stack = new Stack();
232 4593
        if (!$this->evaluate($scriptSig, $stack, SigHash::V0, $flags, $checker)) {
233 226
            return false;
234
        }
235
236 4367
        $backup = [];
237 4367
        if ($flags & self::VERIFY_P2SH) {
238 3161
            foreach ($stack as $s) {
239 2562
                $backup[] = $s;
240 1559
            }
241 1559
        }
242
243 4367
        if (!$this->evaluate($scriptPubKey, $stack, SigHash::V0, $flags, $checker)) {
244 1413
            return false;
245
        }
246
247 2987
        if ($stack->isEmpty()) {
248 46
            return false;
249
        }
250
251 2941
        if (false === $this->castToBool($stack[-1])) {
252 200
            return false;
253
        }
254
255 2741
        $program = null;
256 2741
        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 2693
        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 2629
        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 2621
        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 2617
        return true;
339
    }
340
341
    /**
342
     * @param Stack $vfStack
343
     * @param bool $value
344
     * @return bool
345
     */
346 4652
    private function checkExec(Stack $vfStack, $value)
347
    {
348 4652
        $ret = 0;
349 4652
        foreach ($vfStack as $item) {
350 968
            if ($item === $value) {
351 800
                $ret++;
352 316
            }
353 2252
        }
354
355 4652
        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 4686
    public function evaluate(ScriptInterface $script, Stack $mainStack, $sigVersion, $flags, Checker $checker)
367
    {
368 4686
        $hashStartPos = 0;
369 4686
        $opCount = 0;
370 4686
        $zero = gmp_init(0, 10);
371 4686
        $altStack = new Stack();
372 4686
        $vfStack = new Stack();
373 4686
        $minimal = ($flags & self::VERIFY_MINIMALDATA) !== 0;
374 4686
        $parser = $script->getScriptParser();
375
376 4686
        if ($script->getBuffer()->getSize() > 10000) {
377 4
            return false;
378
        }
379
380
        try {
381 4686
            foreach ($parser as $operation) {
382 4652
                $opCode = $operation->getOp();
383 4652
                $pushData = $operation->getData();
384 4652
                $fExec = !$this->checkExec($vfStack, false);
385
386
                // If pushdata was written to
387 4652
                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 4646
                if ($opCode > Opcodes::OP_16 && ++$opCount) {
393 4396
                    $this->checkOpcodeCount($opCount);
394 2128
                }
395
396 4646
                if (in_array($opCode, $this->disabledOps, true)) {
397 96
                    throw new \RuntimeException('Disabled Opcode');
398
                }
399
400 4646
                if ($fExec && $operation->isPush()) {
401
                    // In range of a pushdata opcode
402 3458
                    if ($minimal && !$this->checkMinimalPush($opCode, $pushData)) {
403 84
                        throw new ScriptRuntimeException(self::VERIFY_MINIMALDATA, 'Minimal pushdata required');
404
                    }
405
406 3374
                    $mainStack->push($pushData);
407
                    // echo " - [pushed '" . $pushData->getHex() . "']\n";
408 4522
                } elseif ($fExec || (Opcodes::OP_IF <= $opCode && $opCode <= Opcodes::OP_ENDIF)) {
409
                    // echo "OPCODE - " . $script->getOpcodes()->getOp($opCode) . "\n";
410
                    switch ($opCode) {
411 4488
                        case Opcodes::OP_1NEGATE:
412 4488
                        case Opcodes::OP_1:
413 4444
                        case Opcodes::OP_2:
414 4436
                        case Opcodes::OP_3:
415 4436
                        case Opcodes::OP_4:
416 4436
                        case Opcodes::OP_5:
417 4436
                        case Opcodes::OP_6:
418 4436
                        case Opcodes::OP_7:
419 4434
                        case Opcodes::OP_8:
420 4434
                        case Opcodes::OP_9:
421 4434
                        case Opcodes::OP_10:
422 4434
                        case Opcodes::OP_11:
423 4432
                        case Opcodes::OP_12:
424 4432
                        case Opcodes::OP_13:
425 4432
                        case Opcodes::OP_14:
426 4432
                        case Opcodes::OP_15:
427 4432
                        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 4376
                        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 4372
                        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 4344
                        case Opcodes::OP_NOP1:
479 4342
                        case Opcodes::OP_NOP4:
480 4340
                        case Opcodes::OP_NOP5:
481 4338
                        case Opcodes::OP_NOP6:
482 4336
                        case Opcodes::OP_NOP7:
483 4334
                        case Opcodes::OP_NOP8:
484 4332
                        case Opcodes::OP_NOP9:
485 4330
                        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 4304
                        case Opcodes::OP_NOP:
492 336
                            break;
493
494 4212
                        case Opcodes::OP_IF:
495 4168
                        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 4116
                        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 4104
                        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 3560
                        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 3532
                        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 3524
                        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 3512
                        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 3500
                        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 3464
                        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 3452
                        case Opcodes::OP_DUP:
576 232
                            if ($mainStack->isEmpty()) {
577 44
                                throw new \RuntimeException('Invalid stack operation OP_DUP');
578
                            }
579 224
                            $vch = $mainStack[-1];
580 224
                            $mainStack->push($vch);
581 224
                            break;
582
583 3416
                        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 3392
                        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 3376
                        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 3352
                        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 3336
                        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 3320
                        case Opcodes::OP_PICK:
622 3302
                        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 3252
                        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 3244
                        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 3228
                        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 3188
                        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 3172
                        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 3164
                        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 3148
                        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 3136
                        case Opcodes::OP_EQUAL:
709 2914
                        case Opcodes::OP_EQUALVERIFY:
710 1316
                            if (count($mainStack) < 2) {
711 16
                                throw new \RuntimeException('Invalid stack operation OP_EQUAL');
712
                            }
713
714 1300
                            $equal = $mainStack[-2]->equals($mainStack[-1]);
715 1300
                            $mainStack->pop();
716 1300
                            $mainStack->pop();
717 1300
                            $mainStack->push($equal ? $this->vchTrue : $this->vchFalse);
718 1300
                            if ($opCode === Opcodes::OP_EQUALVERIFY) {
719 300
                                if ($equal) {
720 258
                                    $mainStack->pop();
721 110
                                } else {
722 42
                                    throw new \RuntimeException('Error EQUALVERIFY');
723
                                }
724 110
                            }
725
726 1262
                            break;
727
728
                        // Arithmetic operations
729 2568
                        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 2332
                        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 1676
                        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 1616
                        case Opcodes::OP_RIPEMD160:
830 1604
                        case Opcodes::OP_SHA1:
831 1588
                        case Opcodes::OP_SHA256:
832 1576
                        case Opcodes::OP_HASH160:
833 1494
                        case Opcodes::OP_HASH256:
834 478
                            if ($mainStack->isEmpty()) {
835 46
                                throw new \RuntimeException('Invalid stack operation');
836
                            }
837
838 432
                            $buffer = $mainStack[-1];
839 432
                            if ($opCode === Opcodes::OP_RIPEMD160) {
840 20
                                $hash = Hash::ripemd160($buffer);
841 424
                            } elseif ($opCode === Opcodes::OP_SHA1) {
842 24
                                $hash = Hash::sha1($buffer);
843 404
                            } elseif ($opCode === Opcodes::OP_SHA256) {
844 24
                                $hash = Hash::sha256($buffer);
845 384
                            } elseif ($opCode === Opcodes::OP_HASH160) {
846 356
                                $hash = Hash::sha256ripe160($buffer);
847 144
                            } else {
848 20
                                $hash = Hash::sha256d($buffer);
849
                            }
850
851 432
                            $mainStack->pop();
852 432
                            $mainStack->push($hash);
853 432
                            break;
854
855 1364
                        case Opcodes::OP_CODESEPARATOR:
856 4
                            $hashStartPos = $parser->getPosition();
857 4
                            break;
858
859 1360
                        case Opcodes::OP_CHECKSIG:
860 1054
                        case Opcodes::OP_CHECKSIGVERIFY:
861 520
                            if (count($mainStack) < 2) {
862 20
                                throw new \RuntimeException('Invalid stack operation');
863
                            }
864
865 512
                            $vchPubKey = $mainStack[-1];
866 512
                            $vchSig = $mainStack[-2];
867
868 512
                            $scriptCode = new Script($script->getBuffer()->slice($hashStartPos));
869
870 512
                            $success = $checker->checkSig($scriptCode, $vchSig, $vchPubKey, $sigVersion, $flags);
871
872 380
                            $mainStack->pop();
873 380
                            $mainStack->pop();
874 380
                            $mainStack->push($success ? $this->vchTrue : $this->vchFalse);
875
876 380
                            if ($opCode === Opcodes::OP_CHECKSIGVERIFY) {
877
                                if ($success) {
878
                                    $mainStack->pop();
879
                                } else {
880
                                    throw new \RuntimeException('Checksig verify');
881
                                }
882
                            }
883 380
                            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 4038
                    if (count($mainStack) + count($altStack) > 1000) {
975 2332
                        throw new \RuntimeException('Invalid stack size, exceeds 1000');
976
                    }
977 1968
                }
978 2206
            }
979
980 4480
            if (count($vfStack) !== 0) {
981 24
                throw new \RuntimeException('Unbalanced conditional at script end');
982
            }
983
984 4460
            return true;
985 1696
        } 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 1372
        } catch (\Exception $e) {
990
            // echo "\n General: " . $e->getMessage()  . PHP_EOL . $e->getTraceAsString() . PHP_EOL;
991 1372
            return false;
992
        }
993
    }
994
}
995