Completed
Pull Request — master (#332)
by thomas
38:04
created

Interpreter::verifyWitnessProgram()   C

Complexity

Conditions 12
Paths 22

Size

Total Lines 54
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 30
CRAP Score 12.1081

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 12
eloc 33
c 1
b 0
f 1
nc 22
nop 4
dl 0
loc 54
ccs 30
cts 33
cp 0.9091
crap 12.1081
rs 6.7848

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