Completed
Pull Request — master (#403)
by thomas
23:44
created

Interpreter::isValidSignatureEncoding()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
170 16
                    return false;
171
                }
172 23
            } elseif ($buffer->getSize() === 20) {
173
                // Version 0 special case for pay-to-pubkeyhash
174 15
                if ($witnessCount !== 2) {
175
                    // 2 items in witness - <signature> <pubkey>
176 12
                    return false;
177
                }
178
179 14
                $scriptPubKey = ScriptFactory::scriptPubKey()->payToPubKeyHash($buffer);
180 14
                $stackValues = $scriptWitness;
181 4
            } else {
182 25
                return false;
183
            }
184 12
        } elseif ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM) {
185 1
            return false;
186
        } else {
187
            return false;
188
        }
189
190 35
        $mainStack = new Stack();
191 35
        foreach ($stackValues as $value) {
192 34
            $mainStack->push($value);
193 11
        }
194
195 35
        if (!$this->evaluate($scriptPubKey, $mainStack, SigHash::V1, $flags, $checker)) {
196 14
            return false;
197
        }
198
199 35
        if ($mainStack->count() !== 1) {
200
            return false;
201
        }
202
203 35
        if (!$this->castToBool($mainStack->bottom())) {
204 9
            return false;
205
        }
206
207 26
        return true;
208
    }
209
210
    /**
211
     * @param ScriptInterface $scriptSig
212
     * @param ScriptInterface $scriptPubKey
213
     * @param int $flags
214
     * @param Checker $checker
215
     * @param ScriptWitnessInterface|null $witness
216
     * @return bool
217
     */
218 1390
    public function verify(ScriptInterface $scriptSig, ScriptInterface $scriptPubKey, $flags, Checker $checker, ScriptWitnessInterface $witness = null)
219
    {
220 1390
        static $emptyWitness = null;
221 1390
        if ($emptyWitness === null) {
222 6
            $emptyWitness = new ScriptWitness([]);
223 3
        }
224
225 1390
        $witness = is_null($witness) ? $emptyWitness : $witness;
226
227 1390
        if (($flags & self::VERIFY_SIGPUSHONLY) !== 0 && !$scriptSig->isPushOnly()) {
228 2
            return false;
229
        }
230
231 1388
        $stack = new Stack();
232 1388
        if (!$this->evaluate($scriptSig, $stack, SigHash::V0, $flags, $checker)) {
233 61
            return false;
234
        }
235
236 1327
        $backup = [];
237 1327
        if ($flags & self::VERIFY_P2SH) {
238 844
            foreach ($stack as $s) {
239 687
                $backup[] = $s;
240 43
            }
241 43
        }
242
243 1327
        if (!$this->evaluate($scriptPubKey, $stack, SigHash::V0, $flags, $checker)) {
244 477
            return false;
245
        }
246
247 874
        if ($stack->isEmpty()) {
248 16
            return false;
249
        }
250
251 858
        if (false === $this->castToBool($stack[-1])) {
252 68
            return false;
253
        }
254
255 790
        $program = null;
256 790
        if ($flags & self::VERIFY_WITNESS) {
257 62
            if ($scriptPubKey->isWitness($program)) {
258
                /** @var WitnessProgram $program */
259 24
                if ($scriptSig->getBuffer()->getSize() !== 0) {
260 1
                    return false;
261
                }
262
263 23
                if (!$this->verifyWitnessProgram($program, $witness, $flags, $checker)) {
264 21
                    return false;
265
                }
266
267 12
                $stack->resize(1);
268 5
            }
269 20
        }
270
271 778
        if ($flags & self::VERIFY_P2SH && (new OutputClassifier())->isPayToScriptHash($scriptPubKey)) {
272 61
            if (!$scriptSig->isPushOnly()) {
273 9
                return false;
274
            }
275
276 52
            $stack = new Stack();
277 52
            foreach ($backup as $i) {
278 52
                $stack->push($i);
279 15
            }
280
281
            // Restore mainStack to how it was after evaluating scriptSig
282 52
            if ($stack->isEmpty()) {
283
                return false;
284
            }
285
286
            // Load redeemscript as the scriptPubKey
287 52
            $scriptPubKey = new Script($stack->bottom());
288 52
            $stack->pop();
289
290 52
            if (!$this->evaluate($scriptPubKey, $stack, 0, $flags, $checker)) {
291 16
                return false;
292
            }
293
294 42
            if ($stack->isEmpty()) {
295
                return false;
296
            }
297
298 42
            if (!$this->castToBool($stack->bottom())) {
299 1
                return false;
300
            }
301
302 41
            if ($flags & self::VERIFY_WITNESS) {
303 25
                if ($scriptPubKey->isWitness($program)) {
304
                    /** @var WitnessProgram $program */
305 19
                    if (!$scriptSig->equals(ScriptFactory::sequence([$scriptPubKey->getBuffer()]))) {
306 1
                        return false; // SCRIPT_ERR_WITNESS_MALLEATED_P2SH
307
                    }
308
309 18
                    if (!$this->verifyWitnessProgram($program, $witness, $flags, $checker)) {
310 16
                        return false;
311
                    }
312
313 14
                    $stack->resize(1);
314 6
                }
315 9
            }
316 12
        }
317
318 753
        if ($flags & self::VERIFY_CLEAN_STACK) {
319 21
            if (!($flags & self::VERIFY_P2SH !== 0) && ($flags & self::VERIFY_WITNESS !== 0)) {
320
                return false; // implied flags required
321
            }
322
323 21
            if (count($stack) !== 1) {
324 2
                return false; // Cleanstack
325
            }
326 9
        }
327
328 751
        if ($flags & self::VERIFY_WITNESS) {
329 45
            if (!$flags & self::VERIFY_P2SH) {
330
                return false; //
331
            }
332
333 45
            if ($program === null && !$witness->isNull()) {
334 1
                return false; // SCRIPT_ERR_WITNESS_UNEXPECTED
335
            }
336 20
        }
337
338 750
        return true;
339
    }
