Completed
Push — master ( 26690c...ea008d )
by thomas
177:34 queued 174:51
created

Interpreter::castToBool()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 5.025

Importance

Changes 0
Metric Value
cc 5
eloc 9
nc 4
nop 1
dl 0
loc 14
ccs 9
cts 10
cp 0.9
crap 5.025
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
namespace BitWasp\Bitcoin\Script\Interpreter;
4
5
use BitWasp\Bitcoin\Bitcoin;
6
use BitWasp\Bitcoin\Crypto\EcAdapter\Adapter\EcAdapterInterface;
7
use BitWasp\Bitcoin\Crypto\Hash;
8
use BitWasp\Bitcoin\Exceptions\SignatureNotCanonical;
9
use BitWasp\Bitcoin\Exceptions\ScriptRuntimeException;
10
use BitWasp\Bitcoin\Script\Classifier\OutputClassifier;
11
use BitWasp\Bitcoin\Script\Opcodes;
12
use BitWasp\Bitcoin\Script\Script;
13
use BitWasp\Bitcoin\Script\ScriptFactory;
14
use BitWasp\Bitcoin\Script\ScriptInterface;
15
use BitWasp\Bitcoin\Script\ScriptWitness;
16
use BitWasp\Bitcoin\Script\ScriptWitnessInterface;
17
use BitWasp\Bitcoin\Script\WitnessProgram;
18
use BitWasp\Bitcoin\Signature\TransactionSignature;
19
use BitWasp\Bitcoin\Transaction\TransactionInputInterface;
20
use BitWasp\Buffertools\Buffer;
21
use BitWasp\Buffertools\BufferInterface;
22
23
class Interpreter implements InterpreterInterface
24
{
25
26
    /**
27
     * @var \BitWasp\Bitcoin\Math\Math
28
     */
29
    private $math;
30
31
    /**
32
     * @var BufferInterface
33
     */
34
    private $vchFalse;
35
36
    /**
37
     * @var BufferInterface
38
     */
39
    private $vchTrue;
40
41
    /**
42
     * @var array
43
     */
44
    private $disabledOps = [
45
        Opcodes::OP_CAT,    Opcodes::OP_SUBSTR, Opcodes::OP_LEFT,  Opcodes::OP_RIGHT,
46
        Opcodes::OP_INVERT, Opcodes::OP_AND,    Opcodes::OP_OR,    Opcodes::OP_XOR,
47
        Opcodes::OP_2MUL,   Opcodes::OP_2DIV,   Opcodes::OP_MUL,   Opcodes::OP_DIV,
48
        Opcodes::OP_MOD,    Opcodes::OP_LSHIFT, Opcodes::OP_RSHIFT
49
    ];
50
51
    /**
52
     * @param EcAdapterInterface $ecAdapter
53
     */
54 99
    public function __construct(EcAdapterInterface $ecAdapter = null)
55
    {
56 99
        $ecAdapter = $ecAdapter ?: Bitcoin::getEcAdapter();
57 99
        $this->math = $ecAdapter->getMath();
58 99
        $this->vchFalse = new Buffer("", 0, $this->math);
59 99
        $this->vchTrue = new Buffer("\x01", 1, $this->math);
60 99
    }
61
62
    /**
63
     * Cast the value to a boolean
64
     *
65
     * @param BufferInterface $value
66
     * @return bool
67
     */
68 3267
    public function castToBool(BufferInterface $value)
69
    {
70 3267
        $val = $value->getBinary();
71 3267
        for ($i = 0, $size = strlen($val); $i < $size; $i++) {
72 2995
            $chr = ord($val[$i]);
73 2995
            if ($chr != 0) {
74 2989
                if (($i == ($size - 1)) && $chr == 0x80) {
75
                    return false;
76
                }
77 2989
                return true;
78
            }
79 6
        }
80 790
        return false;
81
    }
82
83
    /**
84
     * @param BufferInterface $signature
85
     * @return bool
86
     */
87
    public function isValidSignatureEncoding(BufferInterface $signature)
88
    {
89
        try {
90
            TransactionSignature::isDERSignature($signature);
91
            return true;
92
        } catch (SignatureNotCanonical $e) {
93
            /* In any case, we will return false outside this block */
94
        }
95
96
        return false;
97
    }
98
99
    /**
100
     * @param int $opCode
101
     * @param BufferInterface $pushData
102
     * @return bool
103
     * @throws \Exception
104
     */
105 466
    public function checkMinimalPush($opCode, BufferInterface $pushData)
106
    {
107 466
        $pushSize = $pushData->getSize();
108 466
        $binary = $pushData->getBinary();
109
110 466
        if ($pushSize === 0) {
111 222
            return $opCode === Opcodes::OP_0;
112 382
        } elseif ($pushSize === 1) {
113 94
            $first = ord($binary[0]);
114
115 94
            if ($first >= 1 && $first <= 16) {
116 70
                return $opCode === (Opcodes::OP_1 + ($first - 1));
117 30
            } elseif ($first === 0x81) {
118 20
                return $opCode === Opcodes::OP_1NEGATE;
119
            }
120 304
        } elseif ($pushSize <= 75) {
121 286
            return $opCode === $pushSize;
122 14
        } elseif ($pushSize <= 255) {
123 10
            return $opCode === Opcodes::OP_PUSHDATA1;
124 10
        } elseif ($pushSize <= 65535) {
125 10
            return $opCode === Opcodes::OP_PUSHDATA2;
126
        }
127
128 26
        return true;
129
    }
130
131
    /**
132
     * @param int $count
133
     * @return $this
134
     */
135 4207
    private function checkOpcodeCount($count)
136
    {
137 4207
        if ($count > 201) {
138 20
            throw new \RuntimeException('Error: Script op code count');
139
        }
140
141 4207
        return $this;
142
    }
143
144
    /**
145
     * @param WitnessProgram $witnessProgram
146
     * @param ScriptWitnessInterface $scriptWitness
147
     * @param int $flags
148
     * @param Checker $checker
149
     * @return bool
150
     */
151 91
    private function verifyWitnessProgram(WitnessProgram $witnessProgram, ScriptWitnessInterface $scriptWitness, $flags, Checker $checker)
152
    {
153 91
        $witnessCount = count($scriptWitness);
154
155 91
        if ($witnessProgram->getVersion() == 0) {
156 87
            $buffer = $witnessProgram->getProgram();
157 87
            if ($buffer->getSize() === 32) {
158
                // Version 0 segregated witness program: SHA256(Script) in program, Script + inputs in witness
159 49
                if ($witnessCount === 0) {
160
                    // Must contain script at least
161 4
                    return false;
162
                }
163
164 45
                $scriptPubKey = new Script($scriptWitness[$witnessCount - 1]);
165 45
                $stackValues = $scriptWitness->slice(0, -1);
166 45
                $hashScriptPubKey = Hash::sha256($scriptPubKey->getBuffer());
167
168 47
                if (!$hashScriptPubKey->equals($buffer)) {
0 ignored issues
show
Documentation introduced by
$buffer is of type object<BitWasp\Buffertools\BufferInterface>, but the function expects a object<self>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
169 28
                    return false;
170
                }
171 55
            } elseif ($buffer->getSize() === 20) {
172
                // Version 0 special case for pay-to-pubkeyhash
173 34
                if ($witnessCount !== 2) {
174
                    // 2 items in witness - <signature> <pubkey>
175 4
                    return false;
176
                }
177
178 30
                $scriptPubKey = ScriptFactory::scriptPubKey()->payToPubKeyHashFromHash($buffer);
179 30
                $stackValues = $scriptWitness;
180 14
            } else {
181 40
                return false;
182
            }
183 35
        } elseif ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM) {
184 4
            return false;
185
        } else {
186
            return false;
187
        }
188
189 67
        $mainStack = new Stack();
190 67
        foreach ($stackValues as $value) {
191 63
            $mainStack->push($value);
192 31
        }
193
194 67
        if (!$this->evaluate($scriptPubKey, $mainStack, 1, $flags, $checker)) {
195
            return false;
196
        }
197
198 67
        if ($mainStack->count() !== 1) {
199
            return false;
200
        }
201
202 67
        if (!$this->castToBool($mainStack->bottom())) {
203 36
            return false;
204
        }
205
206 31
        return true;
207
    }
