Completed
Push — master ( 508371...265855 )
by thomas
68:00 queued 64:13
created

Interpreter::verifyWitnessProgram()   C

Complexity

Conditions 12
Paths 22

Size

Total Lines 57
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 31
CRAP Score 12.0988

Importance

Changes 0
Metric Value
cc 12
eloc 33
c 0
b 0
f 0
nc 22
nop 4
dl 0
loc 57
ccs 31
cts 34
cp 0.9118
crap 12.0988
rs 6.62

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace BitWasp\Bitcoin\Script\Interpreter;
4
5
use BitWasp\Bitcoin\Crypto\EcAdapter\Adapter\EcAdapterInterface;
6
use BitWasp\Bitcoin\Crypto\Hash;
7
use BitWasp\Bitcoin\Exceptions\SignatureNotCanonical;
8
use BitWasp\Bitcoin\Exceptions\ScriptRuntimeException;
9
use BitWasp\Bitcoin\Script\Classifier\OutputClassifier;
10
use BitWasp\Bitcoin\Script\Opcodes;
11
use BitWasp\Bitcoin\Script\Script;
12
use BitWasp\Bitcoin\Script\ScriptFactory;
13
use BitWasp\Bitcoin\Script\ScriptInterface;
14
use BitWasp\Bitcoin\Script\ScriptWitness;
15
use BitWasp\Bitcoin\Script\ScriptWitnessInterface;
16
use BitWasp\Bitcoin\Script\WitnessProgram;
17
use BitWasp\Bitcoin\Signature\TransactionSignature;
18
use BitWasp\Bitcoin\Transaction\TransactionInputInterface;
19
use BitWasp\Buffertools\Buffer;
20
use BitWasp\Buffertools\BufferInterface;
21
22
class Interpreter implements InterpreterInterface
23
{
24
25
    /**
26
     * @var \BitWasp\Bitcoin\Math\Math
27
     */
28
    private $math;
29
30
    /**
31
     * @var BufferInterface
32
     */
33
    private $vchFalse;
34
35
    /**
36
     * @var BufferInterface
37
     */
38
    private $vchTrue;
39
40
    /**
41
     * @var array
42
     */
43
    private $disabledOps = [
44
        Opcodes::OP_CAT,    Opcodes::OP_SUBSTR, Opcodes::OP_LEFT,  Opcodes::OP_RIGHT,
45
        Opcodes::OP_INVERT, Opcodes::OP_AND,    Opcodes::OP_OR,    Opcodes::OP_XOR,
46
        Opcodes::OP_2MUL,   Opcodes::OP_2DIV,   Opcodes::OP_MUL,   Opcodes::OP_DIV,
47
        Opcodes::OP_MOD,    Opcodes::OP_LSHIFT, Opcodes::OP_RSHIFT
48
    ];
49
50
    /**
51
     * @param EcAdapterInterface $ecAdapter
52
     */
53 63
    public function __construct(EcAdapterInterface $ecAdapter)
54
    {
55 63
        $this->math = $ecAdapter->getMath();
56 63
        $this->vchFalse = new Buffer("", 0, $this->math);
57 63
        $this->vchTrue = new Buffer("\x01", 1, $this->math);
58 63
    }
59
60
    /**
61
     * Cast the value to a boolean
62
     *
63
     * @param BufferInterface $value
64
     * @return bool
65
     */
66 1647
    public function castToBool(BufferInterface $value)
67
    {
68 1647
        $val = $value->getBinary();
69 1647
        for ($i = 0, $size = strlen($val); $i < $size; $i++) {
70 1511
            $chr = ord($val[$i]);
71 1511
            if ($chr != 0) {
72 1508
                if (($i == ($size - 1)) && $chr == 0x80) {
73
                    return false;
74
                }
75 1508
                return true;
76
            }
77 4
        }
78 395
        return false;
79
    }
80
81
    /**
82
     * @param BufferInterface $signature
83
     * @return bool
84
     */
85
    public function isValidSignatureEncoding(BufferInterface $signature)
86
    {
87
        try {
88
            TransactionSignature::isDERSignature($signature);
89
            return true;
90
        } catch (SignatureNotCanonical $e) {
91
            /* In any case, we will return false outside this block */
92
        }
93
94
        return false;
95
    }
96
97
    /**
98
     * @param int $opCode
99
     * @param BufferInterface $pushData
100
     * @return bool
101
     * @throws \Exception
102
     */
103 233
    public function checkMinimalPush($opCode, BufferInterface $pushData)
104
    {
105 233
        $pushSize = $pushData->getSize();
106 233
        $binary = $pushData->getBinary();
107
108 233
        if ($pushSize === 0) {
109 111
            return $opCode === Opcodes::OP_0;
110 191
        } elseif ($pushSize === 1) {
111 47
            $first = ord($binary[0]);
112
113 47
            if ($first >= 1 && $first <= 16) {
114 35
                return $opCode === (Opcodes::OP_1 + ($first - 1));
115 15
            } elseif ($first === 0x81) {
116 10
                return $opCode === Opcodes::OP_1NEGATE;
117
            }
118 152
        } elseif ($pushSize <= 75) {
119 143
            return $opCode === $pushSize;
120 7
        } elseif ($pushSize <= 255) {
121 5
            return $opCode === Opcodes::OP_PUSHDATA1;
122 5
        } elseif ($pushSize <= 65535) {
123 5
            return $opCode === Opcodes::OP_PUSHDATA2;
124
        }
125
126 13
        return true;
127
    }
128
129
    /**
130
     * @param int $count
131
     * @return $this
132
     */
133 2117
    private function checkOpcodeCount($count)
134
    {
135 2117
        if ($count > 201) {
136 10
            throw new \RuntimeException('Error: Script op code count');
137
        }
138
139 2117
        return $this;
140
    }
141
142
    /**
143
     * @param WitnessProgram $witnessProgram
144
     * @param ScriptWitnessInterface $scriptWitness
145
     * @param int $flags
146
     * @param Checker $checker
147
     * @return bool
148
     */
149 53
    private function verifyWitnessProgram(WitnessProgram $witnessProgram, ScriptWitnessInterface $scriptWitness, $flags, Checker $checker)
150
    {
151 53
        $witnessCount = count($scriptWitness);
152
153 53
        if ($witnessProgram->getVersion() == 0) {
154 51
            $buffer = $witnessProgram->getProgram();
155 51
            if ($buffer->getSize() === 32) {
156
                // Version 0 segregated witness program: SHA256(Script) in program, Script + inputs in witness
157 29
                if ($witnessCount === 0) {
158
                    // Must contain script at least
159 2
                    return false;
160
                }
161
162 27
                $scriptPubKey = new Script($scriptWitness[$witnessCount - 1]);
163 27
                $stackValues = $scriptWitness->slice(0, -1);
164 27
                $hashScriptPubKey = Hash::sha256($scriptPubKey->getBuffer());
165
166 27
                if (!$hashScriptPubKey->equals($buffer)) {
167 14
                    return false;
168 2
                }
169 35
            } elseif ($buffer->getSize() === 20) {
170
                // Version 0 special case for pay-to-pubkeyhash
171 20
                if ($witnessCount !== 2) {
172
                    // 2 items in witness - <signature> <pubkey>
173 2
                    return false;
174
                }
175
176 18
                $scriptPubKey = ScriptFactory::create()->sequence([Opcodes::OP_DUP, Opcodes::OP_HASH160, $buffer, Opcodes::OP_EQUALVERIFY, Opcodes::OP_CHECKSIG])->getScript();
177 18
                $stackValues = $scriptWitness;
178 10
            } else {
179 20
                return false;
180
            }
181 25
        } elseif ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM) {
182 2
            return false;
183
        } else {
184
            return false;
185
        }
186
187 41
        $mainStack = new Stack();
188 41
        foreach ($stackValues as $value) {
189 39
            $mainStack->push($value);
190 23
        }
191
192 41
        if (!$this->evaluate($scriptPubKey, $mainStack, 1, $flags, $checker)) {
193
            return false;
194
        }
195
196 41
        if ($mainStack->count() !== 1) {
197
            return false;
198
        }
199
200 41
        if (!$this->castToBool($mainStack->bottom())) {
201 18
            return false;
202
        }
203
204 23
        return true;
205
    }
