Completed
Push — master ( ce605d...b98633 )
by thomas
24:11 queued 20:21
created

Interpreter::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 4
Bugs 0 Features 0
Metric Value
c 4
b 0
f 0
dl 0
loc 9
ccs 8
cts 8
cp 1
rs 9.6666
cc 1
eloc 7
nc 1
nop 1
crap 1
1
<?php
2
3
namespace BitWasp\Bitcoin\Script\Interpreter;
4
5
use BitWasp\Bitcoin\Crypto\EcAdapter\Adapter\EcAdapterInterface;
6
use BitWasp\Bitcoin\Crypto\Hash;
7
use BitWasp\Bitcoin\Exceptions\SignatureNotCanonical;
8
use BitWasp\Bitcoin\Exceptions\ScriptRuntimeException;
9
use BitWasp\Bitcoin\Script\Classifier\OutputClassifier;
10
use BitWasp\Bitcoin\Script\Opcodes;
11
use BitWasp\Bitcoin\Script\Script;
12
use BitWasp\Bitcoin\Script\ScriptFactory;
13
use BitWasp\Bitcoin\Script\ScriptInterface;
14
use BitWasp\Bitcoin\Script\ScriptWitness;
15
use BitWasp\Bitcoin\Script\ScriptWitnessInterface;
16
use BitWasp\Bitcoin\Script\WitnessProgram;
17
use BitWasp\Bitcoin\Signature\TransactionSignature;
18
use BitWasp\Bitcoin\Transaction\TransactionInputInterface;
19
use BitWasp\Buffertools\Buffer;
20
use BitWasp\Buffertools\BufferInterface;
21
22
class Interpreter implements InterpreterInterface
23
{
24
25
    /**
26
     * @var int
27
     */
28
    private $opCount;
29
30
    /**
31
     * @var EcAdapterInterface
32
     */
33
    private $ecAdapter;
34
35
    /**
36
     * @var \BitWasp\Bitcoin\Math\Math
37
     */
38
    private $math;
39
40
    /**
41
     * @var BufferInterface
42
     */
43
    private $vchFalse;
44
45
    /**
46
     * @var BufferInterface
47
     */
48
    private $vchTrue;
49
50
    /**
51
     * @var BufferInterface
52
     */
53
    private $int0;
54
55
    /**
56
     * @var BufferInterface
57
     */
58
    private $int1;
59
60
    /**
61
     * @var array
62
     */
63
    private $disabledOps = [
64
        Opcodes::OP_CAT,    Opcodes::OP_SUBSTR, Opcodes::OP_LEFT,  Opcodes::OP_RIGHT,
65
        Opcodes::OP_INVERT, Opcodes::OP_AND,    Opcodes::OP_OR,    Opcodes::OP_XOR,
66
        Opcodes::OP_2MUL,   Opcodes::OP_2DIV,   Opcodes::OP_MUL,   Opcodes::OP_DIV,
67
        Opcodes::OP_MOD,    Opcodes::OP_LSHIFT, Opcodes::OP_RSHIFT
68
    ];
69
70
    /**
71
     * @param EcAdapterInterface $ecAdapter
72
     */
73 816
    public function __construct(EcAdapterInterface $ecAdapter)
74
    {
75 816
        $this->ecAdapter = $ecAdapter;
76 816
        $this->math = $ecAdapter->getMath();
77 816
        $this->vchFalse = new Buffer("", 0, $this->math);
78 816
        $this->vchTrue = new Buffer("\x01", 1, $this->math);
79 816
        $this->int0 = Number::buffer($this->vchFalse, false, 4, $this->math)->getBuffer();
80 816
        $this->int1 = Number::buffer($this->vchTrue, false, 1, $this->math)->getBuffer();
81 816
    }
82
83
    /**
84
     * Cast the value to a boolean
85
     *
86
     * @param BufferInterface $value
87
     * @return bool
88
     */
89 498
    public function castToBool(BufferInterface $value)
90
    {
91 498
        $val = $value->getBinary();
92 498
        for ($i = 0, $size = strlen($val); $i < $size; $i++) {
93 492
            $chr = ord($val[$i]);
94 492
            if ($chr != 0) {
95 480
                if ($i == ($size - 1) && $chr == 0x80) {
96
                    return false;
97
                }
98
99 480
                return true;
100
            }
101 12
        }
102
103 18
        return false;
104
    }
105
106
    /**
107
     * @param BufferInterface $signature
108
     * @return bool
109
     */
110
    public function isValidSignatureEncoding(BufferInterface $signature)
111
    {
112
        try {
113
            TransactionSignature::isDERSignature($signature);
114
            return true;
115
        } catch (SignatureNotCanonical $e) {
116
            /* In any case, we will return false outside this block */
117
        }
118
119
        return false;
120
    }
121
122
    /**
123
     * @param int $opCode
124
     * @param BufferInterface $pushData
125
     * @return bool
126
     * @throws \Exception
127
     */
128 12
    public function checkMinimalPush($opCode, BufferInterface $pushData)
129
    {
130 12
        $pushSize = $pushData->getSize();
131 12
        $binary = $pushData->getBinary();
132
133 12
        if ($pushSize === 0) {
134 6
            return $opCode === Opcodes::OP_0;
135 12
        } elseif ($pushSize === 1) {
136 6
            $first = ord($binary[0]);
137 6
            if ($first >= 1 && $first <= 16) {
138 6
                return $opCode === (Opcodes::OP_1 + ($first - 1));
139 6
            } elseif ($first === 0x81) {
140 6
                return $opCode === Opcodes::OP_1NEGATE;
141
            }
142 12
        } elseif ($pushSize <= 75) {
143 12
            return $opCode === $pushSize;
144 6
        } elseif ($pushSize <= 255) {
145 6
            return $opCode === Opcodes::OP_PUSHDATA1;
146 6
        } elseif ($pushSize <= 65535) {
147 6
            return $opCode === Opcodes::OP_PUSHDATA2;
148
        }
149
150 6
        return true;
151
    }
152
153
    /**
154
     * @return $this
155
     * @throws \Exception
156
     */
157 774
    private function checkOpcodeCount()
158
    {
159 774
        if ($this->math->cmp($this->opCount, 201) > 0) {
160 6
            throw new \RuntimeException('Error: Script op code count');
161
        }
162
163 774
        return $this;
164
    }
165
166
    /**
167
     * @param WitnessProgram $witnessProgram
168
     * @param ScriptWitness $scriptWitness
169
     * @param int $flags
170
     * @param Checker $checker
171
     * @return bool
172
     */
173 30
    private function verifyWitnessProgram(WitnessProgram $witnessProgram, ScriptWitness $scriptWitness, $flags, Checker $checker)
174
    {
175 30
        $witnessCount = count($scriptWitness);
176
177 30
        if ($witnessProgram->getVersion() == 0) {
178 30
            $buffer = $witnessProgram->getProgram();
179 30
            if ($buffer->getSize() === 32) {
180
                // Version 0 segregated witness program: SHA256(Script) in program, Script + inputs in witness
181 18
                if ($witnessCount === 0) {
182
                    // Must contain script at least
183
                    return false;
184
                }
185
186 18
                $scriptPubKey = new Script($scriptWitness[$witnessCount - 1]);
187 18
                $stackValues = $scriptWitness->slice(0, -1);
188 18
                $hashScriptPubKey = Hash::sha256($scriptPubKey->getBuffer());
189
190 18
                if ($hashScriptPubKey == $buffer) {
191
                    return false;
192
                }
193 30
            } elseif ($buffer->getSize() === 20) {
194
                // Version 0 special case for pay-to-pubkeyhash
195 12
                if ($witnessCount !== 2) {
196
                    // 2 items in witness - <signature> <pubkey>
197
                    return false;
198
                }
199
200 12
                $scriptPubKey = ScriptFactory::create()->sequence([Opcodes::OP_DUP, Opcodes::OP_HASH160, $buffer, Opcodes::OP_EQUALVERIFY, Opcodes::OP_CHECKSIG])->getScript();
201 12
                $stackValues = $scriptWitness;
202 12
            } else {
203
                return false;
204
            }
205 30
        } elseif ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM) {
206
            return false;
207
        } else {
208
            return false;
209
        }
210
211 30
        $mainStack = new Stack();
212 30
        foreach ($stackValues as $value) {
213 30
            $mainStack->push($value);
214 30
        }
215
216 30
        if (!$this->evaluate($scriptPubKey, $mainStack, 1, $flags, $checker)) {
217
            return false;
218
        }
219
220 30
        if ($mainStack->count() !== 1) {
221
            return false;
222
        }
223
224 30
        if (!$this->castToBool($mainStack->bottom())) {
225
            return false;
226
        }
227
228 30
        return true;
229
    }