340
341
    /**
342
     * @param Stack $vfStack
343
     * @param bool $value
344
     * @return bool
345
     */
346 1462
    private function checkExec(Stack $vfStack, $value)
347
    {
348 1462
        $ret = 0;
349 1462
        foreach ($vfStack as $item) {
350 242
            if ($item === $value) {
351 242
                $ret++;
352
            }
353 205
        }
354
355 1462
        return $ret;
356
    }
357
358
    /**
359
     * @param ScriptInterface $script
360
     * @param Stack $mainStack
361
     * @param int $sigVersion
362
     * @param int $flags
363
     * @param Checker $checker
364
     * @return bool
365
     */
366 1472
    public function evaluate(ScriptInterface $script, Stack $mainStack, $sigVersion, $flags, Checker $checker)
367
    {
368 1472
        $hashStartPos = 0;
369 1472
        $opCount = 0;
370 1472
        $zero = gmp_init(0, 10);
371 1472
        $altStack = new Stack();
372 1472
        $vfStack = new Stack();
373 1472
        $minimal = ($flags & self::VERIFY_MINIMALDATA) !== 0;
374 1472
        $parser = $script->getScriptParser();
375
376 1472
        if ($script->getBuffer()->getSize() > 10000) {
377 1
            return false;
378
        }
379
380
        try {
381 1472
            foreach ($parser as $operation) {
382 1462
                $opCode = $operation->getOp();
383 1462
                $pushData = $operation->getData();
384 1462
                $fExec = !$this->checkExec($vfStack, false);
385
386
                // If pushdata was written to
387 1462
                if ($operation->isPush() && $operation->getDataSize() > InterpreterInterface::MAX_SCRIPT_ELEMENT_SIZE) {
388 8
                    throw new \RuntimeException('Error - push size');
389
                }
390
391
                // OP_RESERVED should not count towards opCount
392 1456
                if ($opCode > Opcodes::OP_16 && ++$opCount) {
393 1382
                    $this->checkOpcodeCount($opCount);
394 194
                }
395
396 1456
                if (in_array($opCode, $this->disabledOps, true)) {
397 24
                    throw new \RuntimeException('Disabled Opcode');
398
                }
399
400 1456
                if ($fExec && $operation->isPush()) {
401
                    // In range of a pushdata opcode
402 1150
                    if ($minimal && !$this->checkMinimalPush($opCode, $pushData)) {
403 21
                        throw new ScriptRuntimeException(self::VERIFY_MINIMALDATA, 'Minimal pushdata required');
404
                    }
405
406 1129
                    $mainStack->push($pushData);
407
                    // echo " - [pushed '" . $pushData->getHex() . "']\n";
408 1413
                } elseif ($fExec || (Opcodes::OP_IF <= $opCode && $opCode <= Opcodes::OP_ENDIF)) {
409
                    // echo "OPCODE - " . $script->getOpcodes()->getOp($opCode) . "\n";
410
                    switch ($opCode) {
411 1405
                        case Opcodes::OP_1NEGATE:
412 1405
                        case Opcodes::OP_1:
413 1383
                        case Opcodes::OP_2:
414 1379
                        case Opcodes::OP_3:
415 1379
                        case Opcodes::OP_4:
416 1379
                        case Opcodes::OP_5:
417 1379
                        case Opcodes::OP_6:
418 1379
                        case Opcodes::OP_7:
419 1378
                        case Opcodes::OP_8:
420 1378
                        case Opcodes::OP_9:
421 1378
                        case Opcodes::OP_10:
422 1378
                        case Opcodes::OP_11:
423 1377
                        case Opcodes::OP_12:
424 1377
                        case Opcodes::OP_13:
425 1377
                        case Opcodes::OP_14:
426 1377
                        case Opcodes::OP_15:
427 1377
                        case Opcodes::OP_16:
428 712
                            $num = \BitWasp\Bitcoin\Script\decodeOpN($opCode);
429 712
                            $mainStack->push(Number::int($num)->getBuffer());
430 712
                            break;
431
432 1377
                        case Opcodes::OP_CHECKLOCKTIMEVERIFY:
433 6
                            if (!($flags & self::VERIFY_CHECKLOCKTIMEVERIFY)) {
434 6
                                if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
435 1
                                    throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
436
                                }
437 5
                                break;
438
                            }
439
440
                            if ($mainStack->isEmpty()) {
441
                                throw new \RuntimeException('Invalid stack operation - CLTV');
442
                            }
443
444
                            $lockTime = Number::buffer($mainStack[-1], $minimal, 5, $this->math);
445
                            if (!$checker->checkLockTime($lockTime)) {
446
                                throw new ScriptRuntimeException(self::VERIFY_CHECKLOCKTIMEVERIFY, 'Unsatisfied locktime');
447
                            }
448
449
                            break;
450
451 1376
                        case Opcodes::OP_CHECKSEQUENCEVERIFY:
452 12
                            if (!($flags & self::VERIFY_CHECKSEQUENCEVERIFY)) {
453 6
                                if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
454 1
                                    throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
455
                                }
456 5
                                break;
457
                            }
458
459 6
                            if ($mainStack->isEmpty()) {
460 1
                                throw new \RuntimeException('Invalid stack operation - CSV');
461
                            }
462
463 5
                            $sequence = Number::buffer($mainStack[-1], $minimal, 5, $this->math);
464 4
                            $nSequence = $sequence->getGmp();
465 4
                            if ($this->math->cmp($nSequence, $zero) < 0) {
466 1
                                throw new ScriptRuntimeException(self::VERIFY_CHECKSEQUENCEVERIFY, 'Negative locktime');
467
                            }
468
469 3
                            if ($this->math->cmp($this->math->bitwiseAnd($nSequence, gmp_init(TransactionInputInterface::SEQUENCE_LOCKTIME_DISABLE_FLAG, 10)), $zero) !== 0) {
470 1
                                break;
471
                            }
472
473 2
                            if (!$checker->checkSequence($sequence)) {
474 2
                                throw new ScriptRuntimeException(self::VERIFY_CHECKSEQUENCEVERIFY, 'Unsatisfied sequence');
475
                            }
476
                            break;
477
478 1369
                        case Opcodes::OP_NOP1:
479 1368
                        case Opcodes::OP_NOP4:
480 1367
                        case Opcodes::OP_NOP5:
481 1366
                        case Opcodes::OP_NOP6:
482 1365
                        case Opcodes::OP_NOP7:
483 1364
                        case Opcodes::OP_NOP8:
484 1363
                        case Opcodes::OP_NOP9:
485 1362
                        case Opcodes::OP_NOP10:
486 27
                            if ($flags & self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
487 10
                                throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
488
                            }
489 17
                            break;
490
491 1359
                        case Opcodes::OP_NOP:
492 84
                            break;
493
494 1336
                        case Opcodes::OP_IF:
495 1314
                        case Opcodes::OP_NOTIF:
496
                            // <expression> if [statements] [else [statements]] endif
497 247
                            $value = false;
498 247
                            if ($fExec) {
499 247
                                if ($mainStack->isEmpty()) {
500 2
                                    throw new \RuntimeException('Unbalanced conditional');
501
                                }
502
503 245
                                $buffer = Number::buffer($mainStack->pop(), $minimal)->getBuffer();
0 ignored issues
show
Bug introduced by
It seems like $mainStack->pop() can be null; however, buffer() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
504 245
                                $value = $this->castToBool($buffer);
505 245
                                if ($opCode === Opcodes::OP_NOTIF) {
506 17
                                    $value = !$value;
507
                                }
508
                            }
509 245
                            $vfStack->push($value);
510 245
                            break;
511
512 1312
                        case Opcodes::OP_ELSE:
513 115
                            if ($vfStack->isEmpty()) {
514 4
                                throw new \RuntimeException('Unbalanced conditional');
515
                            }
516 113
                            $vfStack->push(!$vfStack->pop());
517 113
                            break;
518
519 1309
                        case Opcodes::OP_ENDIF:
520 147
                            if ($vfStack->isEmpty()) {
521 7
                                throw new \RuntimeException('Unbalanced conditional');
522
                            }
523 143
                            $vfStack->pop();
524 143
                            break;
525
526 1173
                        case Opcodes::OP_VERIFY:
527 30
                            if ($mainStack->isEmpty()) {
528 1
                                throw new \RuntimeException('Invalid stack operation');
529
                            }
530 29
                            $value = $this->castToBool($mainStack[-1]);
531 29
                            if (!$value) {
532 1
                                throw new \RuntimeException('Error: verify');
533
                            }
534 28
                            $mainStack->pop();
535 28
                            break;
536
537 1166
                        case Opcodes::OP_TOALTSTACK:
538 8
                            if ($mainStack->isEmpty()) {
539 1
                                throw new \RuntimeException('Invalid stack operation OP_TOALTSTACK');
540
                            }
541 7
                            $altStack->push($mainStack->pop());
542 7
                            break;
543
544 1164
                        case Opcodes::OP_FROMALTSTACK:
545 5
                            if ($altStack->isEmpty()) {
546 2
                                throw new \RuntimeException('Invalid alt-stack operation OP_FROMALTSTACK');
547
                            }
548 3
                            $mainStack->push($altStack->pop());
549 3
                            break;
550
551 1161
                        case Opcodes::OP_IFDUP:
552
                            // If top value not zero, duplicate it.
553 6
                            if ($mainStack->isEmpty()) {
554 2
                                throw new \RuntimeException('Invalid stack operation OP_IFDUP');
555
                            }
556 4
                            $vch = $mainStack[-1];
557 4
                            if ($this->castToBool($vch)) {
558 3
                                $mainStack->push($vch);
559
                            }
560 4
                            break;
561
562 1158
                        case Opcodes::OP_DEPTH:
563 81
                            $num = count($mainStack);
564 81
                            $depth = Number::int($num)->getBuffer();
565 81
                            $mainStack->push($depth);
566 81
                            break;
567
568 1149
                        case Opcodes::OP_DROP:
569 48
                            if ($mainStack->isEmpty()) {
570 2
                                throw new \RuntimeException('Invalid stack operation OP_DROP');
571
                            }
572 46
                            $mainStack->pop();
573 46
                            break;
574
575 1146
                        case Opcodes::OP_DUP:
576 136
                            if ($mainStack->isEmpty()) {
577 26
                                throw new \RuntimeException('Invalid stack operation OP_DUP');
578
                            }
579 134
                            $vch = $mainStack[-1];
580 134
                            $mainStack->push($vch);
581 134
                            break;
582
583 1137
                        case Opcodes::OP_NIP:
584 6
                            if (count($mainStack) < 2) {
585 3
                                throw new \RuntimeException('Invalid stack operation OP_NIP');
586
                            }
587 3
                            unset($mainStack[-2]);
588 3
                            break;
589
590 1131
                        case Opcodes::OP_OVER:
591 6
                            if (count($mainStack) < 2) {
592 3
                                throw new \RuntimeException('Invalid stack operation OP_OVER');
593
                            }
594 3
                            $vch = $mainStack[-2];
595 3
                            $mainStack->push($vch);
596 3
                            break;
597
598 1127
                        case Opcodes::OP_ROT:
599 12
                            if (count($mainStack) < 3) {
600 4
                                throw new \RuntimeException('Invalid stack operation OP_ROT');
601
                            }
602 8
                            $mainStack->swap(-3, -2);
603 8
                            $mainStack->swap(-2, -1);
604 8
                            break;
605
606 1121
                        case Opcodes::OP_SWAP:
607 10
                            if (count($mainStack) < 2) {
608 3
                                throw new \RuntimeException('Invalid stack operation OP_SWAP');
609
                            }
610 7
                            $mainStack->swap(-2, -1);
611 7
                            break;
612
613 1117
                        case Opcodes::OP_TUCK:
614 6
                            if (count($mainStack) < 2) {
615 3
                                throw new \RuntimeException('Invalid stack operation OP_TUCK');
616
                            }
617 3
                            $vch = $mainStack[-1];
618 3
                            $mainStack->add(- 2, $vch);
619 3
                            break;
620
621 1113
                        case Opcodes::OP_PICK:
622 1104
                        case Opcodes::OP_ROLL:
623 29
                            if (count($mainStack) < 2) {
624 4
                                throw new \RuntimeException('Invalid stack operation OP_PICK');
625
                            }
626
627 25
                            $n = Number::buffer($mainStack[-1], $minimal, 4)->getGmp();
628 23
                            $mainStack->pop();
629 23
                            if ($this->math->cmp($n, $zero) < 0 || $this->math->cmp($n, gmp_init(count($mainStack))) >= 0) {
630 5
                                throw new \RuntimeException('Invalid stack operation OP_PICK');
631
                            }
632
633 18
                            $pos = (int) gmp_strval($this->math->sub($this->math->sub($zero, $n), gmp_init(1)), 10);
634 18
                            $vch = $mainStack[$pos];
635 18
                            if ($opCode === Opcodes::OP_ROLL) {
636 9
                                unset($mainStack[$pos]);
637
                            }
638 18
                            $mainStack->push($vch);
639 18
                            break;
640
641 1096
                        case Opcodes::OP_2DROP:
642 9
                            if (count($mainStack) < 2) {
643 1
                                throw new \RuntimeException('Invalid stack operation OP_2DROP');
644
                            }
645 8
                            $mainStack->pop();
646 8
                            $mainStack->pop();
647 8
                            break;
648
649 1094
                        case Opcodes::OP_2DUP:
650 6
                            if (count($mainStack) < 2) {
651 3
                                throw new \RuntimeException('Invalid stack operation OP_2DUP');
652
                            }
653 3
                            $string1 = $mainStack[-2];
654 3
                            $string2 = $mainStack[-1];
655 3
                            $mainStack->push($string1);
656 3
                            $mainStack->push($string2);
657 3
                            break;
658
659 1090
                        case Opcodes::OP_3DUP:
660 11
                            if (count($mainStack) < 3) {
661 4
                                throw new \RuntimeException('Invalid stack operation OP_3DUP');
662
                            }
663 7
                            $string1 = $mainStack[-3];
664 7
                            $string2 = $mainStack[-2];
665 7
                            $string3 = $mainStack[-1];
666 7
                            $mainStack->push($string1);
667 7
                            $mainStack->push($string2);
668 7
                            $mainStack->push($string3);
669 7
                            break;
670
671 1080
                        case Opcodes::OP_2OVER:
672 5
                            if (count($mainStack) < 4) {
673 3
                                throw new \RuntimeException('Invalid stack operation OP_2OVER');
674
                            }
675 2
                            $string1 = $mainStack[-4];
676 2
                            $string2 = $mainStack[-3];
677 2
                            $mainStack->push($string1);
678 2
                            $mainStack->push($string2);
679 2
                            break;
680
681 1076
                        case Opcodes::OP_2ROT:
682 10
                            if (count($mainStack) < 6) {
683 1
                                throw new \RuntimeException('Invalid stack operation OP_2ROT');
684
                            }
685 9
                            $string1 = $mainStack[-6];
686 9
                            $string2 = $mainStack[-5];
687 9
                            unset($mainStack[-6], $mainStack[-5]);
688 9
                            $mainStack->push($string1);
689 9
                            $mainStack->push($string2);
690 9
                            break;
691
692 1074
                        case Opcodes::OP_2SWAP:
693 5
                            if (count($mainStack) < 4) {
694 3
                                throw new \RuntimeException('Invalid stack operation OP_2SWAP');
695
                            }
696 2
                            $mainStack->swap(-3, -1);
697 2
                            $mainStack->swap(-4, -2);
698 2
                            break;
699
700 1070
                        case Opcodes::OP_SIZE:
701 31
                            if ($mainStack->isEmpty()) {
702 2
                                throw new \RuntimeException('Invalid stack operation OP_SIZE');
703
                            }
704 29
                            $size = Number::int($mainStack[-1]->getSize());
705 29
                            $mainStack->push($size->getBuffer());
706 29
                            break;
707
708 1067
                        case Opcodes::OP_EQUAL:
709 956
                        case Opcodes::OP_EQUALVERIFY:
710 464
                            if (count($mainStack) < 2) {
711 4
                                throw new \RuntimeException('Invalid stack operation OP_EQUAL');
712
                            }
713
714 460
                            $equal = $mainStack[-2]->equals($mainStack[-1]);
715 460
                            $mainStack->pop();
716 460
                            $mainStack->pop();
717 460
                            $mainStack->push($equal ? $this->vchTrue : $this->vchFalse);
718 460
                            if ($opCode === Opcodes::OP_EQUALVERIFY) {
719 153
                                if ($equal) {
720 138
                                    $mainStack->pop();
721 51
                                } else {
722 15
                                    throw new \RuntimeException('Error EQUALVERIFY');
723
                                }
724 51
                            }
725
726 446
                            break;
727
728
                        // Arithmetic operations
729 925
                        case $opCode >= Opcodes::OP_1ADD && $opCode <= Opcodes::OP_0NOTEQUAL:
730 114
                            if ($mainStack->isEmpty()) {
731 6
                                throw new \Exception('Invalid stack operation 1ADD-OP_0NOTEQUAL');
732
                            }
733
734 108
                            $num = Number::buffer($mainStack[-1], $minimal)->getGmp();
735
736 85
                            if ($opCode === Opcodes::OP_1ADD) {
737 7
                                $num = $this->math->add($num, gmp_init(1));
738 78
                            } elseif ($opCode === Opcodes::OP_1SUB) {
739 3
                                $num = $this->math->sub($num, gmp_init(1));
740 75
                            } elseif ($opCode === Opcodes::OP_2MUL) {
741
                                $num = $this->math->mul(gmp_init(2), $num);
742 75
                            } elseif ($opCode === Opcodes::OP_NEGATE) {
743 4
                                $num = $this->math->sub($zero, $num);
744 72
                            } elseif ($opCode === Opcodes::OP_ABS) {
745 5
                                if ($this->math->cmp($num, $zero) < 0) {
746 5
                                    $num = $this->math->sub($zero, $num);
747
                                }
748 67
                            } elseif ($opCode === Opcodes::OP_NOT) {
749 61
                                $num = gmp_init($this->math->cmp($num, $zero) === 0 ? 1 : 0);
750 6
                            } else {
751
                                // is OP_0NOTEQUAL
752 6
                                $num = gmp_init($this->math->cmp($num, $zero) !== 0 ? 1 : 0);
753
                            }
754
755 85
                            $mainStack->pop();
756
757 85
                            $buffer = Number::int(gmp_strval($num, 10))->getBuffer();
758
759 85
                            $mainStack->push($buffer);
760 85
                            break;
761
762 866
                        case $opCode >= Opcodes::OP_ADD && $opCode <= Opcodes::OP_MAX:
763 164
                            if (count($mainStack) < 2) {
764 13
                                throw new \Exception('Invalid stack operation (OP_ADD - OP_MAX)');
765
                            }
766
767 151
                            $num1 = Number::buffer($mainStack[-2], $minimal)->getGmp();
768 134
                            $num2 = Number::buffer($mainStack[-1], $minimal)->getGmp();
769
770 121
                            if ($opCode === Opcodes::OP_ADD) {
771 30
                                $num = $this->math->add($num1, $num2);
772 97
                            } else if ($opCode === Opcodes::OP_SUB) {
773 6
                                $num = $this->math->sub($num1, $num2);
774 91
                            } else if ($opCode === Opcodes::OP_BOOLAND) {
775 8
                                $num = $this->math->cmp($num1, $zero) !== 0 && $this->math->cmp($num2, $zero) !== 0;
776 83
                            } else if ($opCode === Opcodes::OP_BOOLOR) {
777 8
                                $num = $this->math->cmp($num1, $zero) !== 0 || $this->math->cmp($num2, $zero) !== 0;
778 75
                            } elseif ($opCode === Opcodes::OP_NUMEQUAL) {
779 28
                                $num = $this->math->cmp($num1, $num2) === 0;
780 55
                            } elseif ($opCode === Opcodes::OP_NUMEQUALVERIFY) {
781 4
                                $num = $this->math->cmp($num1, $num2) === 0;
782 51
                            } elseif ($opCode === Opcodes::OP_NUMNOTEQUAL) {
783 5
                                $num = $this->math->cmp($num1, $num2) !== 0;
784 46
                            } elseif ($opCode === Opcodes::OP_LESSTHAN) {
785 8
                                $num = $this->math->cmp($num1, $num2) < 0;
786 38
                            } elseif ($opCode === Opcodes::OP_GREATERTHAN) {
787 8
                                $num = $this->math->cmp($num1, $num2) > 0;
788 30
                            } elseif ($opCode === Opcodes::OP_LESSTHANOREQUAL) {
789 8
                                $num = $this->math->cmp($num1, $num2) <= 0;
790 22
                            } elseif ($opCode === Opcodes::OP_GREATERTHANOREQUAL) {
791 8
                                $num = $this->math->cmp($num1, $num2) >= 0;
792 14
                            } elseif ($opCode === Opcodes::OP_MIN) {
793 7
                                $num = ($this->math->cmp($num1, $num2) <= 0) ? $num1 : $num2;
794
                            } else {
795 7
                                $num = ($this->math->cmp($num1, $num2) >= 0) ? $num1 : $num2;
796
                            }
797
798 121
                            $mainStack->pop();
799 121
                            $mainStack->pop();
800 121
                            $buffer = Number::int(gmp_strval($num, 10))->getBuffer();
801 121
                            $mainStack->push($buffer);
802
803 121
                            if ($opCode === Opcodes::OP_NUMEQUALVERIFY) {
804 4
                                if ($this->castToBool($mainStack[-1])) {
805 4
                                    $mainStack->pop();
806
                                } else {
807
                                    throw new \RuntimeException('NUM EQUAL VERIFY error');
808
                                }
809
                            }
810 121
                            break;
811
812 702
                        case Opcodes::OP_WITHIN:
813 15
                            if (count($mainStack) < 3) {
814 1
                                throw new \RuntimeException('Invalid stack operation');
815
                            }
816
817 14
                            $num1 = Number::buffer($mainStack[-3], $minimal)->getGmp();
818 13
                            $num2 = Number::buffer($mainStack[-2], $minimal)->getGmp();
819 12
                            $num3 = Number::buffer($mainStack[-1], $minimal)->getGmp();
820
821 11
                            $value = $this->math->cmp($num2, $num1) <= 0 && $this->math->cmp($num1, $num3) < 0;
822 11
                            $mainStack->pop();
823 11
                            $mainStack->pop();
824 11
                            $mainStack->pop();
825 11
                            $mainStack->push($value ? $this->vchTrue : $this->vchFalse);
826 11
                            break;
827
828
                        // Hash operation
829 687
                        case Opcodes::OP_RIPEMD160:
830 681
                        case Opcodes::OP_SHA1:
831 673
                        case Opcodes::OP_SHA256:
832 667
                        case Opcodes::OP_HASH160:
833 616
                        case Opcodes::OP_HASH256:
834 259
                            if ($mainStack->isEmpty()) {
835 16
                                throw new \RuntimeException('Invalid stack operation');
836
                            }
837
838 243
                            $buffer = $mainStack[-1];
839 243
                            if ($opCode === Opcodes::OP_RIPEMD160) {
840 5
                                $hash = Hash::ripemd160($buffer);
841 239
                            } elseif ($opCode === Opcodes::OP_SHA1) {
842 6
                                $hash = Hash::sha1($buffer);
843 233
                            } elseif ($opCode === Opcodes::OP_SHA256) {
844 6
                                $hash = Hash::sha256($buffer);
845 229
                            } elseif ($opCode === Opcodes::OP_HASH160) {
846 224
                                $hash = Hash::sha256ripe160($buffer);
847 93
                            } else {
848 5
                                $hash = Hash::sha256d($buffer);
849
                            }
850
851 243
                            $mainStack->pop();
852 243
                            $mainStack->push($hash);
853 243
                            break;
854
855 579
                        case Opcodes::OP_CODESEPARATOR:
856 1
                            $hashStartPos = $parser->getPosition();
857 1
                            break;
858
859 578
                        case Opcodes::OP_CHECKSIG:
860 388
                        case Opcodes::OP_CHECKSIGVERIFY:
861 319
                            if (count($mainStack) < 2) {
862 12
                                throw new \RuntimeException('Invalid stack operation');
863
                            }
864
865 317
                            $vchPubKey = $mainStack[-1];
866 317
                            $vchSig = $mainStack[-2];
867
868 317
                            $scriptCode = new Script($script->getBuffer()->slice($hashStartPos));
869
870 317
                            $success = $checker->checkSig($scriptCode, $vchSig, $vchPubKey, $sigVersion, $flags);
871
872 203
                            $mainStack->pop();
873 203
                            $mainStack->pop();
874 203
                            $mainStack->push($success ? $this->vchTrue : $this->vchFalse);
875
876 203
                            if ($opCode === Opcodes::OP_CHECKSIGVERIFY) {
877
                                if ($success) {
878
                                    $mainStack->pop();
879
                                } else {
880
                                    throw new \RuntimeException('Checksig verify');
881
                                }
882
                            }
883 203
                            break;
884
885 259
                        case Opcodes::OP_CHECKMULTISIG:
886 167
                        case Opcodes::OP_CHECKMULTISIGVERIFY:
887 150
                            $i = 1;
888 150
                            if (count($mainStack) < $i) {
889 1
                                throw new \RuntimeException('Invalid stack operation');
890
                            }
891
892 149
                            $keyCount = Number::buffer($mainStack[-$i], $minimal)->getInt();
893 147
                            if ($keyCount < 0 || $keyCount > 20) {
894 2
                                throw new \RuntimeException('OP_CHECKMULTISIG: Public key count exceeds 20');
895
                            }
896
897 145
                            $opCount += $keyCount;
898 145
                            $this->checkOpcodeCount($opCount);
899
900
                            // Extract positions of the keys, and signatures, from the stack.
901 145
                            $ikey = ++$i;
902 145
                            $i += $keyCount;
903 145
                            if (count($mainStack) < $i) {
904 1
                                throw new \RuntimeException('Invalid stack operation');
905
                            }
906
907 144
                            $sigCount = Number::buffer($mainStack[-$i], $minimal)->getInt();
908 141
                            if ($sigCount < 0 || $sigCount > $keyCount) {
909 2
                                throw new \RuntimeException('Invalid Signature count');
910
                            }
911
912 139
                            $isig = ++$i;
913 139
                            $i += $sigCount;
914
915
                            // Extract the script since the last OP_CODESEPARATOR
916 139
                            $scriptCode = new Script($script->getBuffer()->slice($hashStartPos));
917
918 139
                            $fSuccess = true;
919 139
                            while ($fSuccess && $sigCount > 0) {
920
                                // Fetch the signature and public key
921 79
                                $sig = $mainStack[-$isig];
922 78
                                $pubkey = $mainStack[-$ikey];
923
924 78
                                if ($checker->checkSig($scriptCode, $sig, $pubkey, $sigVersion, $flags)) {
925 40
                                    $isig++;
926 40
                                    $sigCount--;
927 14
                                }
928
929 62
                                $ikey++;
930 62
                                $keyCount--;
931
932
                                // If there are more signatures left than keys left,
933
                                // then too many signatures have failed. Exit early,
934
                                // without checking any further signatures.
935 62
                                if ($sigCount > $keyCount) {
936 34
                                    $fSuccess = false;
937 11
                                }
938 20
                            }
939
940 110
                            while ($i-- > 1) {
941 110
                                $mainStack->pop();
942 14
                            }
943
944
                            // A bug causes CHECKMULTISIG to consume one extra argument
945
                            // whose contents were not checked in any way.
946
                            //
947
                            // Unfortunately this is a potential source of mutability,
948
                            // so optionally verify it is exactly equal to zero prior
949
                            // to removing it from the stack.
950 110
                            if ($mainStack->isEmpty()) {
951 9
                                throw new \RuntimeException('Invalid stack operation');
952
                            }
953
954 110
                            if ($flags & self::VERIFY_NULL_DUMMY && $mainStack[-1]->getSize() !== 0) {
955 2
                                throw new ScriptRuntimeException(self::VERIFY_NULL_DUMMY, 'Extra P2SH stack value should be OP_0');
956
                            }
957
958 108
                            $mainStack->pop();
959 108
                            $mainStack->push($fSuccess ? $this->vchTrue : $this->vchFalse);
960
961 108
                            if ($opCode === Opcodes::OP_CHECKMULTISIGVERIFY) {
962 30
                                if ($fSuccess) {
963 30
                                    $mainStack->pop();
964
                                } else {
965
                                    throw new \RuntimeException('OP_CHECKMULTISIG verify');
966
                                }
967
                            }
968 108
                            break;
969
970 9
                        default:
971 109
                            throw new \RuntimeException('Opcode not found');
972 9
                    }
973
974 1207
                    if (count($mainStack) + count($altStack) > 1000) {
975 1218
                        throw new \RuntimeException('Invalid stack size, exceeds 1000');
976
                    }
977 137
                }
978 205
            }
979
980 1416
            if (count($vfStack) !== 0) {
981 6
                throw new \RuntimeException('Unbalanced conditional at script end');
982
            }
983
984 1411
            return true;
985 579
        } catch (ScriptRuntimeException $e) {
986
            // echo "\n Runtime: " . $e->getMessage() . "\n" . $e->getTraceAsString() . PHP_EOL;
987
            // Failure due to script tags, can access flag: $e->getFailureFlag()
988 180
            return false;
989 399
        } catch (\Exception $e) {
990
            // echo "\n General: " . $e->getMessage()  . PHP_EOL . $e->getTraceAsString() . PHP_EOL;
991 399
            return false;
992
        }
993
    }
994
}
995