206
207
    /**
208
     * @param ScriptInterface $scriptSig
209
     * @param ScriptInterface $scriptPubKey
210
     * @param int $flags
211
     * @param Checker $checker
212
     * @param ScriptWitnessInterface|null $witness
213
     * @return bool
214
     */
215 2251
    public function verify(ScriptInterface $scriptSig, ScriptInterface $scriptPubKey, $flags, Checker $checker, ScriptWitnessInterface $witness = null)
216
    {
217 2251
        static $emptyWitness = null;
218 2251
        if ($emptyWitness === null) {
219 3
            $emptyWitness = new ScriptWitness([]);
220 2
        }
221
222 2251
        $witness = is_null($witness) ? $emptyWitness : $witness;
223
224 2251
        if (($flags & self::VERIFY_SIGPUSHONLY) != 0 && !$scriptSig->isPushOnly()) {
225 4
            return false;
226
        }
227
228 2247
        $stack = new Stack();
229 2247
        if (!$this->evaluate($scriptSig, $stack, 0, $flags, $checker)) {
230 113
            return false;
231
        }
232
233 2134
        $backup = [];
234 2134
        if ($flags & self::VERIFY_P2SH) {
235 1561
            foreach ($stack as $s) {
236 1263
                $backup[] = $s;
237 788
            }
238 788
        }
239
240 2134
        if (!$this->evaluate($scriptPubKey, $stack, 0, $flags, $checker)) {
241 690
            return false;
242
        }
243
244 1444
        if ($stack->isEmpty()) {
245 23
            return false;
246
        }
247
248 1421
        if (false === $this->castToBool($stack[-1])) {
249 97
            return false;
250
        }
251
252 1324
        $program = null;
253 1324
        if ($flags & self::VERIFY_WITNESS) {
254 80
            if ($scriptPubKey->isWitness($program)) {
255
                /** @var WitnessProgram $program */
256 37
                if ($scriptSig->getBuffer()->getSize() !== 0) {
257 2
                    return false;
258
                }
259
260 35
                if (!$this->verifyWitnessProgram($program, $witness, $flags, $checker)) {
261 22
                    return false;
262
                }
263
264 13
                $stack->resize(1);
265 8
            }
266 34
        }
267
268 1300
        if ($flags & self::VERIFY_P2SH && (new OutputClassifier())->isPayToScriptHash($scriptPubKey)) {
269 68
            if (!$scriptSig->isPushOnly()) {
270 9
                return false;
271
            }
272
273 59
            $stack = new Stack();
274 59
            foreach ($backup as $i) {
275 59
                $stack->push($i);
276 32
            }
277
278
            // Restore mainStack to how it was after evaluating scriptSig
279 59
            if ($stack->isEmpty()) {
280
                return false;
281
            }
282
283
            // Load redeemscript as the scriptPubKey
284 59
            $scriptPubKey = new Script($stack->bottom());
285 59
            $stack->pop();
286
287 59
            if (!$this->evaluate($scriptPubKey, $stack, 0, $flags, $checker)) {
288 11
                return false;
289
            }
290
291 48
            if ($stack->isEmpty()) {
292
                return false;
293
            }
294
295 48
            if (!$this->castToBool($stack->bottom())) {
296 2
                return false;
297
            }
298
299 46
            if ($flags & self::VERIFY_WITNESS) {
300 26
                if ($scriptPubKey->isWitness($program)) {
301
                    /** @var WitnessProgram $program */
302 20
                    if ($scriptSig != (ScriptFactory::create()->push($scriptPubKey->getBuffer())->getScript())) {
303 2
                        return false; // SCRIPT_ERR_WITNESS_MALLEATED_P2SH
304
                    }
305
306 18
                    if (!$this->verifyWitnessProgram($program, $witness, $flags, $checker)) {
307 8
                        return false;
308
                    }
309
310 10
                    $stack->resize(1);
311 6
                }
312 10
            }
313 20
        }
314
315 1268
        if ($flags & self::VERIFY_CLEAN_STACK) {
316 15
            if (!($flags & self::VERIFY_P2SH != 0) && ($flags & self::VERIFY_WITNESS != 0)) {
317
                return false; // implied flags required
318
            }
319
320 15
            if (count($stack) != 1) {
321 4
                return false; // Cleanstack
322
            }
323 7
        }
324
325 1264
        if ($flags & self::VERIFY_WITNESS) {
326 46
            if (!$flags & self::VERIFY_P2SH) {
327
                return false; //
328
            }
329
330 46
            if ($program === null && !$witness->isNull()) {
331 2
                return false; // SCRIPT_ERR_WITNESS_UNEXPECTED
332
            }
333 28
        }
334
335 1262
        return true;
336
    }