230
231
    /**
232
     * @param ScriptInterface $scriptSig
233
     * @param ScriptInterface $scriptPubKey
234
     * @param int $flags
235
     * @param Checker $checker
236
     * @param ScriptWitnessInterface|null $witness
237
     * @return bool
238
     */
239 804
    public function verify(ScriptInterface $scriptSig, ScriptInterface $scriptPubKey, $flags, Checker $checker, ScriptWitnessInterface $witness = null)
240
    {
241 804
        static $emptyWitness = null;
242 804
        if ($emptyWitness === null) {
243 6
            $emptyWitness = new ScriptWitness([]);
244 6
        }
245
246 804
        $witness = $witness ?: $emptyWitness;
247
248 804
        if (($flags & self::VERIFY_SIGPUSHONLY) != 0 && !$scriptSig->isPushOnly()) {
249
            return false;
250
        }
251
252 804
        $stack = new Stack();
253 804
        if (!$this->evaluate($scriptSig, $stack, 0, $flags, $checker)) {
254 6
            return false;
255
        }
256
257 798
        $backup = [];
258 798
        if ($flags & self::VERIFY_P2SH) {
259 108
            foreach ($stack as $s) {
260 78
                $backup[] = $s;
261 108
            }
262 108
        }
263
264 798
        if (!$this->evaluate($scriptPubKey, $stack, 0, $flags, $checker)) {
265 300
            return false;
266
        }
267
268 498
        if ($stack->isEmpty()) {
269 6
            return false;
270
        }
271
272 492
        if (false === $this->castToBool($stack[-1])) {
273 12
            return false;
274
        }
275
276 480
        $program = null;
277
278 480
        if ($flags & self::VERIFY_WITNESS) {
279 72
            if ($scriptPubKey->isWitness($program)) {
0 ignored issues
show
Documentation introduced by
$program is of type null, but the function expects a object<BitWasp\Bitcoin\Script\WitnessProgram>.

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...
280
                /** @var WitnessProgram $program */
281 18
                if ($scriptSig->getBuffer()->getSize() !== 0) {
282
                    return false;
283
                }
284
285 18
                if (!$this->verifyWitnessProgram($program, $witness, $flags, $checker)) {
0 ignored issues
show
Documentation introduced by
$witness is of type null|object<BitWasp\Bitc...ScriptWitnessInterface>, but the function expects a object<BitWasp\Bitcoin\Script\ScriptWitness>.

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...
286
                    return false;
287
                }
288
289 18
                $stack->resize(1);
290 18
            }
291 72
        }
292
293 480
        if ($flags & self::VERIFY_P2SH && (new OutputClassifier($scriptPubKey))->isPayToScriptHash()) {
294 36
            if (!$scriptSig->isPushOnly()) {
295 6
                return false;
296
            }
297
298 30
            $stack = new Stack();
299 30
            foreach ($backup as $i) {
300 30
                $stack->push($i);
301 30
            }
302
303
            // Restore mainStack to how it was after evaluating scriptSig
304 30
            if ($stack->isEmpty()) {
305
                return false;
306
            }
307
308
            // Load redeemscript as the scriptPubKey
309 30
            $scriptPubKey = new Script($stack->bottom());
310 30
            $stack->pop();
311
312 30
            if (!$this->evaluate($scriptPubKey, $stack, 0, $flags, $checker)) {
313 6
                return false;
314
            }
315
316 24
            if ($stack->isEmpty()) {
317
                return false;
318
            }
319
320 24
            if (!$this->castToBool($stack->bottom())) {
321
                return false;
322
            }
323
324 24
            if ($flags & self::VERIFY_WITNESS) {
325 24
                if ($scriptPubKey->isWitness($program)) {
326
                    /** @var WitnessProgram $program */
327 12
                    if ($scriptSig != (ScriptFactory::create()->push($scriptPubKey->getBuffer())->getScript())) {
328
                        return false; // SCRIPT_ERR_WITNESS_MALLEATED_P2SH
329
                    }
330
331 12
                    if (!$this->verifyWitnessProgram($program, $witness, $flags, $checker)) {
0 ignored issues
show
Documentation introduced by
$witness is of type null|object<BitWasp\Bitc...ScriptWitnessInterface>, but the function expects a object<BitWasp\Bitcoin\Script\ScriptWitness>.

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...
332
                        return false;
333
                    }
334
335 12
                    $stack->resize(1);
336 12
                }
337 24
            }
338 24
        }
339
340 468
        if ($flags & self::VERIFY_CLEAN_STACK != 0) {
341 72
            if (!($flags & self::VERIFY_P2SH != 0 && $flags & self::VERIFY_WITNESS != 0)) {
342
                return false; // implied flags required
343
            }
344
345 72
            if (count($stack) != 1) {
346
                return false; // Cleanstack
347
            }
348 72
        }
349
350 468
        if ($flags & self::VERIFY_WITNESS) {
351 72
            if (!$flags & self::VERIFY_P2SH) {
352
                return false; //
353
            }
354
355 72
            if ($program === null && !$witness->isNull()) {
356
                return false; // SCRIPT_ERR_WITNESS_UNEXPECTED
357
            }
358 72
        }
359
360 468
        return true;
361
    }