208
209
    /**
210
     * @param ScriptInterface $scriptSig
211
     * @param ScriptInterface $scriptPubKey
212
     * @param int $flags
213
     * @param Checker $checker
214
     * @param ScriptWitnessInterface|null $witness
215
     * @return bool
216
     */
217 4475
    public function verify(ScriptInterface $scriptSig, ScriptInterface $scriptPubKey, $flags, Checker $checker, ScriptWitnessInterface $witness = null)
218
    {
219 4475
        static $emptyWitness = null;
220 4475
        if ($emptyWitness === null) {
221 6
            $emptyWitness = new ScriptWitness([]);
222 2
        }
223
224 4475
        $witness = is_null($witness) ? $emptyWitness : $witness;
225
226 4475
        if (($flags & self::VERIFY_SIGPUSHONLY) != 0 && !$scriptSig->isPushOnly()) {
227 8
            return false;
228
        }
229
230 4467
        $stack = new Stack();
231 4467
        if (!$this->evaluate($scriptSig, $stack, 0, $flags, $checker)) {
232 226
            return false;
233
        }
234
235 4241
        $backup = [];
236 4241
        if ($flags & self::VERIFY_P2SH) {
237 3095
            foreach ($stack as $s) {
238 2508
                $backup[] = $s;
239 1537
            }
240 1537
        }
241
242 4241
        if (!$this->evaluate($scriptPubKey, $stack, 0, $flags, $checker)) {
243 1380
            return false;
244
        }
245
246 2861
        if ($stack->isEmpty()) {
247 46
            return false;
248
        }
249
250 2815
        if (false === $this->castToBool($stack[-1])) {
251 194
            return false;
252
        }
253
254 2621
        $program = null;
255 2621
        if ($flags & self::VERIFY_WITNESS) {
256 133
            if ($scriptPubKey->isWitness($program)) {
257
                /** @var WitnessProgram $program */
258 65
                if ($scriptSig->getBuffer()->getSize() !== 0) {
259 4
                    return false;
260
                }
261
262 61
                if (!$this->verifyWitnessProgram($program, $witness, $flags, $checker)) {
263 44
                    return false;
264
                }
265
266 17
                $stack->resize(1);
267 7
            }
268 35
        }
269
270 2573
        if ($flags & self::VERIFY_P2SH && (new OutputClassifier())->isPayToScriptHash($scriptPubKey)) {
271 127
            if (!$scriptSig->isPushOnly()) {
272 18
                return false;
273
            }
274
275 109
            $stack = new Stack();
276 109
            foreach ($backup as $i) {
277 109
                $stack->push($i);
278 51
            }
279
280
            // Restore mainStack to how it was after evaluating scriptSig
281 109
            if ($stack->isEmpty()) {
282
                return false;
283
            }
284
285
            // Load redeemscript as the scriptPubKey
286 109
            $scriptPubKey = new Script($stack->bottom());
287 109
            $stack->pop();
288
289 109
            if (!$this->evaluate($scriptPubKey, $stack, 0, $flags, $checker)) {
290 22
                return false;
291
            }
292
293 87
            if ($stack->isEmpty()) {
294
                return false;
295
            }
296
297 87
            if (!$this->castToBool($stack->bottom())) {
298 4
                return false;
299
            }
300
301 83
            if ($flags & self::VERIFY_WITNESS) {
302 43
                if ($scriptPubKey->isWitness($program)) {
303
                    /** @var WitnessProgram $program */
304 34
                    if (!$scriptSig->equals(ScriptFactory::sequence([$scriptPubKey->getBuffer()]))) {
305 4
                        return false; // SCRIPT_ERR_WITNESS_MALLEATED_P2SH
306
                    }
307
308 30
                    if (!$this->verifyWitnessProgram($program, $witness, $flags, $checker)) {
309 16
                        return false;
310
                    }
311
312 14
                    $stack->resize(1);
313 6
                }
314 9
            }
315 29
        }
316
317 2509
        if ($flags & self::VERIFY_CLEAN_STACK) {
318 30
            if (!($flags & self::VERIFY_P2SH != 0) && ($flags & self::VERIFY_WITNESS != 0)) {
319
                return false; // implied flags required
320
            }
321
322 30
            if (count($stack) != 1) {
323 8
                return false; // Cleanstack
324
            }
325 8
        }
326
327 2501
        if ($flags & self::VERIFY_WITNESS) {
328 65
            if (!$flags & self::VERIFY_P2SH) {
329
                return false; //
330
            }
331
332 65
            if ($program === null && !$witness->isNull()) {
333 4
                return false; // SCRIPT_ERR_WITNESS_UNEXPECTED
334
            }
335 23
        }
336
337 2497
        return true;
338
    }