337
338
    /**
339
     * @param Stack $vfStack
340
     * @param bool $value
341
     * @return bool
342
     */
343 2239
    private function checkExec(Stack $vfStack, $value)
344
    {
345 2239
        $ret = 0;
346 2239
        foreach ($vfStack as $item) {
347 484
            if ($item == $value) {
348 400
                $ret++;
349 158
            }
350 1142
        }
351
352 2239
        return $ret;
353
    }
354
355
    /**
356
     * @param ScriptInterface $script
357
     * @param Stack $mainStack
358
     * @param int $sigVersion
359
     * @param int $flags
360
     * @param Checker $checker
361
     * @return bool
362
     */
363 2250
    public function evaluate(ScriptInterface $script, Stack $mainStack, $sigVersion, $flags, Checker $checker)
364
    {
365 2250
        $hashStartPos = 0;
366 2250
        $opCount = 0;
367 2250
        $altStack = new Stack();
368 2250
        $vfStack = new Stack();
369 2250
        $minimal = ($flags & self::VERIFY_MINIMALDATA) != 0;
370 2250
        $parser = $script->getScriptParser();
371
372 2250
        if ($script->getBuffer()->getSize() > 10000) {
373 2
            return false;
374
        }
375
376
        try {
377 2250
            foreach ($parser as $operation) {
378 2239
                $opCode = $operation->getOp();
379 2239
                $pushData = $operation->getData();
380 2239
                $fExec = !$this->checkExec($vfStack, false);
381
382
                // If pushdata was written to
383 2239
                if ($operation->isPush() && $operation->getDataSize() > InterpreterInterface::MAX_SCRIPT_ELEMENT_SIZE) {
384 7
                    throw new \RuntimeException('Error - push size');
385
                }
386
387
                // OP_RESERVED should not count towards opCount
388 2236
                if ($opCode > Opcodes::OP_16 && ++$opCount) {
389 2117
                    $this->checkOpcodeCount($opCount);
390 1080
                }
391
392 2236
                if (in_array($opCode, $this->disabledOps, true)) {
393 48
                    throw new \RuntimeException('Disabled Opcode');
394
                }
395
396 2236
                if ($fExec && $operation->isPush()) {
397
                    // In range of a pushdata opcode
398 1642
                    if ($minimal && !$this->checkMinimalPush($opCode, $pushData)) {
399 42
                        throw new ScriptRuntimeException(self::VERIFY_MINIMALDATA, 'Minimal pushdata required');
400
                    }
401
402 1600
                    $mainStack->push($pushData);
403
                    // echo " - [pushed '" . $pushData->getHex() . "']\n";
404 2179
                } elseif ($fExec || (Opcodes::OP_IF <= $opCode && $opCode <= Opcodes::OP_ENDIF)) {
405
                    // echo "OPCODE - " . $script->getOpcodes()->getOp($opCode) . "\n";
406
                    switch ($opCode) {
407 2163
                        case Opcodes::OP_1NEGATE:
408 2163
                        case Opcodes::OP_1:
409 2141
                        case Opcodes::OP_2:
410 2137
                        case Opcodes::OP_3:
411 2137
                        case Opcodes::OP_4:
412 2137
                        case Opcodes::OP_5:
413 2137
                        case Opcodes::OP_6:
414 2137
                        case Opcodes::OP_7:
415 2136
                        case Opcodes::OP_8:
416 2136
                        case Opcodes::OP_9:
417 2136
                        case Opcodes::OP_10:
418 2136
                        case Opcodes::OP_11:
419 2135
                        case Opcodes::OP_12:
420 2135
                        case Opcodes::OP_13:
421 2135
                        case Opcodes::OP_14:
422 2135
                        case Opcodes::OP_15:
423 2135
                        case Opcodes::OP_16:
424 1335
                            $num = \BitWasp\Bitcoin\Script\decodeOpN($opCode);
425 1335
                            $mainStack->push(Number::int($num)->getBuffer());
426 1335
                            break;
427
428 2107
                        case Opcodes::OP_CHECKLOCKTIMEVERIFY:
429 12
                            if (!($flags & self::VERIFY_CHECKLOCKTIMEVERIFY)) {
430 12
                                if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
431 2
                                    throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
432
                                }
433 10
                                break;
434
                            }
435
436
                            if ($mainStack->isEmpty()) {
437
                                throw new \RuntimeException('Invalid stack operation - CLTV');
438
                            }
439
440
                            $lockTime = Number::buffer($mainStack[-1], $minimal, 5, $this->math);
441
                            if (!$checker->checkLockTime($lockTime)) {
442
                                throw new ScriptRuntimeException(self::VERIFY_CHECKLOCKTIMEVERIFY, 'Unsatisfied locktime');
443
                            }
444
445
                            break;
446
447 2105
                        case Opcodes::OP_CHECKSEQUENCEVERIFY:
448 24
                            if (!($flags & self::VERIFY_CHECKSEQUENCEVERIFY)) {
449 12
                                if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
450 2
                                    throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
451
                                }
452 10
                                break;
453
                            }
454
455 12
                            if ($mainStack->isEmpty()) {
456 2
                                throw new \RuntimeException('Invalid stack operation - CSV');
457
                            }
458
459 10
                            $sequence = Number::buffer($mainStack[-1], $minimal, 5, $this->math);
460 8
                            $nSequence = $sequence->getGmp();
461 8
                            if ($this->math->cmp($nSequence, gmp_init(0)) < 0) {
462 2
                                throw new ScriptRuntimeException(self::VERIFY_CHECKSEQUENCEVERIFY, 'Negative locktime');
463
                            }
464
465 6
                            if ($this->math->cmp($this->math->bitwiseAnd($nSequence, gmp_init(TransactionInputInterface::SEQUENCE_LOCKTIME_DISABLE_FLAG, 10)), gmp_init(0)) !== 0) {
466 2
                                break;
467
                            }
468
469 4
                            if (!$checker->checkSequence($sequence)) {
470 4
                                throw new ScriptRuntimeException(self::VERIFY_CHECKSEQUENCEVERIFY, 'Unsatisfied sequence');
471
                            }
472
                            break;
473
474 2091
                        case Opcodes::OP_NOP1:
475 2090
                        case Opcodes::OP_NOP4:
476 2089
                        case Opcodes::OP_NOP5:
477 2088
                        case Opcodes::OP_NOP6:
478 2087
                        case Opcodes::OP_NOP7:
479 2086
                        case Opcodes::OP_NOP8:
480 2085
                        case Opcodes::OP_NOP9:
481 2084
                        case Opcodes::OP_NOP10:
482 54
                            if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
483 20
                                throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
484
                            }
485 34
                            break;
486
487 2071
                        case Opcodes::OP_NOP:
488 168
                            break;
489
490 2025
                        case Opcodes::OP_IF:
491 2003
                        case Opcodes::OP_NOTIF:
492
                            // <expression> if [statements] [else [statements]] endif
493 494
                            $value = false;
494 494
                            if ($fExec) {
495 494
                                if ($mainStack->isEmpty()) {
496 4
                                    throw new \RuntimeException('Unbalanced conditional');
497
                                }
498
499 490
                                $buffer = Number::buffer($mainStack->pop(), $minimal)->getBuffer();
500 490
                                $value = $this->castToBool($buffer);
501 490
                                if ($opCode === Opcodes::OP_NOTIF) {
502 34
                                    $value = !$value;
503 17
                                }
504 245
                            }
505 490
                            $vfStack->push($value);
506 490
                            break;
507
508 1977
                        case Opcodes::OP_ELSE:
509 230
                            if ($vfStack->isEmpty()) {
510 8
                                throw new \RuntimeException('Unbalanced conditional');
511
                            }
512 226
                            $vfStack->push(!$vfStack->pop());
513 226
                            break;
514
515 1971
                        case Opcodes::OP_ENDIF:
516 294
                            if ($vfStack->isEmpty()) {
517 14
                                throw new \RuntimeException('Unbalanced conditional');
518
                            }
519 286
                            $vfStack->pop();
520 286
                            break;
521
522 1699
                        case Opcodes::OP_VERIFY:
523 60
                            if ($mainStack->isEmpty()) {
524 2
                                throw new \RuntimeException('Invalid stack operation');
525
                            }
526 58
                            $value = $this->castToBool($mainStack[-1]);
527 58
                            if (!$value) {
528 2
                                throw new \RuntimeException('Error: verify');
529
                            }
530 56
                            $mainStack->pop();
531 56
                            break;
532
533 1685
                        case Opcodes::OP_TOALTSTACK:
534 16
                            if ($mainStack->isEmpty()) {
535 2
                                throw new \RuntimeException('Invalid stack operation OP_TOALTSTACK');
536
                            }
537 14
                            $altStack->push($mainStack->pop());
538 14
                            break;
539
540 1681
                        case Opcodes::OP_FROMALTSTACK:
541 10
                            if ($altStack->isEmpty()) {
542 4
                                throw new \RuntimeException('Invalid alt-stack operation OP_FROMALTSTACK');
543
                            }
544 6
                            $mainStack->push($altStack->pop());
545 6
                            break;
546
547 1675
                        case Opcodes::OP_IFDUP:
548
                            // If top value not zero, duplicate it.
549 12
                            if ($mainStack->isEmpty()) {
550 4
                                throw new \RuntimeException('Invalid stack operation OP_IFDUP');
551
                            }
552 8
                            $vch = $mainStack[-1];
553 8
                            if ($this->castToBool($vch)) {
554 6
                                $mainStack->push($vch);
555 3
                            }
556 8
                            break;
557
558 1669
                        case Opcodes::OP_DEPTH:
559 153
                            $num = count($mainStack);
560 153
                            $depth = Number::int($num)->getBuffer();
561 153
                            $mainStack->push($depth);
562 153
                            break;
563
564 1651
                        case Opcodes::OP_DROP:
565 96
                            if ($mainStack->isEmpty()) {
566 4
                                throw new \RuntimeException('Invalid stack operation OP_DROP');
567
                            }
568 92
                            $mainStack->pop();
569 92
                            break;
570
571 1645
                        case Opcodes::OP_DUP:
572 71
                            if ($mainStack->isEmpty()) {
573 4
                                throw new \RuntimeException('Invalid stack operation OP_DUP');
574
                            }
575 67
                            $vch = $mainStack[-1];
576 67
                            $mainStack->push($vch);
577 67
                            break;
578
579 1627
                        case Opcodes::OP_NIP:
580 12
                            if (count($mainStack) < 2) {
581 6
                                throw new \RuntimeException('Invalid stack operation OP_NIP');
582
                            }
583 6
                            unset($mainStack[-2]);
584 6
                            break;
585
586 1615
                        case Opcodes::OP_OVER:
587 12
                            if (count($mainStack) < 2) {
588 6
                                throw new \RuntimeException('Invalid stack operation OP_OVER');
589
                            }
590 6
                            $vch = $mainStack[-2];
591 6
                            $mainStack->push($vch);
592 6
                            break;
593
594 1607
                        case Opcodes::OP_ROT:
595 24
                            if (count($mainStack) < 3) {
596 8
                                throw new \RuntimeException('Invalid stack operation OP_ROT');
597
                            }
598 16
                            $mainStack->swap(-3, -2);
599 16
                            $mainStack->swap(-2, -1);
600 16
                            break;
601
602 1595
                        case Opcodes::OP_SWAP:
603 20
                            if (count($mainStack) < 2) {
604 6
                                throw new \RuntimeException('Invalid stack operation OP_SWAP');
605
                            }
606 14
                            $mainStack->swap(-2, -1);
607 14
                            break;
608
609 1587
                        case Opcodes::OP_TUCK:
610 12
                            if (count($mainStack) < 2) {
611 6
                                throw new \RuntimeException('Invalid stack operation OP_TUCK');
612
                            }
613 6
                            $vch = $mainStack[-1];
614 6
                            $mainStack->add(- 2, $vch);
615 6
                            break;
616
617 1579
                        case Opcodes::OP_PICK:
618 1570
                        case Opcodes::OP_ROLL:
619 58
                            if (count($mainStack) < 2) {
620 8
                                throw new \RuntimeException('Invalid stack operation OP_PICK');
621
                            }
622
623 50
                            $n = Number::buffer($mainStack[-1], $minimal, 4)->getGmp();
624 46
                            $mainStack->pop();
625 46
                            if ($this->math->cmp($n, gmp_init(0)) < 0 || $this->math->cmp($n, gmp_init(count($mainStack))) >= 0) {
626 10
                                throw new \RuntimeException('Invalid stack operation OP_PICK');
627
                            }
628
629 36
                            $pos = (int) gmp_strval($this->math->sub($this->math->sub(gmp_init(0), $n), gmp_init(1)), 10);
630 36
                            $vch = $mainStack[$pos];
631 36
                            if ($opCode === Opcodes::OP_ROLL) {
632 18
                                unset($mainStack[$pos]);
633 9
                            }
634 36
                            $mainStack->push($vch);
635 36
                            break;
636
637 1545
                        case Opcodes::OP_2DROP:
638 18
                            if (count($mainStack) < 2) {
639 2
                                throw new \RuntimeException('Invalid stack operation OP_2DROP');
640
                            }
641 16
                            $mainStack->pop();
642 16
                            $mainStack->pop();
643 16
                            break;
644
645 1541
                        case Opcodes::OP_2DUP:
646 12
                            if (count($mainStack) < 2) {
647 6
                                throw new \RuntimeException('Invalid stack operation OP_2DUP');
648
                            }
649 6
                            $string1 = $mainStack[-2];
650 6
                            $string2 = $mainStack[-1];
651 6
                            $mainStack->push($string1);
652 6
                            $mainStack->push($string2);
653 6
                            break;
654
655 1533
                        case Opcodes::OP_3DUP:
656 22
                            if (count($mainStack) < 3) {
657 8
                                throw new \RuntimeException('Invalid stack operation OP_3DUP');
658
                            }
659 14
                            $string1 = $mainStack[-3];
660 14
                            $string2 = $mainStack[-2];
661 14
                            $string3 = $mainStack[-1];
662 14
                            $mainStack->push($string1);
663 14
                            $mainStack->push($string2);
664 14
                            $mainStack->push($string3);
665 14
                            break;
666
667 1513
                        case Opcodes::OP_2OVER:
668 10
                            if (count($mainStack) < 4) {
669 6
                                throw new \RuntimeException('Invalid stack operation OP_2OVER');
670
                            }
671 4
                            $string1 = $mainStack[-4];
672 4
                            $string2 = $mainStack[-3];
673 4
                            $mainStack->push($string1);
674 4
                            $mainStack->push($string2);
675 4
                            break;
676
677 1505
                        case Opcodes::OP_2ROT:
678 20
                            if (count($mainStack) < 6) {
679 2
                                throw new \RuntimeException('Invalid stack operation OP_2ROT');
680
                            }
681 18
                            $string1 = $mainStack[-6];
682 18
                            $string2 = $mainStack[-5];
683 18
                            unset($mainStack[-6], $mainStack[-5]);
684 18
                            $mainStack->push($string1);
685 18
                            $mainStack->push($string2);
686 18
                            break;
687
688 1501
                        case Opcodes::OP_2SWAP:
689 10
                            if (count($mainStack) < 4) {
690 6
                                throw new \RuntimeException('Invalid stack operation OP_2SWAP');
691
                            }
692 4
                            $mainStack->swap(-3, -1);
693 4
                            $mainStack->swap(-4, -2);
694 4
                            break;
695
696 1493
                        case Opcodes::OP_SIZE:
697 62
                            if ($mainStack->isEmpty()) {
698 4
                                throw new \RuntimeException('Invalid stack operation OP_SIZE');
699
                            }
700 58
                            $size = Number::int($mainStack[-1]->getSize());
701 58
                            $mainStack->push($size->getBuffer());
702 58
                            break;
703
704 1487
                        case Opcodes::OP_EQUAL:
705 1376
                        case Opcodes::OP_EQUALVERIFY:
706 586
                            if (count($mainStack) < 2) {
707 8
                                throw new \RuntimeException('Invalid stack operation OP_EQUAL');
708
                            }
709
710 578
                            $equal = $mainStack[-2]->equals($mainStack[-1]);
711 578
                            $mainStack->pop();
712 578
                            $mainStack->pop();
713 578
                            $mainStack->push($equal ? $this->vchTrue : $this->vchFalse);
714 578
                            if ($opCode === Opcodes::OP_EQUALVERIFY) {
715 105
                                if ($equal) {
716 87
                                    $mainStack->pop();
717 46
                                } else {
718 18
                                    throw new \RuntimeException('Error EQUALVERIFY');
719
                                }
720 46
                            }
721
722 562
                            break;
723
724
                        // Arithmetic operations
725 1203
                        case $opCode >= Opcodes::OP_1ADD && $opCode <= Opcodes::OP_0NOTEQUAL:
726 210
                            if ($mainStack->isEmpty()) {
727 12
                                throw new \Exception('Invalid stack operation 1ADD-OP_0NOTEQUAL');
728
                            }
729
730 198
                            $num = Number::buffer($mainStack[-1], $minimal)->getGmp();
731
732 152
                            if ($opCode === Opcodes::OP_1ADD) {
733 14
                                $num = $this->math->add($num, gmp_init(1));
734 145
                            } elseif ($opCode === Opcodes::OP_1SUB) {
735 6
                                $num = $this->math->sub($num, gmp_init(1));
736 135
                            } elseif ($opCode === Opcodes::OP_2MUL) {
737
                                $num = $this->math->mul(gmp_init(2), $num);
738 132
                            } elseif ($opCode === Opcodes::OP_NEGATE) {
739 8
                                $num = $this->math->sub(gmp_init(0), $num);
740 129
                            } elseif ($opCode === Opcodes::OP_ABS) {
741 10
                                if ($this->math->cmp($num, gmp_init(0)) < 0) {
742 7
                                    $num = $this->math->sub(gmp_init(0), $num);
743 2
                                }
744 121
                            } elseif ($opCode === Opcodes::OP_NOT) {
745 104
                                $num = gmp_init($this->math->cmp($num, gmp_init(0)) == 0 ? 1 : 0);
746 53
                            } else {
747
                                // is OP_0NOTEQUAL
748 12
                                $num = gmp_init($this->math->cmp($num, gmp_init(0)) != 0 ? 1 : 0);
749
                            }
750
751 152
                            $mainStack->pop();
752
753 152
                            $buffer = Number::int(gmp_strval($num, 10))->getBuffer();
754
755 152
                            $mainStack->push($buffer);
756 152
                            break;
757
758 1085
                        case $opCode >= Opcodes::OP_ADD && $opCode <= Opcodes::OP_MAX:
759 328
                            if (count($mainStack) < 2) {
760 26
                                throw new \Exception('Invalid stack operation (OP_ADD - OP_MAX)');
761
                            }
762
763 302
                            $num1 = Number::buffer($mainStack[-2], $minimal)->getGmp();
764 268
                            $num2 = Number::buffer($mainStack[-1], $minimal)->getGmp();
765
766 242
                            if ($opCode === Opcodes::OP_ADD) {
767 60
                                $num = $this->math->add($num1, $num2);
768 218
                            } else if ($opCode === Opcodes::OP_SUB) {
769 12
                                $num = $this->math->sub($num1, $num2);
770 188
                            } else if ($opCode === Opcodes::OP_BOOLAND) {
771 16
                                $num = $this->math->cmp($num1, gmp_init(0)) !== 0 && $this->math->cmp($num2, gmp_init(0)) !== 0;
772 174
                            } else if ($opCode === Opcodes::OP_BOOLOR) {
773 16
                                $num = $this->math->cmp($num1, gmp_init(0)) !== 0 || $this->math->cmp($num2, gmp_init(0)) !== 0;
774 158
                            } elseif ($opCode === Opcodes::OP_NUMEQUAL) {
775 56
                                $num = $this->math->cmp($num1, $num2) === 0;
776 130
                            } elseif ($opCode === Opcodes::OP_NUMEQUALVERIFY) {
777 8
                                $num = $this->math->cmp($num1, $num2) === 0;
778 106
                            } elseif ($opCode === Opcodes::OP_NUMNOTEQUAL) {
779 10
                                $num = $this->math->cmp($num1, $num2) !== 0;
780 97
                            } elseif ($opCode === Opcodes::OP_LESSTHAN) {
781 16
                                $num = $this->math->cmp($num1, $num2) < 0;
782 84
                            } elseif ($opCode === Opcodes::OP_GREATERTHAN) {
783 16
                                $num = $this->math->cmp($num1, $num2) > 0;
784 68
                            } elseif ($opCode === Opcodes::OP_LESSTHANOREQUAL) {
785 16
                                $num = $this->math->cmp($num1, $num2) <= 0;
786 52
                            } elseif ($opCode === Opcodes::OP_GREATERTHANOREQUAL) {
787 16
                                $num = $this->math->cmp($num1, $num2) >= 0;
788 36
                            } elseif ($opCode === Opcodes::OP_MIN) {
789 14
                                $num = ($this->math->cmp($num1, $num2) <= 0) ? $num1 : $num2;
790 7
                            } else {
791 14
                                $num = ($this->math->cmp($num1, $num2) >= 0) ? $num1 : $num2;
792
                            }
793
794 242
                            $mainStack->pop();
795 242
                            $mainStack->pop();
796 242
                            $buffer = Number::int(gmp_strval($num, 10))->getBuffer();
797 242
                            $mainStack->push($buffer);
798
799 242
                            if ($opCode === Opcodes::OP_NUMEQUALVERIFY) {
800 8
                                if ($this->castToBool($mainStack[-1])) {
801 8
                                    $mainStack->pop();
802 4
                                } else {
803
                                    throw new \RuntimeException('NUM EQUAL VERIFY error');
804
                                }
805 4
                            }
806 242
                            break;
807
808 757
                        case Opcodes::OP_WITHIN:
809 30
                            if (count($mainStack) < 3) {
810 2
                                throw new \RuntimeException('Invalid stack operation');
811
                            }
812
813 28
                            $num1 = Number::buffer($mainStack[-3], $minimal)->getGmp();
814 26
                            $num2 = Number::buffer($mainStack[-2], $minimal)->getGmp();
815 24
                            $num3 = Number::buffer($mainStack[-1], $minimal)->getGmp();
816
817 22
                            $value = $this->math->cmp($num2, $num1) <= 0 && $this->math->cmp($num1, $num3) < 0;
818 22
                            $mainStack->pop();
819 22
                            $mainStack->pop();
820 22
                            $mainStack->pop();
821 22
                            $mainStack->push($value ? $this->vchTrue : $this->vchFalse);
822 22
                            break;
823
824
                        // Hash operation
825 727
                        case Opcodes::OP_RIPEMD160:
826 721
                        case Opcodes::OP_SHA1:
827 713
                        case Opcodes::OP_SHA256:
828 707
                        case Opcodes::OP_HASH160:
829 684
                        case Opcodes::OP_HASH256:
830 167
                            if ($mainStack->isEmpty()) {
831 23
                                throw new \RuntimeException('Invalid stack operation');
832
                            }
833
834 144
                            $buffer = $mainStack[-1];
835 144
                            if ($opCode === Opcodes::OP_RIPEMD160) {
836 10
                                $hash = Hash::ripemd160($buffer);
837 140
                            } elseif ($opCode === Opcodes::OP_SHA1) {
838 12
                                $hash = Hash::sha1($buffer);
839 130
                            } elseif ($opCode === Opcodes::OP_SHA256) {
840 12
                                $hash = Hash::sha256($buffer);
841 120
                            } elseif ($opCode === Opcodes::OP_HASH160) {
842 106
                                $hash = Hash::sha256ripe160($buffer);
843 58
                            } else {
844 10
                                $hash = Hash::sha256d($buffer);
845
                            }
846
847 144
                            $mainStack->pop();
848 144
                            $mainStack->push($hash);
849 144
                            break;
850
851 625
                        case Opcodes::OP_CODESEPARATOR:
852 2
                            $hashStartPos = $parser->getPosition();
853 2
                            break;
854
855 623
                        case Opcodes::OP_CHECKSIG:
856 535
                        case Opcodes::OP_CHECKSIGVERIFY:
857 203
                            if (count($mainStack) < 2) {
858 4
                                throw new \RuntimeException('Invalid stack operation');
859
                            }
860
861 199
                            $vchPubKey = $mainStack[-1];
862 199
                            $vchSig = $mainStack[-2];
863
864 199
                            $scriptCode = new Script($script->getBuffer()->slice($hashStartPos));
865
866 199
                            $success = $checker->checkSig($scriptCode, $vchSig, $vchPubKey, $sigVersion, $flags);
867
868 133
                            $mainStack->pop();
869 133
                            $mainStack->pop();
870 133
                            $mainStack->push($success ? $this->vchTrue : $this->vchFalse);
871
872 133
                            if ($opCode === Opcodes::OP_CHECKSIGVERIFY) {
873
                                if ($success) {
874
                                    $mainStack->pop();
875
                                } else {
876
                                    throw new \RuntimeException('Checksig verify');
877
                                }
878
                            }
879 133
                            break;
880
881 420
                        case Opcodes::OP_CHECKMULTISIG:
882 343
                        case Opcodes::OP_CHECKMULTISIGVERIFY:
883 229
                            $i = 1;
884 229
                            if (count($mainStack) < $i) {
885 2
                                throw new \RuntimeException('Invalid stack operation');
886
                            }
887
888 227
                            $keyCount = Number::buffer($mainStack[-$i], $minimal)->getInt();
889 223
                            if ($keyCount < 0 || $keyCount > 20) {
890 4
                                throw new \RuntimeException('OP_CHECKMULTISIG: Public key count exceeds 20');
891
                            }
892
893 219
                            $opCount += $keyCount;
894 219
                            $this->checkOpcodeCount($opCount);
895
896
                            // Extract positions of the keys, and signatures, from the stack.
897 219
                            $ikey = ++$i;
898 219
                            $i += $keyCount; /** @var int $i */
899 219
                            if (count($mainStack) < $i) {
900 2
                                throw new \RuntimeException('Invalid stack operation');
901
                            }
902
903 217
                            $sigCount = Number::buffer($mainStack[-$i], $minimal)->getInt();
904 211
                            if ($sigCount < 0 || $sigCount > $keyCount) {
905 4
                                throw new \RuntimeException('Invalid Signature count');
906
                            }
907
908 207
                            $isig = ++$i;
909 207
                            $i += $sigCount;
910
911
                            // Extract the script since the last OP_CODESEPARATOR
912 207
                            $scriptCode = new Script($script->getBuffer()->slice($hashStartPos));
913
914 207
                            $fSuccess = true;
915 207
                            while ($fSuccess && $sigCount > 0) {
916
                                // Fetch the signature and public key
917 87
                                $sig = $mainStack[-$isig];
918 85
                                $pubkey = $mainStack[-$ikey];
919
920 85
                                if ($checker->checkSig($scriptCode, $sig, $pubkey, $sigVersion, $flags)) {
921 45
                                    $isig++;
922 45
                                    $sigCount--;
923 26
                                }
924
925 71
                                $ikey++;
926 71
                                $keyCount--;
927
928
                                // If there are more signatures left than keys left,
929
                                // then too many signatures have failed. Exit early,
930
                                // without checking any further signatures.
931 71
                                if ($sigCount > $keyCount) {
932 30
                                    $fSuccess = false;
933 16
                                }
934 40
                            }
935
936 185
                            while ($i-- > 1) {
937 185
                                $mainStack->pop();
938 96
                            }
939
940
                            // A bug causes CHECKMULTISIG to consume one extra argument
941
                            // whose contents were not checked in any way.
942
                            //
943
                            // Unfortunately this is a potential source of mutability,
944
                            // so optionally verify it is exactly equal to zero prior
945
                            // to removing it from the stack.
946 185
                            if ($mainStack->isEmpty()) {
947 2
                                throw new \RuntimeException('Invalid stack operation');
948
                            }
949
950 185
                            if ($flags & self::VERIFY_NULL_DUMMY && $mainStack[-1]->getSize() !== 0) {
951 4
                                throw new ScriptRuntimeException(self::VERIFY_NULL_DUMMY, 'Extra P2SH stack value should be OP_0');
952
                            }
953
954 181
                            $mainStack->pop();
955 181
                            $mainStack->push($fSuccess ? $this->vchTrue : $this->vchFalse);
956
957 181
                            if ($opCode === Opcodes::OP_CHECKMULTISIGVERIFY) {
958 60
                                if ($fSuccess) {
959 60
                                    $mainStack->pop();
960 30
                                } else {
961
                                    throw new \RuntimeException('OP_CHECKMULTISIG verify');
962
                                }
963 30
                            }
964 181
                            break;
965
966 97
                        default:
967 191
                            throw new \RuntimeException('Opcode not found');
968 97
                    }
969
970 1938
                    if (count($mainStack) + count($altStack) > 1000) {
971 1066
                        throw new \RuntimeException('Invalid stack size, exceeds 1000');
972
                    }
973 981
                }
974 1117
            }
975
976 2147
            if (count($vfStack) !== 0) {
977 12
                throw new \RuntimeException('Unbalanced conditional at script end');
978
            }
979
980 2137
            return true;
981 815
        } catch (ScriptRuntimeException $e) {
982
            // echo "\n Runtime: " . $e->getMessage() . "\n" . $e->getTraceAsString() . PHP_EOL;
983
            // Failure due to script tags, can access flag: $e->getFailureFlag()
984 162
            return false;
985 653
        } catch (\Exception $e) {
986
            // echo "\n General: " . $e->getMessage()  . PHP_EOL . $e->getTraceAsString() . PHP_EOL;
987 653
            return false;
988
        }
989
    }
990
}
991