362
363
    /**
364
     * @param Stack $vfStack
365
     * @return bool
366
     */
367 804
    private function checkExec(Stack $vfStack)
368
    {
369 804
        $c = 0;
370 804
        $len = $vfStack->end();
371 804
        for ($i = 0; $i < $len; $i++) {
372
            if ($vfStack[0 - $len - $i] === true) {
373
                $c++;
374
            }
375
        }
376
377 804
        return !(bool)$c;
378
    }
379
380
    /**
381
     * @param ScriptInterface $script
382
     * @param Stack $mainStack
383
     * @param int $sigVersion
384
     * @param int $flags
385
     * @param Checker $checker
386
     * @return bool
387
     */
388 810
    public function evaluate(ScriptInterface $script, Stack $mainStack, $sigVersion, $flags, Checker $checker)
389
    {
390 810
        $math = $this->math;
391 810
        $hashStartPos = 0;
392 810
        $this->opCount = 0;
393 810
        $altStack = new Stack();
394 810
        $vfStack = new Stack();
395 810
        $minimal = ($flags & self::VERIFY_MINIMALDATA) != 0;
396 810
        $parser = $script->getScriptParser();
397
398 810
        if ($script->getBuffer()->getSize() > 10000) {
399
            return false;
400
        }
401
402
        try {
403 810
            foreach ($parser as $operation) {
404 804
                $opCode = $operation->getOp();
405 804
                $pushData = $operation->getData();
406 804
                $fExec = $this->checkExec($vfStack);
407
408
                // If pushdata was written to
409 804
                if ($operation->isPush() && $operation->getDataSize() > InterpreterInterface::MAX_SCRIPT_ELEMENT_SIZE) {
410 6
                    throw new \RuntimeException('Error - push size');
411
                }
412
413
                // OP_RESERVED should not count towards opCount
414 798
                if ($opCode > Opcodes::OP_16 && ++$this->opCount) {
415 774
                    $this->checkOpcodeCount();
416 774
                }
417
418 798
                if (in_array($opCode, $this->disabledOps, true)) {
419 12
                    throw new \RuntimeException('Disabled Opcode');
420
                }
421
422 798
                if ($fExec && $operation->isPush()) {
423
                    // In range of a pushdata opcode
424 504
                    if ($minimal && !$this->checkMinimalPush($opCode, $pushData)) {
425 6
                        throw new ScriptRuntimeException(self::VERIFY_MINIMALDATA, 'Minimal pushdata required');
426
                    }
427
428 498
                    $mainStack->push($pushData);
429
                    // echo " - [pushed '" . $pushData->getHex() . "']\n";
430 792
                } elseif ($fExec || ($opCode !== Opcodes::OP_IF && $opCode !== Opcodes::OP_ENDIF)) {
431
                    // echo "OPCODE - " . $script->getOpcodes()->getOp($opCode) . "\n";
432
                    switch ($opCode) {
433 768
                        case Opcodes::OP_1NEGATE:
434 768
                        case Opcodes::OP_1:
435 768
                        case Opcodes::OP_2:
436 768
                        case Opcodes::OP_3:
437 768
                        case Opcodes::OP_4:
438 768
                        case Opcodes::OP_5:
439 768
                        case Opcodes::OP_6:
440 768
                        case Opcodes::OP_7:
441 768
                        case Opcodes::OP_8:
442 768
                        case Opcodes::OP_9:
443 768
                        case Opcodes::OP_10:
444 768
                        case Opcodes::OP_11:
445 768
                        case Opcodes::OP_12:
446 768
                        case Opcodes::OP_13:
447 768
                        case Opcodes::OP_14:
448 768
                        case Opcodes::OP_15:
449 768
                        case Opcodes::OP_16:
450 240
                            $num = \BitWasp\Bitcoin\Script\decodeOpN($opCode);
451 240
                            $mainStack->push(Number::int($num)->getBuffer());
452 240
                            break;
453
454 768
                        case Opcodes::OP_CHECKLOCKTIMEVERIFY:
455
                            if (!$flags & self::VERIFY_CHECKLOCKTIMEVERIFY) {
456
                                if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
457
                                    throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
458
                                }
459
                                break;
460
                            }
461
462
                            if ($mainStack->isEmpty()) {
463
                                throw new \RuntimeException('Invalid stack operation - CLTV');
464
                            }
465
466
                            $lockTime = Number::buffer($mainStack[-1], $minimal, 5, $math);
467
                            if (!$checker->checkLockTime($lockTime)) {
468
                                throw new ScriptRuntimeException(self::VERIFY_CHECKLOCKTIMEVERIFY, 'Unsatisfied locktime');
469
                            }
470
471
                            break;
472
473 768
                        case Opcodes::OP_CHECKSEQUENCEVERIFY:
474
                            if (!$flags & self::VERIFY_CHECKSEQUENCEVERIFY) {
475
                                if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
476
                                    throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
477
                                }
478
                                break;
479
                            }
480
481
                            if ($mainStack->isEmpty()) {
482
                                throw new \RuntimeException('Invalid stack operation - CSV');
483
                            }
484
485
                            $sequence = Number::buffer($mainStack[-1], $minimal, 5, $math);
486
                            $nSequence = $sequence->getInt();
487
                            if ($math->cmp($nSequence, 0) < 0) {
488
                                throw new ScriptRuntimeException(self::VERIFY_CHECKSEQUENCEVERIFY, 'Negative locktime');
489
                            }
490
491
                            if ($math->cmp($math->bitwiseAnd($nSequence, TransactionInputInterface::SEQUENCE_LOCKTIME_DISABLE_FLAG), '0') !== 0) {
492
                                break;
493
                            }
494
495
                            if (!$checker->checkSequence($sequence)) {
496
                                throw new ScriptRuntimeException(self::VERIFY_CHECKSEQUENCEVERIFY, 'Unsatisfied locktime');
497
                            }
498
                            break;
499
500 768
                        case Opcodes::OP_NOP1:
501 768
                        case Opcodes::OP_NOP4:
502 768
                        case Opcodes::OP_NOP5:
503 768
                        case Opcodes::OP_NOP6:
504 768
                        case Opcodes::OP_NOP7:
505 768
                        case Opcodes::OP_NOP8:
506 768
                        case Opcodes::OP_NOP9:
507 768
                        case Opcodes::OP_NOP10:
508 6
                            if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
509 6
                                throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
510
                            }
511
                            break;
512
513 762
                        case Opcodes::OP_NOP:
514 12
                            break;
515
516 750
                        case Opcodes::OP_IF:
517 750
                        case Opcodes::OP_NOTIF:
518
                            // <expression> if [statements] [else [statements]] endif
519 6
                            $value = false;
520 6
                            if ($fExec) {
521 6
                                if ($mainStack->isEmpty()) {
522 6
                                    throw new \RuntimeException('Unbalanced conditional');
523
                                }
524
525
                                $buffer = Number::buffer($mainStack->pop(), $minimal)->getBuffer();
526
                                $value = $this->castToBool($buffer);
527
528
                                if ($opCode === Opcodes::OP_NOTIF) {
529
                                    $value = !$value;
530
                                }
531
                            }
532
                            $vfStack->push($value ? $this->vchTrue : $this->vchFalse);
533
                            break;
534
535 744
                        case Opcodes::OP_ELSE:
536 6
                            if ($vfStack->isEmpty()) {
537 6
                                throw new \RuntimeException('Unbalanced conditional');
538
                            }
539
                            $vfStack->push(!$vfStack->end() ? $this->vchTrue : $this->vchFalse);
540
                            break;
541
542 738
                        case Opcodes::OP_ENDIF:
543 6
                            if ($vfStack->isEmpty()) {
544 6
                                throw new \RuntimeException('Unbalanced conditional');
545
                            }
546
                            break;
547
548 732
                        case Opcodes::OP_VERIFY:
549 24
                            if ($mainStack->isEmpty()) {
550 6
                                throw new \RuntimeException('Invalid stack operation');
551
                            }
552 18
                            $value = $this->castToBool($mainStack[-1]);
553 18
                            if (!$value) {
554 6
                                throw new \RuntimeException('Error: verify');
555
                            }
556 12
                            $mainStack->pop();
557 12
                            break;
558
559 708
                        case Opcodes::OP_TOALTSTACK:
560 18
                            if ($mainStack->isEmpty()) {
561 6
                                throw new \RuntimeException('Invalid stack operation OP_TOALTSTACK');
562
                            }
563 12
                            $altStack->push($mainStack->pop());
564 12
                            break;
565
566 702
                        case Opcodes::OP_FROMALTSTACK:
567 12
                            if ($altStack->isEmpty()) {
568 6
                                throw new \RuntimeException('Invalid alt-stack operation OP_FROMALTSTACK');
569
                            }
570 6
                            $mainStack->push($altStack->pop());
571 6
                            break;
572
573 696
                        case Opcodes::OP_IFDUP:
574
                            // If top value not zero, duplicate it.
575 12
                            if ($mainStack->isEmpty()) {
576 6
                                throw new \RuntimeException('Invalid stack operation OP_IFDUP');
577
                            }
578 6
                            $vch = $mainStack[-1];
579 6
                            if ($this->castToBool($vch)) {
580 6
                                $mainStack->push($vch);
581 6
                            }
582 6
                            break;
583
584 690
                        case Opcodes::OP_DEPTH:
585 84
                            $num = count($mainStack);
586 84
                            $depth = Number::int($num)->getBuffer();
587 84
                            $mainStack->push($depth);
588 84
                            break;
589
590 684
                        case Opcodes::OP_DROP:
591 6
                            if ($mainStack->isEmpty()) {
592 6
                                throw new \RuntimeException('Invalid stack operation OP_DROP');
593
                            }
594
                            $mainStack->pop();
595
                            break;
596
597 678
                        case Opcodes::OP_DUP:
598 42
                            if ($mainStack->isEmpty()) {
599 6
                                throw new \RuntimeException('Invalid stack operation OP_DUP');
600
                            }
601 36
                            $vch = $mainStack[-1];
602 36
                            $mainStack->push($vch);
603 36
                            break;
604
605 672
                        case Opcodes::OP_NIP:
606 18
                            if (count($mainStack) < 2) {
607 6
                                throw new \RuntimeException('Invalid stack operation OP_NIP');
608
                            }
609 12
                            unset($mainStack[-2]);
610 12
                            break;
611
612 666
                        case Opcodes::OP_OVER:
613 18
                            if (count($mainStack) < 2) {
614 6
                                throw new \RuntimeException('Invalid stack operation OP_OVER');
615
                            }
616 12
                            $vch = $mainStack[-2];
617 12
                            $mainStack->push($vch);
618 12
                            break;
619
620 660
                        case Opcodes::OP_ROT:
621 12
                            if (count($mainStack) < 3) {
622 6
                                throw new \RuntimeException('Invalid stack operation OP_ROT');
623
                            }
624 6
                            $mainStack->swap(-3, -2);
625 6
                            $mainStack->swap(-2, -1);
626 6
                            break;
627
628 654
                        case Opcodes::OP_SWAP:
629 12
                            if (count($mainStack) < 2) {
630 6
                                throw new \RuntimeException('Invalid stack operation OP_SWAP');
631
                            }
632 6
                            $mainStack->swap(-2, -1);
633 6
                            break;
634
635 648
                        case Opcodes::OP_TUCK:
636 12
                            if (count($mainStack) < 2) {
637 6
                                throw new \RuntimeException('Invalid stack operation OP_TUCK');
638
                            }
639 6
                            $vch = $mainStack[-1];
640 6
                            $mainStack->add(count($mainStack) - 1 - 2, $vch);
641
                            break;
642
643 636
                        case Opcodes::OP_PICK:
644 636
                        case Opcodes::OP_ROLL:
645 24
                            if (count($mainStack) < 2) {
646 6
                                throw new \RuntimeException('Invalid stack operation OP_PICK');
647
                            }
648
649 18
                            $n = Number::buffer($mainStack[-1], $minimal, 4)->getInt();
650 18
                            $mainStack->pop();
651 18
                            if ($math->cmp($n, 0) < 0 || $math->cmp($n, count($mainStack)) >= 0) {
652 6
                                throw new \RuntimeException('Invalid stack operation OP_PICK');
653
                            }
654
655 12
                            $pos = (int) $math->sub($math->sub(0, $n), 1);
656 12
                            $vch = $mainStack[$pos];
657 12
                            if ($opCode === Opcodes::OP_ROLL) {
658 6
                                unset($mainStack[$pos]);
659 6
                            }
660 12
                            $mainStack->push($vch);
661 12
                            break;
662
663 624
                        case Opcodes::OP_2DROP:
664 12
                            if (count($mainStack) < 2) {
665 6
                                throw new \RuntimeException('Invalid stack operation OP_2DROP');
666
                            }
667 6
                            $mainStack->pop();
668 6
                            $mainStack->pop();
669 6
                            break;
670
671 618
                        case Opcodes::OP_2DUP:
672 18
                            if (count($mainStack) < 2) {
673 6
                                throw new \RuntimeException('Invalid stack operation OP_2DUP');
674
                            }
675 12
                            $string1 = $mainStack[-2];
676 12
                            $string2 = $mainStack[-1];
677 12
                            $mainStack->push($string1);
678 12
                            $mainStack->push($string2);
679 12
                            break;
680
681 612
                        case Opcodes::OP_3DUP:
682 18
                            if (count($mainStack) < 3) {
683 6
                                throw new \RuntimeException('Invalid stack operation OP_3DUP');
684
                            }
685 12
                            $string1 = $mainStack[-3];
686 12
                            $string2 = $mainStack[-2];
687 12
                            $string3 = $mainStack[-1];
688 12
                            $mainStack->push($string1);
689 12
                            $mainStack->push($string2);
690 12
                            $mainStack->push($string3);
691 12
                            break;
692
693 606
                        case Opcodes::OP_2OVER:
694 18
                            if (count($mainStack) < 4) {
695 6
                                throw new \RuntimeException('Invalid stack operation OP_2OVER');
696
                            }
697 12
                            $string1 = $mainStack[-4];
698 12
                            $string2 = $mainStack[-3];
699 12
                            $mainStack->push($string1);
700 12
                            $mainStack->push($string2);
701 12
                            break;
702
703 600
                        case Opcodes::OP_2ROT:
704 12
                            if (count($mainStack) < 6) {
705 6
                                throw new \RuntimeException('Invalid stack operation OP_2ROT');
706
                            }
707 6
                            $string1 = $mainStack[-6];
708 6
                            $string2 = $mainStack[-5];
709 6
                            unset($mainStack[-6], $mainStack[-5]);
710 6
                            $mainStack->push($string1);
711 6
                            $mainStack->push($string2);
712 6
                            break;
713
714 594
                        case Opcodes::OP_2SWAP:
715 12
                            if (count($mainStack) < 4) {
716 6
                                throw new \RuntimeException('Invalid stack operation OP_2SWAP');
717
                            }
718 6
                            $mainStack->swap(-3, -1);
719 6
                            $mainStack->swap(-4, -2);
720 6
                            break;
721
722 588
                        case Opcodes::OP_SIZE:
723 12
                            if ($mainStack->isEmpty()) {
724 6
                                throw new \RuntimeException('Invalid stack operation OP_SIZE');
725
                            }
726 6
                            $size = Number::int($mainStack[-1]->getSize());
727 6
                            $mainStack->push($size->getBuffer());
728 6
                            break;
729
730 582
                        case Opcodes::OP_EQUAL:
731 582
                        case Opcodes::OP_EQUALVERIFY:
732 444
                            if (count($mainStack) < 2) {
733 6
                                throw new \RuntimeException('Invalid stack operation OP_EQUAL');
734
                            }
735
736 438
                            $equal = $mainStack[-2]->equals($mainStack[-1]);
737 438
                            $mainStack->pop();
738 438
                            $mainStack->pop();
739 438
                            $mainStack->push($equal ? $this->vchTrue : $this->vchFalse);
740 438
                            if ($opCode === Opcodes::OP_EQUALVERIFY) {
741 138
                                if ($equal) {
742 126
                                    $mainStack->pop();
743 126
                                } else {
744 12
                                    throw new \RuntimeException('Error EQUALVERIFY');
745
                                }
746 126
                            }
747
748 426
                            break;
749
750
                        // Arithmetic operations
751 396
                        case $opCode >= Opcodes::OP_1ADD && $opCode <= Opcodes::OP_0NOTEQUAL:
752 48
                            if ($mainStack->isEmpty()) {
753 6
                                throw new \Exception('Invalid stack operation 1ADD-OP_0NOTEQUAL');
754
                            }
755
756 42
                            $num = Number::buffer($mainStack[-1], $minimal)->getInt();
757
758 42
                            if ($opCode === Opcodes::OP_1ADD) {
759 6
                                $num = $math->add($num, '1');
760 42
                            } elseif ($opCode === Opcodes::OP_1SUB) {
761 6
                                $num = $math->sub($num, '1');
762 36
                            } elseif ($opCode === Opcodes::OP_2MUL) {
763
                                $num = $math->mul(2, $num);
764 30
                            } elseif ($opCode === Opcodes::OP_NEGATE) {
765
                                $num = $math->sub(0, $num);
766 30
                            } elseif ($opCode === Opcodes::OP_ABS) {
767
                                if ($math->cmp($num, '0') < 0) {
768
                                    $num = $math->sub(0, $num);
769
                                }
770 30
                            } elseif ($opCode === Opcodes::OP_NOT) {
771 18
                                $num = (int) $math->cmp($num, '0') === 0;
772 18
                            } else {
773
                                // is OP_0NOTEQUAL
774 12
                                $num = (int) ($math->cmp($num, '0') !== 0);
775
                            }
776
777 42
                            $mainStack->pop();
778
779 42
                            $buffer = Number::int($num)->getBuffer();
780
781 42
                            $mainStack->push($buffer);
782 42
                            break;
783
784 348
                        case $opCode >= Opcodes::OP_ADD && $opCode <= Opcodes::OP_MAX:
785 150
                            if (count($mainStack) < 2) {
786 24
                                throw new \Exception('Invalid stack operation (OP_ADD - OP_MAX)');
787
                            }
788
789 126
                            $num1 = Number::buffer($mainStack[-2], $minimal)->getInt();
790 126
                            $num2 = Number::buffer($mainStack[-1], $minimal)->getInt();
791
792 126
                            if ($opCode === Opcodes::OP_ADD) {
793 6
                                $num = $math->add($num1, $num2);
794 126
                            } else if ($opCode === Opcodes::OP_SUB) {
795 6
                                $num = $math->sub($num1, $num2);
796 120
                            } else if ($opCode === Opcodes::OP_BOOLAND) {
797 12
                                $num = $math->cmp($num1, '0') !== 0 && $math->cmp($num2, '0') !== 0;
798 114
                            } else if ($opCode === Opcodes::OP_BOOLOR) {
799 18
                                $num = $math->cmp($num1, '0') !== 0 || $math->cmp($num2, '0') !== 0;
800 102
                            } elseif ($opCode === Opcodes::OP_NUMEQUAL) {
801 18
                                $num = $math->cmp($num1, $num2) === 0;
802 84
                            } elseif ($opCode === Opcodes::OP_NUMEQUALVERIFY) {
803
                                $num = $math->cmp($num1, $num2) === 0;
804 66
                            } elseif ($opCode === Opcodes::OP_NUMNOTEQUAL) {
805 6
                                $num = $math->cmp($num1, $num2) !== 0;
806 66
                            } elseif ($opCode === Opcodes::OP_LESSTHAN) {
807 12
                                $num = $math->cmp($num1, $num2) < 0;
808 60
                            } elseif ($opCode === Opcodes::OP_GREATERTHAN) {
809 12
                                $num = $math->cmp($num1, $num2) > 0;
810 48
                            } elseif ($opCode === Opcodes::OP_LESSTHANOREQUAL) {
811 12
                                $num = $math->cmp($num1, $num2) <= 0;
812 36
                            } elseif ($opCode === Opcodes::OP_GREATERTHANOREQUAL) {
813 12
                                $num = $math->cmp($num1, $num2) >= 0;
814 24
                            } elseif ($opCode === Opcodes::OP_MIN) {
815 6
                                $num = ($math->cmp($num1, $num2) <= 0) ? $num1 : $num2;
816 6
                            } else {
817 6
                                $num = ($math->cmp($num1, $num2) >= 0) ? $num1 : $num2;
818
                            }
819
820 126
                            $mainStack->pop();
821 126
                            $mainStack->pop();
822 126
                            $buffer = Number::int($num)->getBuffer();
823 126
                            $mainStack->push($buffer);
824
825 126
                            if ($opCode === Opcodes::OP_NUMEQUALVERIFY) {
826
                                if ($this->castToBool($mainStack[-1])) {
827
                                    $mainStack->pop();
828
                                } else {
829
                                    throw new \RuntimeException('NUM EQUAL VERIFY error');
830
                                }
831
                            }
832 126
                            break;
833
834 198
                        case Opcodes::OP_WITHIN:
835 12
                            if (count($mainStack) < 3) {
836 6
                                throw new \RuntimeException('Invalid stack operation');
837
                            }
838
839 6
                            $num1 = Number::buffer($mainStack[-3], $minimal)->getInt();
840 6
                            $num2 = Number::buffer($mainStack[-2], $minimal)->getInt();
841 6
                            $num3 = Number::buffer($mainStack[-1], $minimal)->getInt();
842
843 6
                            $value = $math->cmp($num2, $num1) <= 0 && $math->cmp($num1, $num3) < 0;
844 6
                            $mainStack->pop();
845 6
                            $mainStack->pop();
846 6
                            $mainStack->pop();
847 6
                            $mainStack->push($value ? $this->vchTrue : $this->vchFalse);
848 6
                            break;
849
850
                        // Hash operation
851 186
                        case Opcodes::OP_RIPEMD160:
852 186
                        case Opcodes::OP_SHA1:
853 186
                        case Opcodes::OP_SHA256:
854 186
                        case Opcodes::OP_HASH160:
855 186
                        case Opcodes::OP_HASH256:
856 102
                            if ($mainStack->isEmpty()) {
857 12
                                throw new \RuntimeException('Invalid stack operation');
858
                            }
859
860 90
                            $buffer = $mainStack[-1];
861 90
                            if ($opCode === Opcodes::OP_RIPEMD160) {
862 6
                                $hash = Hash::ripemd160($buffer);
863 90
                            } elseif ($opCode === Opcodes::OP_SHA1) {
864 6
                                $hash = Hash::sha1($buffer);
865 84
                            } elseif ($opCode === Opcodes::OP_SHA256) {
866 6
                                $hash = Hash::sha256($buffer);
867 78
                            } elseif ($opCode === Opcodes::OP_HASH160) {
868 66
                                $hash = Hash::sha256ripe160($buffer);
869 66
                            } else {
870 6
                                $hash = Hash::sha256d($buffer);
871
                            }
872
873 90
                            $mainStack->pop();
874 90
                            $mainStack->push($hash);
875 90
                            break;
876
877 138
                        case Opcodes::OP_CODESEPARATOR:
878
                            $hashStartPos = $parser->getPosition();
879
                            break;
880
881 138
                        case Opcodes::OP_CHECKSIG:
882 138
                        case Opcodes::OP_CHECKSIGVERIFY:
883 54
                            if (count($mainStack) < 2) {
884 6
                                throw new \RuntimeException('Invalid stack operation');
885
                            }
886
887 48
                            $vchPubKey = $mainStack[-1];
888 48
                            $vchSig = $mainStack[-2];
889
890 48
                            $scriptCode = new Script($script->getBuffer()->slice($hashStartPos));
891
892 48
                            $success = $checker->checkSig($scriptCode, $vchSig, $vchPubKey, $sigVersion, $flags);
893
894 42
                            $mainStack->pop();
895 42
                            $mainStack->pop();
896 42
                            $mainStack->push($success ? $this->vchTrue : $this->vchFalse);
897
898 42
                            if ($opCode === Opcodes::OP_CHECKSIGVERIFY) {
899
                                if ($success) {
900
                                    $mainStack->pop();
901
                                } else {
902
                                    throw new \RuntimeException('Checksig verify');
903
                                }
904
                            }
905 42
                            break;
906
907 84
                        case Opcodes::OP_CHECKMULTISIG:
908 84
                        case Opcodes::OP_CHECKMULTISIGVERIFY:
909 30
                            $i = 1;
910 30
                            if (count($mainStack) < $i) {
911
                                throw new \RuntimeException('Invalid stack operation');
912
                            }
913
914
915 30
                            $keyCount = Number::buffer($mainStack[-$i], $minimal)->getInt();
916 30
                            if ($math->cmp($keyCount, 0) < 0 || $math->cmp($keyCount, 20) > 0) {
917
                                throw new \RuntimeException('OP_CHECKMULTISIG: Public key count exceeds 20');
918
                            }
919
920 30
                            $this->opCount += $keyCount;
921 30
                            $this->checkOpcodeCount();
922
923
                            // Extract positions of the keys, and signatures, from the stack.
924 30
                            $ikey = ++$i;
925 30
                            $i += $keyCount; /** @var int $i */
926 30
                            if (count($mainStack) < $i) {
927
                                throw new \RuntimeException('Invalid stack operation');
928
                            }
929
930 30
                            $sigCount = Number::buffer($mainStack[-$i], $minimal)->getInt();
931 30
                            if ($math->cmp($sigCount, 0) < 0 || $math->cmp($sigCount, $keyCount) > 0) {
932
                                throw new \RuntimeException('Invalid Signature count');
933
                            }
934
935 30
                            $isig = ++$i;
936 30
                            $i += $sigCount;
937
938
                            // Extract the script since the last OP_CODESEPARATOR
939 30
                            $scriptCode = new Script($script->getBuffer()->slice($hashStartPos));
940
941 30
                            $fSuccess = true;
942 30
                            while ($fSuccess && $sigCount > 0) {
943
944
                                // Fetch the signature and public key
945 30
                                $sig = $mainStack[-$isig];
946 30
                                $pubkey = $mainStack[-$ikey];
947
948 30
                                if ($checker->checkSig($scriptCode, $sig, $pubkey, $sigVersion, $flags)) {
949 30
                                    $isig++;
950 30
                                    $sigCount--;
951 30
                                }
952
953 30
                                $ikey++;
954 30
                                $keyCount--;
955
956
                                // If there are more signatures left than keys left,
957
                                // then too many signatures have failed. Exit early,
958
                                // without checking any further signatures.
959 30
                                if ($sigCount > $keyCount) {
960
                                    $fSuccess = false;
961
                                }
962 30
                            }
963
964 30
                            while ($i-- > 1) {
965 30
                                $mainStack->pop();
966 30
                            }
967
968
                            // A bug causes CHECKMULTISIG to consume one extra argument
969
                            // whose contents were not checked in any way.
970
                            //
971
                            // Unfortunately this is a potential source of mutability,
972
                            // so optionally verify it is exactly equal to zero prior
973
                            // to removing it from the stack.
974 30
                            if ($mainStack->isEmpty()) {
975
                                throw new \RuntimeException('Invalid stack operation');
976
                            }
977
978 30
                            if ($flags & self::VERIFY_NULL_DUMMY && $mainStack[-1]->getSize() !== 0) {
979
                                throw new ScriptRuntimeException(self::VERIFY_NULL_DUMMY, 'Extra P2SH stack value should be OP_0');
980
                            }
981
982 30
                            $mainStack->pop();
983 30
                            $mainStack->push($fSuccess ? $this->vchTrue : $this->vchFalse);
984
985 30
                            if ($opCode === Opcodes::OP_CHECKMULTISIGVERIFY) {
986
                                if ($fSuccess) {
987
                                    $mainStack->pop();
988
                                } else {
989
                                    throw new \RuntimeException('OP_CHECKMULTISIG verify');
990
                                }
991
                            }
992 30
                            break;
993
994 54
                        default:
995 54
                            throw new \RuntimeException('Opcode not found');
996 54
                    }
997
998 504
                    if (count($mainStack) + count($altStack) > 1000) {
999
                        throw new \RuntimeException('Invalid stack size, exceeds 1000');
1000
                    }
1001 504
                }
1002 804
            }
1003
1004 804
            if (!$vfStack->end() === 0) {
1005
                throw new \RuntimeException('Unbalanced conditional at script end');
1006
            }
1007
1008 804
            return true;
1009 318
        } catch (ScriptRuntimeException $e) {
1010
            // echo "\n Runtime: " . $e->getMessage() . "\n";
1011
            // Failure due to script tags, can access flag: $e->getFailureFlag()
1012 18
            return false;
1013 300
        } catch (\Exception $e) {
1014
            // echo "\n General: " . $e->getMessage()  . PHP_EOL . $e->getTraceAsString();
1015 300
            return false;
1016
        }
1017
    }
1018
}
1019