Completed
Pull Request — master (#403)
by thomas
27:54
created

Interpreter::castToBool()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 5.025

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 9
c 1
b 0
f 0
nc 4
nop 1
dl 0
loc 14
ccs 9
cts 10
cp 0.9
crap 5.025
rs 8.8571
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 1860
    public function castToBool(BufferInterface $value)
70
    {
71 1860
        $val = $value->getBinary();
72 1860
        for ($i = 0, $size = strlen($val); $i < $size; $i++) {
73 1706
            $chr = ord($val[$i]);
74 1706
            if ($chr !== 0) {
75 1700
                if (($i === ($size - 1)) && $chr === 0x80) {
76
                    return false;
77
                }
78 1700
                return true;
79
            }
80 2
        }
81 416
        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 236
    public function checkMinimalPush($opCode, BufferInterface $pushData)
107
    {
108 236
        $pushSize = $pushData->getSize();
109 236
        $binary = $pushData->getBinary();
110
111 236
        if ($pushSize === 0) {
112 114
            return $opCode === Opcodes::OP_0;
113 194
        } elseif ($pushSize === 1) {
114 50
            $first = ord($binary[0]);
115
116 50
            if ($first >= 1 && $first <= 16) {
117 38
                return $opCode === (Opcodes::OP_1 + ($first - 1));
118 18
            } elseif ($first === 0x81) {
119 18
                return $opCode === Opcodes::OP_1NEGATE;
120
            }
121 150
        } elseif ($pushSize <= 75) {
122 146
            return $opCode === $pushSize;
123 10
        } elseif ($pushSize <= 255) {
124 8
            return $opCode === Opcodes::OP_PUSHDATA1;
125 8
        } elseif ($pushSize <= 65535) {
126 8
            return $opCode === Opcodes::OP_PUSHDATA2;
127
        }
128
129 16
        return true;
130
    }
131
132
    /**
133
     * @param int $count
134
     * @return $this
135
     */
136 2408
    private function checkOpcodeCount($count)
137
    {
138 2408
        if ($count > 201) {
139 10
            throw new \RuntimeException('Error: Script op code count');
140
        }
141
142 2408
        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 78
    private function verifyWitnessProgram(WitnessProgram $witnessProgram, ScriptWitnessInterface $scriptWitness, $flags, Checker $checker)
153
    {
154 77
        $witnessCount = count($scriptWitness);
155
156 77
        if ($witnessProgram->getVersion() === 0) {
157 75
            $buffer = $witnessProgram->getProgram();
158 75
            if ($buffer->getSize() === 32) {
159
                // Version 0 segregated witness program: SHA256(Script) in program, Script + inputs in witness
160 47
                if ($witnessCount === 0) {
161
                    // Must contain script at least
162 2
                    return false;
163
                }
164
165 45
                $scriptPubKey = new Script($scriptWitness[$witnessCount - 1]);
166 45
                $stackValues = $scriptWitness->slice(0, -1);
167 45
                $hashScriptPubKey = Hash::sha256($scriptPubKey->getBuffer());
168
169 45
                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 36
                    return false;
171
                }
172 37
            } elseif ($buffer->getSize() === 20) {
173
                // Version 0 special case for pay-to-pubkeyhash
174 26
                if ($witnessCount !== 2) {
175
                    // 2 items in witness - <signature> <pubkey>
176 10
                    return false;
177
                }
178
179 24
                $scriptPubKey = ScriptFactory::scriptPubKey()->payToPubKeyHash($buffer);
180 24
                $stackValues = $scriptWitness;
181 4
            } else {
182 54
                return false;
183
            }
184 15
        } elseif ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM) {
185 2
            return false;
186
        } else {
187
            return false;
188
        }
189
190 65
        $mainStack = new Stack();
191 65
        foreach ($stackValues as $value) {
192 63
            $mainStack->push($value);
193 13
        }
194
195 65
        if (!$this->evaluate($scriptPubKey, $mainStack, SigHash::V1, $flags, $checker)) {
196 18
            return false;
197
        }
198
199 65
        if ($mainStack->count() !== 1) {
200
            return false;
201
        }
202
203 65
        if (!$this->castToBool($mainStack->bottom())) {
204 18
            return false;
205
        }
206
207 47
        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 2485
    public function verify(ScriptInterface $scriptSig, ScriptInterface $scriptPubKey, $flags, Checker $checker, ScriptWitnessInterface $witness = null)
219
    {
220 2485
        static $emptyWitness = null;
221 2485
        if ($emptyWitness === null) {
222 6
            $emptyWitness = new ScriptWitness([]);
223 2
        }
224
225 2485
        $witness = is_null($witness) ? $emptyWitness : $witness;
226
227 2485
        if (($flags & self::VERIFY_SIGPUSHONLY) !== 0 && !$scriptSig->isPushOnly()) {
228 4
            return false;
229
        }
230
231 2481
        $stack = new Stack();
232 2481
        if (!$this->evaluate($scriptSig, $stack, SigHash::V0, $flags, $checker)) {
233 116
            return false;
234
        }
235
236 2365
        $backup = [];
237 2365
        if ($flags & self::VERIFY_P2SH) {
238 1645
            foreach ($stack as $s) {
239 1332
                $backup[] = $s;
240 43
            }
241 43
        }
242
243 2365
        if (!$this->evaluate($scriptPubKey, $stack, SigHash::V0, $flags, $checker)) {
244 795
            return false;
245
        }
246
247 1603
        if ($stack->isEmpty()) {
248 26
            return false;
249
        }
250
251 1577
        if (false === $this->castToBool($stack[-1])) {
252 112
            return false;
253
        }
254
255 1465
        $program = null;
256 1465
        if ($flags & self::VERIFY_WITNESS) {
257 101
            if ($scriptPubKey->isWitness($program)) {
258
                /** @var WitnessProgram $program */
259 49
                if ($scriptSig->getBuffer()->getSize() !== 0) {
260 2
                    return false;
261
                }
262
263 47
                if (!$this->verifyWitnessProgram($program, $witness, $flags, $checker)) {
264 34
                    return false;
265
                }
266
267 25
                $stack->resize(1);
268 7
            }
269 19
        }
270
271 1441
        if ($flags & self::VERIFY_P2SH && (new OutputClassifier())->isPayToScriptHash($scriptPubKey)) {
272 98
            if (!$scriptSig->isPushOnly()) {
273 12
                return false;
274
            }
275
276 86
            $stack = new Stack();
277 86
            foreach ($backup as $i) {
278 86
                $stack->push($i);
279 14
            }
280
281
            // Restore mainStack to how it was after evaluating scriptSig
282 86
            if ($stack->isEmpty()) {
283
                return false;
284
            }
285
286
            // Load redeemscript as the scriptPubKey
287 86
            $scriptPubKey = new Script($stack->bottom());
288 86
            $stack->pop();
289
290 86
            if (!$this->evaluate($scriptPubKey, $stack, 0, $flags, $checker)) {
291 23
                return false;
292
            }
293
294 72
            if ($stack->isEmpty()) {
295
                return false;
296
            }
297
298 72
            if (!$this->castToBool($stack->bottom())) {
299 2
                return false;
300
            }
301
302 70
            if ($flags & self::VERIFY_WITNESS) {
303 38
                if ($scriptPubKey->isWitness($program)) {
304
                    /** @var WitnessProgram $program */
305 32
                    if (!$scriptSig->equals(ScriptFactory::sequence([$scriptPubKey->getBuffer()]))) {
306 2
                        return false; // SCRIPT_ERR_WITNESS_MALLEATED_P2SH
307
                    }
308
309 30
                    if (!$this->verifyWitnessProgram($program, $witness, $flags, $checker)) {
310 20
                        return false;
311
                    }
312
313 22
                    $stack->resize(1);
314 6
                }
315 8
            }
316 12
        }
317
318 1403
        if ($flags & self::VERIFY_CLEAN_STACK) {
319 24
            if (!($flags & self::VERIFY_P2SH !== 0) && ($flags & self::VERIFY_WITNESS !== 0)) {
320
                return false; // implied flags required
321
            }
322
323 24
            if (count($stack) !== 1) {
324 4
                return false; // Cleanstack
325
            }
326 6
        }
327
328 1399
        if ($flags & self::VERIFY_WITNESS) {
329 67
            if (!$flags & self::VERIFY_P2SH) {
330
                return false; //
331
            }
332
333 67
            if ($program === null && !$witness->isNull()) {
334 2
                return false; // SCRIPT_ERR_WITNESS_UNEXPECTED
335
            }
336 19
        }
337
338 1397
        return true;
339
    }
340
341
    /**
342
     * @param Stack $vfStack
343
     * @param bool $value
344
     * @return bool
345
     */
346 2548
    private function checkExec(Stack $vfStack, $value)
347
    {
348 2548
        $ret = 0;
349 2548
        foreach ($vfStack as $item) {
350 484
            if ($item === $value) {
351 484
                $ret++;
352
            }
353 148
        }
354
355 2548
        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 2574
    public function evaluate(ScriptInterface $script, Stack $mainStack, $sigVersion, $flags, Checker $checker)
367
    {
368 2574
        $hashStartPos = 0;
369 2574
        $opCount = 0;
370 2574
        $zero = gmp_init(0, 10);
371 2574
        $altStack = new Stack();
372 2574
        $vfStack = new Stack();
373 2574
        $minimal = ($flags & self::VERIFY_MINIMALDATA) !== 0;
374 2574
        $parser = $script->getScriptParser();
375
376 2574
        if ($script->getBuffer()->getSize() > 10000) {
377 2
            return false;
378
        }
379
380
        try {
381 2574
            foreach ($parser as $operation) {
382 2548
                $opCode = $operation->getOp();
383 2548
                $pushData = $operation->getData();
384 2548
                $fExec = !$this->checkExec($vfStack, false);
385
386
                // If pushdata was written to
387 2548
                if ($operation->isPush() && $operation->getDataSize() > InterpreterInterface::MAX_SCRIPT_ELEMENT_SIZE) {
388 10
                    throw new \RuntimeException('Error - push size');
389
                }
390
391
                // OP_RESERVED should not count towards opCount
392 2542
                if ($opCode > Opcodes::OP_16 && ++$opCount) {
393 2408
                    $this->checkOpcodeCount($opCount);
394 140
                }
395
396 2542
                if (in_array($opCode, $this->disabledOps, true)) {
397 48
                    throw new \RuntimeException('Disabled Opcode');
398
                }
399
400 2542
                if ($fExec && $operation->isPush()) {
401
                    // In range of a pushdata opcode
402 1942
                    if ($minimal && !$this->checkMinimalPush($opCode, $pushData)) {
403 42
                        throw new ScriptRuntimeException(self::VERIFY_MINIMALDATA, 'Minimal pushdata required');
404
                    }
405
406 1900
                    $mainStack->push($pushData);
407
                    // echo " - [pushed '" . $pushData->getHex() . "']\n";
408 2460
                } elseif ($fExec || (Opcodes::OP_IF <= $opCode && $opCode <= Opcodes::OP_ENDIF)) {
409
                    // echo "OPCODE - " . $script->getOpcodes()->getOp($opCode) . "\n";
410
                    switch ($opCode) {
411 2454
                        case Opcodes::OP_1NEGATE:
412 2454
                        case Opcodes::OP_1:
413 2410
                        case Opcodes::OP_2:
414 2402
                        case Opcodes::OP_3:
415 2402
                        case Opcodes::OP_4:
416 2402
                        case Opcodes::OP_5:
417 2402
                        case Opcodes::OP_6:
418 2402
                        case Opcodes::OP_7:
419 2400
                        case Opcodes::OP_8:
420 2400
                        case Opcodes::OP_9:
421 2400
                        case Opcodes::OP_10:
422 2400
                        case Opcodes::OP_11:
423 2398
                        case Opcodes::OP_12:
424 2398
                        case Opcodes::OP_13:
425 2398
                        case Opcodes::OP_14:
426 2398
                        case Opcodes::OP_15:
427 2398
                        case Opcodes::OP_16:
428 1374
                            $num = \BitWasp\Bitcoin\Script\decodeOpN($opCode);
429 1374
                            $mainStack->push(Number::int($num)->getBuffer());
430 1374
                            break;
431
432 2398
                        case Opcodes::OP_CHECKLOCKTIMEVERIFY:
433 12
                            if (!($flags & self::VERIFY_CHECKLOCKTIMEVERIFY)) {
434 12
                                if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
435 2
                                    throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
436
                                }
437 10
                                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 2396
                        case Opcodes::OP_CHECKSEQUENCEVERIFY:
452 24
                            if (!($flags & self::VERIFY_CHECKSEQUENCEVERIFY)) {
453 12
                                if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
454 2
                                    throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
455
                                }
456 10
                                break;
457
                            }
458
459 12
                            if ($mainStack->isEmpty()) {
460 2
                                throw new \RuntimeException('Invalid stack operation - CSV');
461
                            }
462
463 10
                            $sequence = Number::buffer($mainStack[-1], $minimal, 5, $this->math);
464 8
                            $nSequence = $sequence->getGmp();
465 8
                            if ($this->math->cmp($nSequence, $zero) < 0) {
466 2
                                throw new ScriptRuntimeException(self::VERIFY_CHECKSEQUENCEVERIFY, 'Negative locktime');
467
                            }
468
469 6
                            if ($this->math->cmp($this->math->bitwiseAnd($nSequence, gmp_init(TransactionInputInterface::SEQUENCE_LOCKTIME_DISABLE_FLAG, 10)), $zero) !== 0) {
470 2
                                break;
471
                            }
472
473 4
                            if (!$checker->checkSequence($sequence)) {
474 4
                                throw new ScriptRuntimeException(self::VERIFY_CHECKSEQUENCEVERIFY, 'Unsatisfied sequence');
475
                            }
476
                            break;
477
478 2382
                        case Opcodes::OP_NOP1:
479 2380
                        case Opcodes::OP_NOP4:
480 2378
                        case Opcodes::OP_NOP5:
481 2376
                        case Opcodes::OP_NOP6:
482 2374
                        case Opcodes::OP_NOP7:
483 2372
                        case Opcodes::OP_NOP8:
484 2370
                        case Opcodes::OP_NOP9:
485 2368
                        case Opcodes::OP_NOP10:
486 54
                            if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
487 20
                                throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
488
                            }
489 34
                            break;
490
491 2362
                        case Opcodes::OP_NOP:
492 168
                            break;
493
494 2316
                        case Opcodes::OP_IF:
495 2272
                        case Opcodes::OP_NOTIF:
496
                            // <expression> if [statements] [else [statements]] endif
497 494
                            $value = false;
498 494
                            if ($fExec) {
499 494
                                if ($mainStack->isEmpty()) {
500 4
                                    throw new \RuntimeException('Unbalanced conditional');
501
                                }
502
503 490
                                $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 490
                                $value = $this->castToBool($buffer);
505 490
                                if ($opCode === Opcodes::OP_NOTIF) {
506 34
                                    $value = !$value;
507
                                }
508
                            }
509 490
                            $vfStack->push($value);
510 490
                            break;
511
512 2268
                        case Opcodes::OP_ELSE:
513 230
                            if ($vfStack->isEmpty()) {
514 8
                                throw new \RuntimeException('Unbalanced conditional');
515
                            }
516 226
                            $vfStack->push(!$vfStack->pop());
517 226
                            break;
518
519 2262
                        case Opcodes::OP_ENDIF:
520 294
                            if ($vfStack->isEmpty()) {
521 14
                                throw new \RuntimeException('Unbalanced conditional');
522
                            }
523 286
                            $vfStack->pop();
524 286
                            break;
525
526 1990
                        case Opcodes::OP_VERIFY:
527 60
                            if ($mainStack->isEmpty()) {
528 2
                                throw new \RuntimeException('Invalid stack operation');
529
                            }
530 58
                            $value = $this->castToBool($mainStack[-1]);
531 58
                            if (!$value) {
532 2
                                throw new \RuntimeException('Error: verify');
533
                            }
534 56
                            $mainStack->pop();
535 56
                            break;
536
537 1976
                        case Opcodes::OP_TOALTSTACK:
538 16
                            if ($mainStack->isEmpty()) {
539 2
                                throw new \RuntimeException('Invalid stack operation OP_TOALTSTACK');
540
                            }
541 14
                            $altStack->push($mainStack->pop());
542 14
                            break;
543
544 1972
                        case Opcodes::OP_FROMALTSTACK:
545 10
                            if ($altStack->isEmpty()) {
546 4
                                throw new \RuntimeException('Invalid alt-stack operation OP_FROMALTSTACK');
547
                            }
548 6
                            $mainStack->push($altStack->pop());
549 6
                            break;
550
551 1966
                        case Opcodes::OP_IFDUP:
552
                            // If top value not zero, duplicate it.
553 12
                            if ($mainStack->isEmpty()) {
554 4
                                throw new \RuntimeException('Invalid stack operation OP_IFDUP');
555
                            }
556 8
                            $vch = $mainStack[-1];
557 8
                            if ($this->castToBool($vch)) {
558 6
                                $mainStack->push($vch);
559
                            }
560 8
                            break;
561
562 1960
                        case Opcodes::OP_DEPTH:
563 156
                            $num = count($mainStack);
564 156
                            $depth = Number::int($num)->getBuffer();
565 156
                            $mainStack->push($depth);
566 156
                            break;
567
568 1942
                        case Opcodes::OP_DROP:
569 96
                            if ($mainStack->isEmpty()) {
570 4
                                throw new \RuntimeException('Invalid stack operation OP_DROP');
571
                            }
572 92
                            $mainStack->pop();
573 92
                            break;
574
575 1936
                        case Opcodes::OP_DUP:
576 176
                            if ($mainStack->isEmpty()) {
577 40
                                throw new \RuntimeException('Invalid stack operation OP_DUP');
578
                            }
579 172
                            $vch = $mainStack[-1];
580 172
                            $mainStack->push($vch);
581 172
                            break;
582
583 1918
                        case Opcodes::OP_NIP:
584 12
                            if (count($mainStack) < 2) {
585 6
                                throw new \RuntimeException('Invalid stack operation OP_NIP');
586
                            }
587 6
                            unset($mainStack[-2]);
588 6
                            break;
589
590 1906
                        case Opcodes::OP_OVER:
591 12
                            if (count($mainStack) < 2) {
592 6
                                throw new \RuntimeException('Invalid stack operation OP_OVER');
593
                            }
594 6
                            $vch = $mainStack[-2];
595 6
                            $mainStack->push($vch);
596 6
                            break;
597
598 1898
                        case Opcodes::OP_ROT:
599 24
                            if (count($mainStack) < 3) {
600 8
                                throw new \RuntimeException('Invalid stack operation OP_ROT');
601
                            }
602 16
                            $mainStack->swap(-3, -2);
603 16
                            $mainStack->swap(-2, -1);
604 16
                            break;
605
606 1886
                        case Opcodes::OP_SWAP:
607 20
                            if (count($mainStack) < 2) {
608 6
                                throw new \RuntimeException('Invalid stack operation OP_SWAP');
609
                            }
610 14
                            $mainStack->swap(-2, -1);
611 14
                            break;
612
613 1878
                        case Opcodes::OP_TUCK:
614 12
                            if (count($mainStack) < 2) {
615 6
                                throw new \RuntimeException('Invalid stack operation OP_TUCK');
616
                            }
617 6
                            $vch = $mainStack[-1];
618 6
                            $mainStack->add(- 2, $vch);
619 6
                            break;
620
621 1870
                        case Opcodes::OP_PICK:
622 1852
                        case Opcodes::OP_ROLL:
623 58
                            if (count($mainStack) < 2) {
624 8
                                throw new \RuntimeException('Invalid stack operation OP_PICK');
625
                            }
626
627 50
                            $n = Number::buffer($mainStack[-1], $minimal, 4)->getGmp();
628 46
                            $mainStack->pop();
629 46
                            if ($this->math->cmp($n, $zero) < 0 || $this->math->cmp($n, gmp_init(count($mainStack))) >= 0) {
630 10
                                throw new \RuntimeException('Invalid stack operation OP_PICK');
631
                            }
632
633 36
                            $pos = (int) gmp_strval($this->math->sub($this->math->sub($zero, $n), gmp_init(1)), 10);
634 36
                            $vch = $mainStack[$pos];
635 36
                            if ($opCode === Opcodes::OP_ROLL) {
636 18
                                unset($mainStack[$pos]);
637
                            }
638 36
                            $mainStack->push($vch);
639 36
                            break;
640
641 1836
                        case Opcodes::OP_2DROP:
642 18
                            if (count($mainStack) < 2) {
643 2
                                throw new \RuntimeException('Invalid stack operation OP_2DROP');
644
                            }
645 16
                            $mainStack->pop();
646 16
                            $mainStack->pop();
647 16
                            break;
648
649 1832
                        case Opcodes::OP_2DUP:
650 12
                            if (count($mainStack) < 2) {
651 6
                                throw new \RuntimeException('Invalid stack operation OP_2DUP');
652
                            }
653 6
                            $string1 = $mainStack[-2];
654 6
                            $string2 = $mainStack[-1];
655 6
                            $mainStack->push($string1);
656 6
                            $mainStack->push($string2);
657 6
                            break;
658
659 1824
                        case Opcodes::OP_3DUP:
660 22
                            if (count($mainStack) < 3) {
661 8
                                throw new \RuntimeException('Invalid stack operation OP_3DUP');
662
                            }
663 14
                            $string1 = $mainStack[-3];
664 14
                            $string2 = $mainStack[-2];
665 14
                            $string3 = $mainStack[-1];
666 14
                            $mainStack->push($string1);
667 14
                            $mainStack->push($string2);
668 14
                            $mainStack->push($string3);
669 14
                            break;
670
671 1804
                        case Opcodes::OP_2OVER:
672 10
                            if (count($mainStack) < 4) {
673 6
                                throw new \RuntimeException('Invalid stack operation OP_2OVER');
674
                            }
675 4
                            $string1 = $mainStack[-4];
676 4
                            $string2 = $mainStack[-3];
677 4
                            $mainStack->push($string1);
678 4
                            $mainStack->push($string2);
679 4
                            break;
680
681 1796
                        case Opcodes::OP_2ROT:
682 20
                            if (count($mainStack) < 6) {
683 2
                                throw new \RuntimeException('Invalid stack operation OP_2ROT');
684
                            }
685 18
                            $string1 = $mainStack[-6];
686 18
                            $string2 = $mainStack[-5];
687 18
                            unset($mainStack[-6], $mainStack[-5]);
688 18
                            $mainStack->push($string1);
689 18
                            $mainStack->push($string2);
690 18
                            break;
691
692 1792
                        case Opcodes::OP_2SWAP:
693 10
                            if (count($mainStack) < 4) {
694 6
                                throw new \RuntimeException('Invalid stack operation OP_2SWAP');
695
                            }
696 4
                            $mainStack->swap(-3, -1);
697 4
                            $mainStack->swap(-4, -2);
698 4
                            break;
699
700 1784
                        case Opcodes::OP_SIZE:
701 62
                            if ($mainStack->isEmpty()) {
702 4
                                throw new \RuntimeException('Invalid stack operation OP_SIZE');
703
                            }
704 58
                            $size = Number::int($mainStack[-1]->getSize());
705 58
                            $mainStack->push($size->getBuffer());
706 58
                            break;
707
708 1778
                        case Opcodes::OP_EQUAL:
709 1556
                        case Opcodes::OP_EQUALVERIFY:
710 760
                            if (count($mainStack) < 2) {
711 8
                                throw new \RuntimeException('Invalid stack operation OP_EQUAL');
712
                            }
713
714 752
                            $equal = $mainStack[-2]->equals($mainStack[-1]);
715 752
                            $mainStack->pop();
716 752
                            $mainStack->pop();
717 752
                            $mainStack->push($equal ? $this->vchTrue : $this->vchFalse);
718 752
                            if ($opCode === Opcodes::OP_EQUALVERIFY) {
719 210
                                if ($equal) {
720 186
                                    $mainStack->pop();
721 38
                                } else {
722 24
                                    throw new \RuntimeException('Error EQUALVERIFY');
723
                                }
724 38
                            }
725
726 730
                            break;
727
728
                        // Arithmetic operations
729 1494
                        case $opCode >= Opcodes::OP_1ADD && $opCode <= Opcodes::OP_0NOTEQUAL:
730 216
                            if ($mainStack->isEmpty()) {
731 12
                                throw new \Exception('Invalid stack operation 1ADD-OP_0NOTEQUAL');
732
                            }
733
734 204
                            $num = Number::buffer($mainStack[-1], $minimal)->getGmp();
735
736 158
                            if ($opCode === Opcodes::OP_1ADD) {
737 14
                                $num = $this->math->add($num, gmp_init(1));
738 144
                            } elseif ($opCode === Opcodes::OP_1SUB) {
739 6
                                $num = $this->math->sub($num, gmp_init(1));
740 138
                            } elseif ($opCode === Opcodes::OP_2MUL) {
741
                                $num = $this->math->mul(gmp_init(2), $num);
742 138
                            } elseif ($opCode === Opcodes::OP_NEGATE) {
743 8
                                $num = $this->math->sub($zero, $num);
744 132
                            } elseif ($opCode === Opcodes::OP_ABS) {
745 10
                                if ($this->math->cmp($num, $zero) < 0) {
746 10
                                    $num = $this->math->sub($zero, $num);
747
                                }
748 122
                            } elseif ($opCode === Opcodes::OP_NOT) {
749 110
                                $num = gmp_init($this->math->cmp($num, $zero) === 0 ? 1 : 0);
750 4
                            } else {
751
                                // is OP_0NOTEQUAL
752 12
                                $num = gmp_init($this->math->cmp($num, $zero) !== 0 ? 1 : 0);
753
                            }
754
755 158
                            $mainStack->pop();
756
757 158
                            $buffer = Number::int(gmp_strval($num, 10))->getBuffer();
758
759 158
                            $mainStack->push($buffer);
760 158
                            break;
761
762 1376
                        case $opCode >= Opcodes::OP_ADD && $opCode <= Opcodes::OP_MAX:
763 328
                            if (count($mainStack) < 2) {
764 26
                                throw new \Exception('Invalid stack operation (OP_ADD - OP_MAX)');
765
                            }
766
767 302
                            $num1 = Number::buffer($mainStack[-2], $minimal)->getGmp();
768 268
                            $num2 = Number::buffer($mainStack[-1], $minimal)->getGmp();
769
770 242
                            if ($opCode === Opcodes::OP_ADD) {
771 60
                                $num = $this->math->add($num1, $num2);
772 194
                            } else if ($opCode === Opcodes::OP_SUB) {
773 12
                                $num = $this->math->sub($num1, $num2);
774 182
                            } else if ($opCode === Opcodes::OP_BOOLAND) {
775 16
                                $num = $this->math->cmp($num1, $zero) !== 0 && $this->math->cmp($num2, $zero) !== 0;
776 166
                            } else if ($opCode === Opcodes::OP_BOOLOR) {
777 16
                                $num = $this->math->cmp($num1, $zero) !== 0 || $this->math->cmp($num2, $zero) !== 0;
778 150
                            } elseif ($opCode === Opcodes::OP_NUMEQUAL) {
779 56
                                $num = $this->math->cmp($num1, $num2) === 0;
780 110
                            } elseif ($opCode === Opcodes::OP_NUMEQUALVERIFY) {
781 8
                                $num = $this->math->cmp($num1, $num2) === 0;
782 102
                            } elseif ($opCode === Opcodes::OP_NUMNOTEQUAL) {
783 10
                                $num = $this->math->cmp($num1, $num2) !== 0;
784 92
                            } elseif ($opCode === Opcodes::OP_LESSTHAN) {
785 16
                                $num = $this->math->cmp($num1, $num2) < 0;
786 76
                            } elseif ($opCode === Opcodes::OP_GREATERTHAN) {
787 16
                                $num = $this->math->cmp($num1, $num2) > 0;
788 60
                            } elseif ($opCode === Opcodes::OP_LESSTHANOREQUAL) {
789 16
                                $num = $this->math->cmp($num1, $num2) <= 0;
790 44
                            } elseif ($opCode === Opcodes::OP_GREATERTHANOREQUAL) {
791 16
                                $num = $this->math->cmp($num1, $num2) >= 0;
792 28
                            } elseif ($opCode === Opcodes::OP_MIN) {
793 14
                                $num = ($this->math->cmp($num1, $num2) <= 0) ? $num1 : $num2;
794
                            } else {
795 14
                                $num = ($this->math->cmp($num1, $num2) >= 0) ? $num1 : $num2;
796
                            }
797
798 242
                            $mainStack->pop();
799 242
                            $mainStack->pop();
800 242
                            $buffer = Number::int(gmp_strval($num, 10))->getBuffer();
801 242
                            $mainStack->push($buffer);
802
803 242
                            if ($opCode === Opcodes::OP_NUMEQUALVERIFY) {
804 8
                                if ($this->castToBool($mainStack[-1])) {
805 8
                                    $mainStack->pop();
806
                                } else {
807
                                    throw new \RuntimeException('NUM EQUAL VERIFY error');
808
                                }
809
                            }
810 242
                            break;
811
812 1048
                        case Opcodes::OP_WITHIN:
813 30
                            if (count($mainStack) < 3) {
814 2
                                throw new \RuntimeException('Invalid stack operation');
815
                            }
816
817 28
                            $num1 = Number::buffer($mainStack[-3], $minimal)->getGmp();
818 26
                            $num2 = Number::buffer($mainStack[-2], $minimal)->getGmp();
819 24
                            $num3 = Number::buffer($mainStack[-1], $minimal)->getGmp();
820
821 22
                            $value = $this->math->cmp($num2, $num1) <= 0 && $this->math->cmp($num1, $num3) < 0;
822 22
                            $mainStack->pop();
823 22
                            $mainStack->pop();
824 22
                            $mainStack->pop();
825 22
                            $mainStack->push($value ? $this->vchTrue : $this->vchFalse);
826 22
                            break;
827
828
                        // Hash operation
829 1018
                        case Opcodes::OP_RIPEMD160:
830 1006
                        case Opcodes::OP_SHA1:
831 990
                        case Opcodes::OP_SHA256:
832 978
                        case Opcodes::OP_HASH160:
833 896
                        case Opcodes::OP_HASH256:
834 344
                            if ($mainStack->isEmpty()) {
835 26
                                throw new \RuntimeException('Invalid stack operation');
836
                            }
837
838 318
                            $buffer = $mainStack[-1];
839 318
                            if ($opCode === Opcodes::OP_RIPEMD160) {
840 10
                                $hash = Hash::ripemd160($buffer);
841 310
                            } elseif ($opCode === Opcodes::OP_SHA1) {
842 12
                                $hash = Hash::sha1($buffer);
843 298
                            } elseif ($opCode === Opcodes::OP_SHA256) {
844 12
                                $hash = Hash::sha256($buffer);
845 290
                            } elseif ($opCode === Opcodes::OP_HASH160) {
846 280
                                $hash = Hash::sha256ripe160($buffer);
847 68
                            } else {
848 10
                                $hash = Hash::sha256d($buffer);
849
                            }
850
851 318
                            $mainStack->pop();
852 318
                            $mainStack->push($hash);
853 318
                            break;
854
855 862
                        case Opcodes::OP_CODESEPARATOR:
856 2
                            $hashStartPos = $parser->getPosition();
857 2
                            break;
858
859 860
                        case Opcodes::OP_CHECKSIG:
860 554
                        case Opcodes::OP_CHECKSIGVERIFY:
861 398
                            if (count($mainStack) < 2) {
862 16
                                throw new \RuntimeException('Invalid stack operation');
863
                            }
864
865 394
                            $vchPubKey = $mainStack[-1];
866 394
                            $vchSig = $mainStack[-2];
867
868 394
                            $scriptCode = new Script($script->getBuffer()->slice($hashStartPos));
869
870 394
                            $success = $checker->checkSig($scriptCode, $vchSig, $vchPubKey, $sigVersion, $flags);
871
872 274
                            $mainStack->pop();
873 274
                            $mainStack->pop();
874 274
                            $mainStack->push($success ? $this->vchTrue : $this->vchFalse);
875
876 274
                            if ($opCode === Opcodes::OP_CHECKSIGVERIFY) {
877
                                if ($success) {
878
                                    $mainStack->pop();
879
                                } else {
880
                                    throw new \RuntimeException('Checksig verify');
881
                                }
882
                            }
883 274
                            break;
884
885 462
                        case Opcodes::OP_CHECKMULTISIG:
886 286
                        case Opcodes::OP_CHECKMULTISIGVERIFY:
887 262
                            $i = 1;
888 262
                            if (count($mainStack) < $i) {
889 2
                                throw new \RuntimeException('Invalid stack operation');
890
                            }
891
892 260
                            $keyCount = Number::buffer($mainStack[-$i], $minimal)->getInt();
893 256
                            if ($keyCount < 0 || $keyCount > 20) {
894 4
                                throw new \RuntimeException('OP_CHECKMULTISIG: Public key count exceeds 20');
895
                            }
896
897 252
                            $opCount += $keyCount;
898 252
                            $this->checkOpcodeCount($opCount);
899
900
                            // Extract positions of the keys, and signatures, from the stack.
901 252
                            $ikey = ++$i;
902 252
                            $i += $keyCount;
903 252
                            if (count($mainStack) < $i) {
904 2
                                throw new \RuntimeException('Invalid stack operation');
905
                            }
906
907 250
                            $sigCount = Number::buffer($mainStack[-$i], $minimal)->getInt();
908 244
                            if ($sigCount < 0 || $sigCount > $keyCount) {
909 4
                                throw new \RuntimeException('Invalid Signature count');
910
                            }
911
912 240
                            $isig = ++$i;
913 240
                            $i += $sigCount;
914
915
                            // Extract the script since the last OP_CODESEPARATOR
916 240
                            $scriptCode = new Script($script->getBuffer()->slice($hashStartPos));
917
918 240
                            $fSuccess = true;
919 240
                            while ($fSuccess && $sigCount > 0) {
920
                                // Fetch the signature and public key
921 120
                                $sig = $mainStack[-$isig];
922 118
                                $pubkey = $mainStack[-$ikey];
923
924 118
                                if ($checker->checkSig($scriptCode, $sig, $pubkey, $sigVersion, $flags)) {
925 66
                                    $isig++;
926 66
                                    $sigCount--;
927 14
                                }
928
929 98
                                $ikey++;
930 98
                                $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 98
                                if ($sigCount > $keyCount) {
936 48
                                    $fSuccess = false;
937 8
                                }
938 18
                            }
939
940 206
                            while ($i-- > 1) {
941 206
                                $mainStack->pop();
942 14
                            }
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 206
                            if ($mainStack->isEmpty()) {
951 14
                                throw new \RuntimeException('Invalid stack operation');
952
                            }
953
954 206
                            if ($flags & self::VERIFY_NULL_DUMMY && $mainStack[-1]->getSize() !== 0) {
955 4
                                throw new ScriptRuntimeException(self::VERIFY_NULL_DUMMY, 'Extra P2SH stack value should be OP_0');
956
                            }
957
958 202
                            $mainStack->pop();
959 202
                            $mainStack->push($fSuccess ? $this->vchTrue : $this->vchFalse);
960
961 202
                            if ($opCode === Opcodes::OP_CHECKMULTISIGVERIFY) {
962 60
                                if ($fSuccess) {
963 60
                                    $mainStack->pop();
964
                                } else {
965
                                    throw new \RuntimeException('OP_CHECKMULTISIG verify');
966
                                }
967
                            }
968 202
                            break;
969
970 6
                        default:
971 200
                            throw new \RuntimeException('Opcode not found');
972 6
                    }
973
974 2172
                    if (count($mainStack) + count($altStack) > 1000) {
975 2328
                        throw new \RuntimeException('Invalid stack size, exceeds 1000');
976
                    }
977 102
                }
978 152
            }
979
980 2468
            if (count($vfStack) !== 0) {
981 12
                throw new \RuntimeException('Unbalanced conditional at script end');
982
            }
983
984 2458
            return true;
985 962
        } 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 228
            return false;
989 734
        } catch (\Exception $e) {
990
            // echo "\n General: " . $e->getMessage()  . PHP_EOL . $e->getTraceAsString() . PHP_EOL;
991 734
            return false;
992
        }
993
    }
994
}
995