339
340
    /**
341
     * @param Stack $vfStack
342
     * @param bool $value
343
     * @return bool
344
     */
345 4451
    private function checkExec(Stack $vfStack, $value)
346
    {
347 4451
        $ret = 0;
348 4451
        foreach ($vfStack as $item) {
349 968
            if ($item == $value) {
350 800
                $ret++;
351 316
            }
352 2185
        }
353
354 4451
        return $ret;
355
    }
356
357
    /**
358
     * @param ScriptInterface $script
359
     * @param Stack $mainStack
360
     * @param int $sigVersion
361
     * @param int $flags
362
     * @param Checker $checker
363
     * @return bool
364
     */
365 4473
    public function evaluate(ScriptInterface $script, Stack $mainStack, $sigVersion, $flags, Checker $checker)
366
    {
367 4473
        $hashStartPos = 0;
368 4473
        $opCount = 0;
369 4473
        $altStack = new Stack();
370 4473
        $vfStack = new Stack();
371 4473
        $minimal = ($flags & self::VERIFY_MINIMALDATA) != 0;
372 4473
        $parser = $script->getScriptParser();
373
374 4473
        if ($script->getBuffer()->getSize() > 10000) {
375 4
            return false;
376
        }
377
378
        try {
379 4473
            foreach ($parser as $operation) {
380 4451
                $opCode = $operation->getOp();
381 4451
                $pushData = $operation->getData();
382 4451
                $fExec = !$this->checkExec($vfStack, false);
383
384
                // If pushdata was written to
385 4451
                if ($operation->isPush() && $operation->getDataSize() > InterpreterInterface::MAX_SCRIPT_ELEMENT_SIZE) {
386 14
                    throw new \RuntimeException('Error - push size');
387
                }
388
389
                // OP_RESERVED should not count towards opCount
390 4445
                if ($opCode > Opcodes::OP_16 && ++$opCount) {
391 4207
                    $this->checkOpcodeCount($opCount);
392 2065
                }
393
394 4445
                if (in_array($opCode, $this->disabledOps, true)) {
395 96
                    throw new \RuntimeException('Disabled Opcode');
396
                }
397
398 4445
                if ($fExec && $operation->isPush()) {
399
                    // In range of a pushdata opcode
400 3257
                    if ($minimal && !$this->checkMinimalPush($opCode, $pushData)) {
401 84
                        throw new ScriptRuntimeException(self::VERIFY_MINIMALDATA, 'Minimal pushdata required');
402
                    }
403
404 3173
                    $mainStack->push($pushData);
405
                    // echo " - [pushed '" . $pushData->getHex() . "']\n";
406 4329
                } elseif ($fExec || (Opcodes::OP_IF <= $opCode && $opCode <= Opcodes::OP_ENDIF)) {
407
                    // echo "OPCODE - " . $script->getOpcodes()->getOp($opCode) . "\n";
408
                    switch ($opCode) {
409 4299
                        case Opcodes::OP_1NEGATE:
410 4299
                        case Opcodes::OP_1:
411 4255
                        case Opcodes::OP_2:
412 4247
                        case Opcodes::OP_3:
413 4247
                        case Opcodes::OP_4:
414 4247
                        case Opcodes::OP_5:
415 4247
                        case Opcodes::OP_6:
416 4247
                        case Opcodes::OP_7:
417 4245
                        case Opcodes::OP_8:
418 4245
                        case Opcodes::OP_9:
419 4245
                        case Opcodes::OP_10:
420 4245
                        case Opcodes::OP_11:
421 4243
                        case Opcodes::OP_12:
422 4243
                        case Opcodes::OP_13:
423 4243
                        case Opcodes::OP_14:
424 4243
                        case Opcodes::OP_15:
425 4243
                        case Opcodes::OP_16:
426 2658
                            $num = \BitWasp\Bitcoin\Script\decodeOpN($opCode);
427 2658
                            $mainStack->push(Number::int($num)->getBuffer());
428 2658
                            break;
429
430 4187
                        case Opcodes::OP_CHECKLOCKTIMEVERIFY:
431 24
                            if (!($flags & self::VERIFY_CHECKLOCKTIMEVERIFY)) {
432 24
                                if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
433 4
                                    throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
434
                                }
435 20
                                break;
436
                            }
437
438
                            if ($mainStack->isEmpty()) {
439
                                throw new \RuntimeException('Invalid stack operation - CLTV');
440
                            }
441
442
                            $lockTime = Number::buffer($mainStack[-1], $minimal, 5, $this->math);
443
                            if (!$checker->checkLockTime($lockTime)) {
444
                                throw new ScriptRuntimeException(self::VERIFY_CHECKLOCKTIMEVERIFY, 'Unsatisfied locktime');
445
                            }
446
447
                            break;
448
449 4183
                        case Opcodes::OP_CHECKSEQUENCEVERIFY:
450 48
                            if (!($flags & self::VERIFY_CHECKSEQUENCEVERIFY)) {
451 24
                                if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
452 4
                                    throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
453
                                }
454 20
                                break;
455
                            }
456
457 24
                            if ($mainStack->isEmpty()) {
458 4
                                throw new \RuntimeException('Invalid stack operation - CSV');
459
                            }
460
461 20
                            $sequence = Number::buffer($mainStack[-1], $minimal, 5, $this->math);
462 16
                            $nSequence = $sequence->getGmp();
463 16
                            if ($this->math->cmp($nSequence, gmp_init(0)) < 0) {
464 4
                                throw new ScriptRuntimeException(self::VERIFY_CHECKSEQUENCEVERIFY, 'Negative locktime');
465
                            }
466
467 12
                            if ($this->math->cmp($this->math->bitwiseAnd($nSequence, gmp_init(TransactionInputInterface::SEQUENCE_LOCKTIME_DISABLE_FLAG, 10)), gmp_init(0)) !== 0) {
468 4
                                break;
469
                            }
470
471 8
                            if (!$checker->checkSequence($sequence)) {
472 8
                                throw new ScriptRuntimeException(self::VERIFY_CHECKSEQUENCEVERIFY, 'Unsatisfied sequence');
473
                            }
474
                            break;
475
476 4155
                        case Opcodes::OP_NOP1:
477 4153
                        case Opcodes::OP_NOP4:
478 4151
                        case Opcodes::OP_NOP5:
479 4149
                        case Opcodes::OP_NOP6:
480 4147
                        case Opcodes::OP_NOP7:
481 4145
                        case Opcodes::OP_NOP8:
482 4143
                        case Opcodes::OP_NOP9:
483 4141
                        case Opcodes::OP_NOP10:
484 108
                            if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
485 40
                                throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
486
                            }
487 68
                            break;
488
489 4115
                        case Opcodes::OP_NOP:
490 336
                            break;
491
492 4023
                        case Opcodes::OP_IF:
493 3979
                        case Opcodes::OP_NOTIF:
494
                            // <expression> if [statements] [else [statements]] endif
495 988
                            $value = false;
496 988
                            if ($fExec) {
497 988
                                if ($mainStack->isEmpty()) {
498 8
                                    throw new \RuntimeException('Unbalanced conditional');
499
                                }
500
501 980
                                $buffer = Number::buffer($mainStack->pop(), $minimal)->getBuffer();
502 980
                                $value = $this->castToBool($buffer);
503 980
                                if ($opCode === Opcodes::OP_NOTIF) {
504 68
                                    $value = !$value;
505 34
                                }
506 490
                            }
507 980
                            $vfStack->push($value);
508 980
                            break;
509
510 3927
                        case Opcodes::OP_ELSE:
511 460
                            if ($vfStack->isEmpty()) {
512 16
                                throw new \RuntimeException('Unbalanced conditional');
513
                            }
514 452
                            $vfStack->push(!$vfStack->pop());
515 452
                            break;
516
517 3915
                        case Opcodes::OP_ENDIF:
518 588
                            if ($vfStack->isEmpty()) {
519 28
                                throw new \RuntimeException('Unbalanced conditional');
520
                            }
521 572
                            $vfStack->pop();
522 572
                            break;
523
524 3371
                        case Opcodes::OP_VERIFY:
525 120
                            if ($mainStack->isEmpty()) {
526 4
                                throw new \RuntimeException('Invalid stack operation');
527
                            }
528 116
                            $value = $this->castToBool($mainStack[-1]);
529 116
                            if (!$value) {
530 4
                                throw new \RuntimeException('Error: verify');
531
                            }
532 112
                            $mainStack->pop();
533 112
                            break;
534
535 3343
                        case Opcodes::OP_TOALTSTACK:
536 32
                            if ($mainStack->isEmpty()) {
537 4
                                throw new \RuntimeException('Invalid stack operation OP_TOALTSTACK');
538
                            }
539 28
                            $altStack->push($mainStack->pop());
540 28
                            break;
541
542 3335
                        case Opcodes::OP_FROMALTSTACK:
543 20
                            if ($altStack->isEmpty()) {
544 8
                                throw new \RuntimeException('Invalid alt-stack operation OP_FROMALTSTACK');
545
                            }
546 12
                            $mainStack->push($altStack->pop());
547 12
                            break;
548
549 3323
                        case Opcodes::OP_IFDUP:
550
                            // If top value not zero, duplicate it.
551 24
                            if ($mainStack->isEmpty()) {
552 8
                                throw new \RuntimeException('Invalid stack operation OP_IFDUP');
553
                            }
554 16
                            $vch = $mainStack[-1];
555 16
                            if ($this->castToBool($vch)) {
556 12
                                $mainStack->push($vch);
557 6
                            }
558 16
                            break;
559
560 3311
                        case Opcodes::OP_DEPTH:
561 306
                            $num = count($mainStack);
562 306
                            $depth = Number::int($num)->getBuffer();
563 306
                            $mainStack->push($depth);
564 306
                            break;
565
566 3275
                        case Opcodes::OP_DROP:
567 192
                            if ($mainStack->isEmpty()) {
568 8
                                throw new \RuntimeException('Invalid stack operation OP_DROP');
569
                            }
570 184
                            $mainStack->pop();
571 184
                            break;
572
573 3263
                        case Opcodes::OP_DUP:
574 130
                            if ($mainStack->isEmpty()) {
575 8
                                throw new \RuntimeException('Invalid stack operation OP_DUP');
576
                            }
577 122
                            $vch = $mainStack[-1];
578 122
                            $mainStack->push($vch);
579 122
                            break;
580
581 3227
                        case Opcodes::OP_NIP:
582 24
                            if (count($mainStack) < 2) {
583 12
                                throw new \RuntimeException('Invalid stack operation OP_NIP');
584
                            }
585 12
                            unset($mainStack[-2]);
586 12
                            break;
587
588 3203
                        case Opcodes::OP_OVER:
589 24
                            if (count($mainStack) < 2) {
590 12
                                throw new \RuntimeException('Invalid stack operation OP_OVER');
591
                            }
592 12
                            $vch = $mainStack[-2];
593 12
                            $mainStack->push($vch);
594 12
                            break;
595
596 3187
                        case Opcodes::OP_ROT:
597 48
                            if (count($mainStack) < 3) {
598 16
                                throw new \RuntimeException('Invalid stack operation OP_ROT');
599
                            }
600 32
                            $mainStack->swap(-3, -2);
601 32
                            $mainStack->swap(-2, -1);
602 32
                            break;
603
604 3163
                        case Opcodes::OP_SWAP:
605 40
                            if (count($mainStack) < 2) {
606 12
                                throw new \RuntimeException('Invalid stack operation OP_SWAP');
607
                            }
608 28
                            $mainStack->swap(-2, -1);
609 28
                            break;
610
611 3147
                        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(- 2, $vch);
617 12
                            break;
618
619 3131
                        case Opcodes::OP_PICK:
620 3113
                        case Opcodes::OP_ROLL:
621 116
                            if (count($mainStack) < 2) {
622 16
                                throw new \RuntimeException('Invalid stack operation OP_PICK');
623
                            }
624
625 100
                            $n = Number::buffer($mainStack[-1], $minimal, 4)->getGmp();
626 92
                            $mainStack->pop();
627 92
                            if ($this->math->cmp($n, gmp_init(0)) < 0 || $this->math->cmp($n, gmp_init(count($mainStack))) >= 0) {
628 20
                                throw new \RuntimeException('Invalid stack operation OP_PICK');
629
                            }
630
631 72
                            $pos = (int) gmp_strval($this->math->sub($this->math->sub(gmp_init(0), $n), gmp_init(1)), 10);
632 72
                            $vch = $mainStack[$pos];
633 72
                            if ($opCode === Opcodes::OP_ROLL) {
634 36
                                unset($mainStack[$pos]);
635 18
                            }
636 72
                            $mainStack->push($vch);
637 72
                            break;
638
639 3063
                        case Opcodes::OP_2DROP:
640 36
                            if (count($mainStack) < 2) {
641 4
                                throw new \RuntimeException('Invalid stack operation OP_2DROP');
642
                            }
643 32
                            $mainStack->pop();
644 32
                            $mainStack->pop();
645 32
                            break;
646
647 3055
                        case Opcodes::OP_2DUP:
648 24
                            if (count($mainStack) < 2) {
649 12
                                throw new \RuntimeException('Invalid stack operation OP_2DUP');
650
                            }
651 12
                            $string1 = $mainStack[-2];
652 12
                            $string2 = $mainStack[-1];
653 12
                            $mainStack->push($string1);
654 12
                            $mainStack->push($string2);
655 12
                            break;
656
657 3039
                        case Opcodes::OP_3DUP:
658 44
                            if (count($mainStack) < 3) {
659 16
                                throw new \RuntimeException('Invalid stack operation OP_3DUP');
660
                            }
661 28
                            $string1 = $mainStack[-3];
662 28
                            $string2 = $mainStack[-2];
663 28
                            $string3 = $mainStack[-1];
664 28
                            $mainStack->push($string1);
665 28
                            $mainStack->push($string2);
666 28
                            $mainStack->push($string3);
667 28
                            break;
668
669 2999
                        case Opcodes::OP_2OVER:
670 20
                            if (count($mainStack) < 4) {
671 12
                                throw new \RuntimeException('Invalid stack operation OP_2OVER');
672
                            }
673 8
                            $string1 = $mainStack[-4];
674 8
                            $string2 = $mainStack[-3];
675 8
                            $mainStack->push($string1);
676 8
                            $mainStack->push($string2);
677 8
                            break;
678
679 2983
                        case Opcodes::OP_2ROT:
680 40
                            if (count($mainStack) < 6) {
681 4
                                throw new \RuntimeException('Invalid stack operation OP_2ROT');
682
                            }
683 36
                            $string1 = $mainStack[-6];
684 36
                            $string2 = $mainStack[-5];
685 36
                            unset($mainStack[-6], $mainStack[-5]);
686 36
                            $mainStack->push($string1);
687 36
                            $mainStack->push($string2);
688 36
                            break;
689
690 2975
                        case Opcodes::OP_2SWAP:
691 20
                            if (count($mainStack) < 4) {
692 12
                                throw new \RuntimeException('Invalid stack operation OP_2SWAP');
693
                            }
694 8
                            $mainStack->swap(-3, -1);
695 8
                            $mainStack->swap(-4, -2);
696 8
                            break;
697
698 2959
                        case Opcodes::OP_SIZE:
699 124
                            if ($mainStack->isEmpty()) {
700 8
                                throw new \RuntimeException('Invalid stack operation OP_SIZE');
701
                            }
702 116
                            $size = Number::int($mainStack[-1]->getSize());
703 116
                            $mainStack->push($size->getBuffer());
704 116
                            break;
705
706 2947
                        case Opcodes::OP_EQUAL:
707 2725
                        case Opcodes::OP_EQUALVERIFY:
708 1154
                            if (count($mainStack) < 2) {
709 16
                                throw new \RuntimeException('Invalid stack operation OP_EQUAL');
710
                            }
711
712 1138
                            $equal = $mainStack[-2]->equals($mainStack[-1]);
713 1138
                            $mainStack->pop();
714 1138
                            $mainStack->pop();
715 1138
                            $mainStack->push($equal ? $this->vchTrue : $this->vchFalse);
716 1138
                            if ($opCode === Opcodes::OP_EQUALVERIFY) {
717 198
                                if ($equal) {
718 162
                                    $mainStack->pop();
719 78
                                } else {
720 36
                                    throw new \RuntimeException('Error EQUALVERIFY');
721
                                }
722 78
                            }
723
724 1106
                            break;
725
726
                        // Arithmetic operations
727 2379
                        case $opCode >= Opcodes::OP_1ADD && $opCode <= Opcodes::OP_0NOTEQUAL:
728 420
                            if ($mainStack->isEmpty()) {
729 24
                                throw new \Exception('Invalid stack operation 1ADD-OP_0NOTEQUAL');
730
                            }
731
732 396
                            $num = Number::buffer($mainStack[-1], $minimal)->getGmp();
733
734 304
                            if ($opCode === Opcodes::OP_1ADD) {
735 28
                                $num = $this->math->add($num, gmp_init(1));
736 290
                            } elseif ($opCode === Opcodes::OP_1SUB) {
737 12
                                $num = $this->math->sub($num, gmp_init(1));
738 270
                            } elseif ($opCode === Opcodes::OP_2MUL) {
739
                                $num = $this->math->mul(gmp_init(2), $num);
740 264
                            } elseif ($opCode === Opcodes::OP_NEGATE) {
741 16
                                $num = $this->math->sub(gmp_init(0), $num);
742 258
                            } elseif ($opCode === Opcodes::OP_ABS) {
743 20
                                if ($this->math->cmp($num, gmp_init(0)) < 0) {
744 14
                                    $num = $this->math->sub(gmp_init(0), $num);
745 4
                                }
746 242
                            } elseif ($opCode === Opcodes::OP_NOT) {
747 208
                                $num = gmp_init($this->math->cmp($num, gmp_init(0)) == 0 ? 1 : 0);
748 102
                            } else {
749
                                // is OP_0NOTEQUAL
750 24
                                $num = gmp_init($this->math->cmp($num, gmp_init(0)) != 0 ? 1 : 0);
751
                            }
752
753 304
                            $mainStack->pop();
754
755 304
                            $buffer = Number::int(gmp_strval($num, 10))->getBuffer();
756
757 304
                            $mainStack->push($buffer);
758 304
                            break;
759
760 2143
                        case $opCode >= Opcodes::OP_ADD && $opCode <= Opcodes::OP_MAX:
761 656
                            if (count($mainStack) < 2) {
762 52
                                throw new \Exception('Invalid stack operation (OP_ADD - OP_MAX)');
763
                            }
764
765 604
                            $num1 = Number::buffer($mainStack[-2], $minimal)->getGmp();
766 536
                            $num2 = Number::buffer($mainStack[-1], $minimal)->getGmp();
767
768 484
                            if ($opCode === Opcodes::OP_ADD) {
769 120
                                $num = $this->math->add($num1, $num2);
770 436
                            } else if ($opCode === Opcodes::OP_SUB) {
771 24
                                $num = $this->math->sub($num1, $num2);
772 376
                            } else if ($opCode === Opcodes::OP_BOOLAND) {
773 32
                                $num = $this->math->cmp($num1, gmp_init(0)) !== 0 && $this->math->cmp($num2, gmp_init(0)) !== 0;
774 348
                            } else if ($opCode === Opcodes::OP_BOOLOR) {
775 32
                                $num = $this->math->cmp($num1, gmp_init(0)) !== 0 || $this->math->cmp($num2, gmp_init(0)) !== 0;
776 316
                            } elseif ($opCode === Opcodes::OP_NUMEQUAL) {
777 112
                                $num = $this->math->cmp($num1, $num2) === 0;
778 260
                            } elseif ($opCode === Opcodes::OP_NUMEQUALVERIFY) {
779 16
                                $num = $this->math->cmp($num1, $num2) === 0;
780 212
                            } elseif ($opCode === Opcodes::OP_NUMNOTEQUAL) {
781 20
                                $num = $this->math->cmp($num1, $num2) !== 0;
782 194
                            } elseif ($opCode === Opcodes::OP_LESSTHAN) {
783 32
                                $num = $this->math->cmp($num1, $num2) < 0;
784 168
                            } elseif ($opCode === Opcodes::OP_GREATERTHAN) {
785 32
                                $num = $this->math->cmp($num1, $num2) > 0;
786 136
                            } elseif ($opCode === Opcodes::OP_LESSTHANOREQUAL) {
787 32
                                $num = $this->math->cmp($num1, $num2) <= 0;
788 104
                            } elseif ($opCode === Opcodes::OP_GREATERTHANOREQUAL) {
789 32
                                $num = $this->math->cmp($num1, $num2) >= 0;
790 72
                            } elseif ($opCode === Opcodes::OP_MIN) {
791 28
                                $num = ($this->math->cmp($num1, $num2) <= 0) ? $num1 : $num2;
792 14
                            } else {
793 28
                                $num = ($this->math->cmp($num1, $num2) >= 0) ? $num1 : $num2;
794
                            }
795
796 484
                            $mainStack->pop();
797 484
                            $mainStack->pop();
798 484
                            $buffer = Number::int(gmp_strval($num, 10))->getBuffer();
799 484
                            $mainStack->push($buffer);
800
801 484
                            if ($opCode === Opcodes::OP_NUMEQUALVERIFY) {
802 16
                                if ($this->castToBool($mainStack[-1])) {
803 16
                                    $mainStack->pop();
804 8
                                } else {
805
                                    throw new \RuntimeException('NUM EQUAL VERIFY error');
806
                                }
807 8
                            }
808 484
                            break;
809
810 1487
                        case Opcodes::OP_WITHIN:
811 60
                            if (count($mainStack) < 3) {
812 4
                                throw new \RuntimeException('Invalid stack operation');
813
                            }
814
815 56
                            $num1 = Number::buffer($mainStack[-3], $minimal)->getGmp();
816 52
                            $num2 = Number::buffer($mainStack[-2], $minimal)->getGmp();
817 48
                            $num3 = Number::buffer($mainStack[-1], $minimal)->getGmp();
818
819 44
                            $value = $this->math->cmp($num2, $num1) <= 0 && $this->math->cmp($num1, $num3) < 0;
820 44
                            $mainStack->pop();
821 44
                            $mainStack->pop();
822 44
                            $mainStack->pop();
823 44
                            $mainStack->push($value ? $this->vchTrue : $this->vchFalse);
824 44
                            break;
825
826
                        // Hash operation
827 1427
                        case Opcodes::OP_RIPEMD160:
828 1415
                        case Opcodes::OP_SHA1:
829 1399
                        case Opcodes::OP_SHA256:
830 1387
                        case Opcodes::OP_HASH160:
831 1337
                        case Opcodes::OP_HASH256:
832 316
                            if ($mainStack->isEmpty()) {
833 46
                                throw new \RuntimeException('Invalid stack operation');
834
                            }
835
836 270
                            $buffer = $mainStack[-1];
837 270
                            if ($opCode === Opcodes::OP_RIPEMD160) {
838 20
                                $hash = Hash::ripemd160($buffer);
839 262
                            } elseif ($opCode === Opcodes::OP_SHA1) {
840 24
                                $hash = Hash::sha1($buffer);
841 242
                            } elseif ($opCode === Opcodes::OP_SHA256) {
842 24
                                $hash = Hash::sha256($buffer);
843 222
                            } elseif ($opCode === Opcodes::OP_HASH160) {
844 194
                                $hash = Hash::sha256ripe160($buffer);
845 90
                            } else {
846 20
                                $hash = Hash::sha256d($buffer);
847
                            }
848
849 270
                            $mainStack->pop();
850 270
                            $mainStack->push($hash);
851 270
                            break;
852
853 1223
                        case Opcodes::OP_CODESEPARATOR:
854 4
                            $hashStartPos = $parser->getPosition();
855 4
                            break;
856
857 1219
                        case Opcodes::OP_CHECKSIG:
858 999
                        case Opcodes::OP_CHECKSIGVERIFY:
859 391
                            if (count($mainStack) < 2) {
860 8
                                throw new \RuntimeException('Invalid stack operation');
861
                            }
862
863 383
                            $vchPubKey = $mainStack[-1];
864 383
                            $vchSig = $mainStack[-2];
865
866 383
                            $scriptCode = new Script($script->getBuffer()->slice($hashStartPos));
867
868 383
                            $success = $checker->checkSig($scriptCode, $vchSig, $vchPubKey, $sigVersion, $flags);
869
870 251
                            $mainStack->pop();
871 251
                            $mainStack->pop();
872 251
                            $mainStack->push($success ? $this->vchTrue : $this->vchFalse);
873
874 251
                            if ($opCode === Opcodes::OP_CHECKSIGVERIFY) {
875
                                if ($success) {
876
                                    $mainStack->pop();
877
                                } else {
878
                                    throw new \RuntimeException('Checksig verify');
879
                                }
880
                            }
881 251
                            break;
882
883 828
                        case Opcodes::OP_CHECKMULTISIG:
884 660
                        case Opcodes::OP_CHECKMULTISIGVERIFY:
885 446
                            $i = 1;
886 446
                            if (count($mainStack) < $i) {
887 4
                                throw new \RuntimeException('Invalid stack operation');
888
                            }
889
890 442
                            $keyCount = Number::buffer($mainStack[-$i], $minimal)->getInt();
891 434
                            if ($keyCount < 0 || $keyCount > 20) {
892 8
                                throw new \RuntimeException('OP_CHECKMULTISIG: Public key count exceeds 20');
893
                            }
894
895 426
                            $opCount += $keyCount;
896 426
                            $this->checkOpcodeCount($opCount);
897
898
                            // Extract positions of the keys, and signatures, from the stack.
899 426
                            $ikey = ++$i;
900 426
                            $i += $keyCount; /** @var int $i */
901 426
                            if (count($mainStack) < $i) {
902 4
                                throw new \RuntimeException('Invalid stack operation');
903
                            }
904
905 422
                            $sigCount = Number::buffer($mainStack[-$i], $minimal)->getInt();
906 410
                            if ($sigCount < 0 || $sigCount > $keyCount) {
907 8
                                throw new \RuntimeException('Invalid Signature count');
908
                            }
909
910 402
                            $isig = ++$i;
911 402
                            $i += $sigCount;
912
913
                            // Extract the script since the last OP_CODESEPARATOR
914 402
                            $scriptCode = new Script($script->getBuffer()->slice($hashStartPos));
915
916 402
                            $fSuccess = true;
917 402
                            while ($fSuccess && $sigCount > 0) {
918
                                // Fetch the signature and public key
919 162
                                $sig = $mainStack[-$isig];
920 158
                                $pubkey = $mainStack[-$ikey];
921
922 158
                                if ($checker->checkSig($scriptCode, $sig, $pubkey, $sigVersion, $flags)) {
923 78
                                    $isig++;
924 78
                                    $sigCount--;
925 34
                                }
926
927 130
                                $ikey++;
928 130
                                $keyCount--;
929
930
                                // If there are more signatures left than keys left,
931
                                // then too many signatures have failed. Exit early,
932
                                // without checking any further signatures.
933 130
                                if ($sigCount > $keyCount) {
934 60
                                    $fSuccess = false;
935 28
                                }
936 58
                            }
937
938 358
                            while ($i-- > 1) {
939 358
                                $mainStack->pop();
940 174
                            }
941
942
                            // A bug causes CHECKMULTISIG to consume one extra argument
943
                            // whose contents were not checked in any way.
944
                            //
945
                            // Unfortunately this is a potential source of mutability,
946
                            // so optionally verify it is exactly equal to zero prior
947
                            // to removing it from the stack.
948 358
                            if ($mainStack->isEmpty()) {
949 4
                                throw new \RuntimeException('Invalid stack operation');
950
                            }
951
952 358
                            if ($flags & self::VERIFY_NULL_DUMMY && $mainStack[-1]->getSize() !== 0) {
953 8
                                throw new ScriptRuntimeException(self::VERIFY_NULL_DUMMY, 'Extra P2SH stack value should be OP_0');
954
                            }
955
956 350
                            $mainStack->pop();
957 350
                            $mainStack->push($fSuccess ? $this->vchTrue : $this->vchFalse);
958
959 350
                            if ($opCode === Opcodes::OP_CHECKMULTISIGVERIFY) {
960 120
                                if ($fSuccess) {
961 120
                                    $mainStack->pop();
962 60
                                } else {
963
                                    throw new \RuntimeException('OP_CHECKMULTISIG verify');
964
                                }
965 60
                            }
966 350
                            break;
967
968 188
                        default:
969 382
                            throw new \RuntimeException('Opcode not found');
970 188
                    }
971
972 3849
                    if (count($mainStack) + count($altStack) > 1000) {
973 2198
                        throw new \RuntimeException('Invalid stack size, exceeds 1000');
974
                    }
975 1905
                }
976 2135
            }
977
978 4267
            if (count($vfStack) !== 0) {
979 24
                throw new \RuntimeException('Unbalanced conditional at script end');
980
            }
981
982 4247
            return true;
983 1630
        } catch (ScriptRuntimeException $e) {
984
            // echo "\n Runtime: " . $e->getMessage() . "\n" . $e->getTraceAsString() . PHP_EOL;
985
            // Failure due to script tags, can access flag: $e->getFailureFlag()
986 324
            return false;
987 1306
        } catch (\Exception $e) {
988
            // echo "\n General: " . $e->getMessage()  . PHP_EOL . $e->getTraceAsString() . PHP_EOL;
989 1306
            return false;
990
        }
991
    }
992
}
993