Completed
Push — master ( 319c7a...cdee94 )
by thomas
79:06 queued 75:43
created

Interpreter::checkLockTime()   B

Complexity

Conditions 7
Paths 4

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 19
ccs 0
cts 11
cp 0
rs 8.2222
cc 7
eloc 10
nc 4
nop 1
crap 56
1
<?php
2
3
namespace BitWasp\Bitcoin\Script\Interpreter;
4
5
use BitWasp\Bitcoin\Crypto\EcAdapter\Adapter\EcAdapterInterface;
6
use BitWasp\Bitcoin\Crypto\Hash;
7
use BitWasp\Bitcoin\Exceptions\SignatureNotCanonical;
8
use BitWasp\Bitcoin\Exceptions\ScriptRuntimeException;
9
use BitWasp\Bitcoin\Flags;
10
use BitWasp\Bitcoin\Crypto\EcAdapter\Impl\PhpEcc\Key\PublicKey;
11
use BitWasp\Bitcoin\Key\PublicKeyFactory;
12
use BitWasp\Bitcoin\Locktime;
13
use BitWasp\Bitcoin\Script\Classifier\OutputClassifier;
14
use BitWasp\Bitcoin\Script\Opcodes;
15
use BitWasp\Bitcoin\Script\Script;
16
use BitWasp\Bitcoin\Script\ScriptInterface;
17
use BitWasp\Bitcoin\Signature\TransactionSignature;
18
use BitWasp\Bitcoin\Signature\TransactionSignatureFactory;
19
use BitWasp\Bitcoin\Transaction\SignatureHash\SignatureHashInterface;
20
use BitWasp\Bitcoin\Transaction\TransactionInterface;
21
use BitWasp\Buffertools\Buffer;
22
23
class Interpreter implements InterpreterInterface
24
{
25
    /**
26
     * @var int|string
27
     */
28
    private $inputToSign;
29
30
    /**
31
     * @var ScriptInterface
32
     */
33
    private $script;
34
35
    /**
36
     * @var TransactionInterface
37
     */
38
    private $transaction;
39
40
    /**
41
     * Position of OP_CODESEPARATOR, for calculating SigHash
42
     * @var int
43
     */
44
    private $hashStartPos;
45
46
    /**
47
     * @var int
48
     */
49
    private $opCount;
50
51
    /**
52
     * @var \BitWasp\Bitcoin\Flags
53
     */
54
    private $flags;
55
56
    /**
57
     * @var EcAdapterInterface
58
     */
59
    private $ecAdapter;
60
61
    /**
62
     * @var \BitWasp\Bitcoin\Math\Math
63
     */
64
    private $math;
65
66
    /**
67
     * @var State
68
     */
69
    private $state;
70
71
    /**
72
     * @var bool
73
     */
74
    private $minimalPush;
75
76
    /**
77
     * @var array
78
     */
79
    private $disabledOps = [
80
        Opcodes::OP_CAT,    Opcodes::OP_SUBSTR, Opcodes::OP_LEFT,  Opcodes::OP_RIGHT,
81
        Opcodes::OP_INVERT, Opcodes::OP_AND,    Opcodes::OP_OR,    Opcodes::OP_XOR,
82
        Opcodes::OP_2MUL,   Opcodes::OP_2DIV,   Opcodes::OP_MUL,   Opcodes::OP_DIV,
83
        Opcodes::OP_MOD,    Opcodes::OP_LSHIFT, Opcodes::OP_RSHIFT
84
    ];
85
86
    /**
87
     * @param EcAdapterInterface $ecAdapter
88
     * @param TransactionInterface $transaction
89
     * @param \BitWasp\Bitcoin\Flags $flags
90
     */
91 762
    public function __construct(EcAdapterInterface $ecAdapter, TransactionInterface $transaction, Flags $flags)
92
    {
93 762
        $this->ecAdapter = $ecAdapter;
94 762
        $this->math = $ecAdapter->getMath();
95 762
        $this->transaction = $transaction;
96 762
        $this->flags = $flags;
97 762
        $this->script = new Script();
98 762
        $this->minimalPush = $this->flags->checkFlags(self::VERIFY_MINIMALDATA) === true;
99 762
        $this->state = new State();
100 762
        $this->vchFalse = new Buffer("", 0, $this->math);
0 ignored issues
show
Bug introduced by
The property vchFalse does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
101 762
        $this->vchTrue = new Buffer("\x01", 1, $this->math);
0 ignored issues
show
Bug introduced by
The property vchTrue does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
102
103 762
        $this->int0 = Number::buffer($this->vchFalse, false, 4, $this->math)->getBuffer();
0 ignored issues
show
Bug introduced by
The property int0 does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
104 762
        $this->int1 = Number::buffer($this->vchTrue, false, 1, $this->math)->getBuffer();
0 ignored issues
show
Bug introduced by
The property int1 does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
105 762
    }
106
107
    /**
108
     * @return State
109
     */
110 6
    public function getStackState()
111
    {
112 6
        return $this->state;
113
    }
114
115
    /**
116
     * @param ScriptInterface $script
117
     * @return $this
118
     */
119 684
    public function setScript(ScriptInterface $script)
120
    {
121 684
        $this->script = $script;
122 684
        return $this;
123
    }
124
125
    /**
126
     * Cast the value to a boolean
127
     *
128
     * @param $value
129
     * @return bool
130
     */
131 432
    public function castToBool(Buffer $value)
132
    {
133 432
        if ($value->getSize() === 0) {
134 72
            return true;
135
        }
136
137
        // Since we're using buffers, lets try ensuring the contents are not 0.
138 360
        return $this->math->cmp($value->getInt(), 0) > 0;
139
    }
140
141
    /**
142
     * @param Buffer $signature
143
     * @return bool
144
     */
145 54
    public function isValidSignatureEncoding(Buffer $signature)
146
    {
147
        try {
148 54
            TransactionSignature::isDERSignature($signature);
149 36
            return true;
150 18
        } catch (SignatureNotCanonical $e) {
1 ignored issue
show
Unused Code introduced by
This catchblock is empty and will swallow any caught exception.

This check looks for ``catch` blocks that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

Empty catch blocks will swallow any caught exception, sometimes causing bugs in your code that are very hard to debug. Consider logging the exception to a debug log or re-throwing it in some way, shape or form.

Loading history...
151
            /* In any case, we will return false outside this block */
152
        }
153
154 18
        return false;
155
    }
156
157
    /**
158
     * @param Buffer $signature
159
     * @return bool
160
     * @throws ScriptRuntimeException
161
     * @throws \Exception
162
     */
163 30
    public function isLowDerSignature(Buffer $signature)
164
    {
165 30
        if (!$this->isValidSignatureEncoding($signature)) {
166 6
            throw new ScriptRuntimeException(self::VERIFY_DERSIG, 'Signature with incorrect encoding');
167
        }
168
169 24
        $binary = $signature->getBinary();
170 24
        $nLenR = ord($binary[3]);
171 24
        $nLenS = ord($binary[5 + $nLenR]);
172 24
        $s = $signature->slice(6 + $nLenR, $nLenS)->getInt();
173
174 24
        return $this->ecAdapter->validateSignatureElement($s, true);
175
    }
176
177
    /**
178
     * Determine whether the sighash byte appended to the signature encodes
179
     * a valid sighash type.
180
     *
181
     * @param Buffer $signature
182
     * @return bool
183
     */
184 36
    public function isDefinedHashtypeSignature(Buffer $signature)
185
    {
186 36
        if ($signature->getSize() === 0) {
187 6
            return false;
188
        }
189
190 30
        $binary = $signature->getBinary();
191 30
        $nHashType = ord(substr($binary, -1)) & (~(SignatureHashInterface::SIGHASH_ANYONECANPAY));
192
193 30
        $math = $this->math;
194 30
        return ! ($math->cmp($nHashType, SignatureHashInterface::SIGHASH_ALL) < 0 || $math->cmp($nHashType, SignatureHashInterface::SIGHASH_SINGLE) > 0);
195
    }
196
197
    /**
198
     * @param Buffer $signature
199
     * @return $this
200
     * @throws \BitWasp\Bitcoin\Exceptions\ScriptRuntimeException
201
     */
202 60
    public function checkSignatureEncoding(Buffer $signature)
203
    {
204 60
        if ($signature->getSize() === 0) {
205 6
            return $this;
206
        }
207
208 54
        if ($this->flags->checkFlags(self::VERIFY_DERSIG | self::VERIFY_LOW_S | self::VERIFY_STRICTENC) && !$this->isValidSignatureEncoding($signature)) {
209 12
            throw new ScriptRuntimeException(self::VERIFY_DERSIG, 'Signature with incorrect encoding');
210 42
        } else if ($this->flags->checkFlags(self::VERIFY_LOW_S) && !$this->isLowDerSignature($signature)) {
211 6
            throw new ScriptRuntimeException(self::VERIFY_LOW_S, 'Signature s element was not low');
212 36
        } else if ($this->flags->checkFlags(self::VERIFY_STRICTENC) && !$this->isDefinedHashtypeSignature($signature)) {
213 6
            throw new ScriptRuntimeException(self::VERIFY_STRICTENC, 'Signature with invalid hashtype');
214
        }
215
216 30
        return $this;
217
    }
218
219
    /**
220
     * @param Buffer $publicKey
221
     * @return $this
222
     * @throws \Exception
223
     */
224 24
    public function checkPublicKeyEncoding(Buffer $publicKey)
225
    {
226 24
        if ($this->flags->checkFlags(self::VERIFY_STRICTENC) && !PublicKey::isCompressedOrUncompressed($publicKey)) {
227 6
            throw new ScriptRuntimeException(self::VERIFY_STRICTENC, 'Public key with incorrect encoding');
228
        }
229
230 18
        return $this;
231
    }
232
233
    /**
234
     * @param $opCode
235
     * @param Buffer $pushData
236
     * @return bool
237
     * @throws \Exception
238
     */
239 6
    public function checkMinimalPush($opCode, Buffer $pushData)
240
    {
241 6
        $pushSize = $pushData->getSize();
242 6
        $binary = $pushData->getBinary();
243
244 6
        if ($pushSize === 0) {
245
            return $opCode === Opcodes::OP_0;
246 6
        } elseif ($pushSize === 1) {
247
            $first = ord($binary[0]);
248
            if ($first >= 1 && $first <= 16) {
249
                return $opCode === (Opcodes::OP_1 + ($first - 1));
250
            } elseif ($first === 0x81) {
251
                return $opCode === Opcodes::OP_1NEGATE;
252
            }
253 6
        } elseif ($pushSize <= 75) {
254 6
            return $opCode === $pushSize;
255
        } elseif ($pushSize <= 255) {
256
            return $opCode === Opcodes::OP_PUSHDATA1;
257
        } elseif ($pushSize <= 65535) {
258
            return $opCode === Opcodes::OP_PUSHDATA2;
259
        }
260
261
        return true;
262
    }
263
264
    /**
265
     * @return $this
266
     * @throws \Exception
267
     */
268 672
    private function checkOpcodeCount()
269
    {
270 672
        if ($this->math->cmp($this->opCount, 201) > 0) {
271 6
            throw new \RuntimeException('Error: Script op code count');
272
        }
273
274 672
        return $this;
275
    }
276
277
    /**
278
     * @param ScriptInterface $script
279
     * @param Buffer $sigBuf
280
     * @param Buffer $keyBuf
281
     * @return bool
282
     * @throws ScriptRuntimeException
283
     * @throws \Exception
284
     */
285 18
    private function checkSig(ScriptInterface $script, Buffer $sigBuf, Buffer $keyBuf)
286
    {
287 18
        $this
288 18
            ->checkSignatureEncoding($sigBuf)
289 12
            ->checkPublicKeyEncoding($keyBuf);
290
291
        try {
292 12
            $txSignature = TransactionSignatureFactory::fromHex($sigBuf->getHex());
293 12
            $publicKey = PublicKeyFactory::fromHex($keyBuf->getHex());
294
295 12
            return $this->ecAdapter->verify(
296 12
                $this
297
                    ->transaction
298 12
                    ->getSignatureHash()
299 12
                    ->calculate($script, $this->inputToSign, $txSignature->getHashType()),
300 12
                $publicKey,
301 12
                $txSignature->getSignature()
302 12
            );
303
        } catch (\Exception $e) {
304
            return false;
305
        }
306
    }
307
308
    /**
309
     * @param int $lockTime
310
     * @return bool
311
     */
312
    private function checkLockTime($lockTime)
313
    {
314
        $txLockTime = $this->transaction->getLockTime();
315
        if (($this->math->cmp($txLockTime, Locktime::BLOCK_MAX) < 0 && $this->math->cmp($lockTime, Locktime::BLOCK_MAX) < 0) ||
316
            ($this->math->cmp($txLockTime, Locktime::BLOCK_MAX) >= 0 && $this->math->cmp($lockTime, Locktime::BLOCK_MAX) >= 0)
317
        ) {
318
            return false;
319
        }
320
321
        if ($this->math->cmp($lockTime, $txLockTime) > 0) {
322
            return false;
323
        }
324
325
        if ($this->transaction->getInput($this->inputToSign)->isFinal()) {
326
            return false;
327
        }
328
329
        return true;
330
    }
331
332
    /**
333
     * @param ScriptInterface $scriptSig
334
     * @param ScriptInterface $scriptPubKey
335
     * @param int $nInputToSign
336
     * @return bool
337
     * @throws \Exception
338
     */
339 684
    public function verify(ScriptInterface $scriptSig, ScriptInterface $scriptPubKey, $nInputToSign)
340
    {
341 684
        $this->inputToSign = $nInputToSign;
342 684
        if (!$this->setScript($scriptSig)->run()) {
343
            return false;
344
        }
345
346 684
        $mainStack = $this->state->getMainStack();
347 684
        $stackCopy = new Stack;
348 684
        if ($this->flags->checkFlags(self::VERIFY_P2SH)) {
349 156
            $stackCopy = $this->state->cloneMainStack();
350 156
        }
351
352 684
        if (!$this->setScript($scriptPubKey)->run()) {
353 258
            return false;
354
        }
355
356 426
        if ($mainStack->isEmpty()) {
357
            return false;
358
        }
359
360 426
        if (false === $this->castToBool($mainStack[-1])) {
361
            return false;
362
        }
363
364 426
        $verifier = new OutputClassifier($scriptPubKey);
365
366 426
        if ($this->flags->checkFlags(self::VERIFY_P2SH) && $verifier->isPayToScriptHash()) {
367 6
            if (!$scriptSig->isPushOnly()) {
368
                return false;
369
            }
370
371
            // Restore mainStack to how it was after evaluating scriptSig
372 6
            $mainStack = $this->state->restoreMainStack($stackCopy)->getMainStack();
373 6
            if ($mainStack->isEmpty()) {
374
                return false;
375
            }
376
377
            // Load redeemscript as the scriptPubKey
378 6
            $scriptPubKey = new Script($mainStack->bottom());
379 6
            $mainStack->pop();
380
381 6
            if (!$this->setScript($scriptPubKey)->run()) {
382
                return false;
383
            }
384 6
        }
385
386 426
        return true;
387
    }
388
389
    /**
390
     * @return bool
391
     */
392 684
    private function checkExec()
393
    {
394 684
        $vfStack = $this->state->getVfStack();
395 684
        $c = 0;
396 684
        $len = $vfStack->end();
397 684
        for ($i = 0; $i < $len; $i++) {
398
            if ($vfStack[0 - $len - $i] === true) {
399
                $c++;
400
            }
401
        }
402 684
        return !(bool)$c;
403
    }
404
405
    /**
406
     * @return bool
407
     */
408 684
    private function run()
409
    {
410 684
        $math = $this->math;
411
412 684
        $flags = $this->flags;
413 684
        $mainStack = $this->state->getMainStack();
414 684
        $altStack = $this->state->getAltStack();
415 684
        $vfStack = $this->state->getVfStack();
416
417 684
        $this->hashStartPos = 0;
418 684
        $this->opCount = 0;
419 684
        $parser = $this->script->getScriptParser();
420
421 684
        if ($this->script->getBuffer()->getSize() > 10000) {
422
            return false;
423
        }
424
425
        try {
426 684
            foreach ($parser as $exec) {
427 684
                $opCode = $exec->getOp();
428 684
                $pushData = $exec->getData();
429 684
                $fExec = $this->checkExec();
430
431
                // If pushdata was written to,
432 684
                if ($exec->isPush() && $exec->getDataSize() > InterpreterInterface::MAX_SCRIPT_ELEMENT_SIZE) {
433
                    throw new \RuntimeException('Error - push size');
434
                }
435
436
                // OP_RESERVED should not count towards opCount
437 684
                if ($opCode > Opcodes::OP_16 && ++$this->opCount) {
438 672
                    $this->checkOpcodeCount();
439 672
                }
440
441 684
                if (in_array($opCode, $this->disabledOps, true)) {
442 12
                    throw new \RuntimeException('Disabled Opcode');
443
                }
444
445 684
                if ($fExec && $exec->isPush()) {
446
                    // In range of a pushdata opcode
447 426
                    if ($this->minimalPush && !$this->checkMinimalPush($opCode, $pushData)) {
448 6
                        throw new ScriptRuntimeException(self::VERIFY_MINIMALDATA, 'Minimal pushdata required');
449
                    }
450
451 420
                    $mainStack->push($pushData);
452
                    // echo " - [pushed '" . $pushData->getHex() . "']\n";
453 678
                } elseif ($fExec || ($opCode !== Opcodes::OP_IF && $opCode !== Opcodes::OP_ENDIF)) {
454
                    // echo "OPCODE - " . $this->script->getOpCodes()->getOp($opCode) . "\n";
455
                    switch ($opCode) {
456 660
                        case Opcodes::OP_1NEGATE:
457 660
                        case Opcodes::OP_1:
458 660
                        case Opcodes::OP_2:
459 660
                        case Opcodes::OP_3:
460 660
                        case Opcodes::OP_4:
461 660
                        case Opcodes::OP_5:
462 660
                        case Opcodes::OP_6:
463 660
                        case Opcodes::OP_7:
464 660
                        case Opcodes::OP_8:
465 660
                        case Opcodes::OP_9:
466 660
                        case Opcodes::OP_10:
467 660
                        case Opcodes::OP_11:
468 660
                        case Opcodes::OP_12:
469 660
                        case Opcodes::OP_13:
470 660
                        case Opcodes::OP_14:
471 660
                        case Opcodes::OP_15:
472 660
                        case Opcodes::OP_16:
473 192
                            $num = $opCode - (Opcodes::OP_1 - 1);
474 192
                            $mainStack->push(Number::int($num)->getBuffer());
475 192
                            break;
476
477 660
                        case Opcodes::OP_CHECKLOCKTIMEVERIFY:
478
                            if (!$this->flags->checkFlags(self::VERIFY_CHECKLOCKTIMEVERIFY)) {
479
                                if ($this->flags->checkFlags(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS)) {
480
                                    throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
481
                                }
482
                                break;
483
                            }
484
485
                            if ($mainStack->isEmpty()) {
486
                                throw new \RuntimeException('Invalid stack operation - CLTV');
487
                            }
488
489
                            $lockTime = Number::buffer($mainStack[-1], $this->minimalPush, 5, $math)->getInt();
490
                            if (!$this->checkLockTime($lockTime)) {
491
                                throw new ScriptRuntimeException(self::VERIFY_CHECKLOCKTIMEVERIFY, 'Unsatisfied locktime');
492
                            }
493
494
                            break;
495
496 660
                        case Opcodes::OP_NOP1:
497 660
                        case Opcodes::OP_NOP3:
498 660
                        case Opcodes::OP_NOP4:
499 660
                        case Opcodes::OP_NOP5:
500 660
                        case Opcodes::OP_NOP6:
501 660
                        case Opcodes::OP_NOP7:
502 660
                        case Opcodes::OP_NOP8:
503 660
                        case Opcodes::OP_NOP9:
504 660
                        case Opcodes::OP_NOP10:
505 6
                            if ($flags->checkFlags(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS)) {
506 6
                                throw new ScriptRuntimeException(self::VERIFY_DISCOURAGE_UPGRADABLE_NOPS, 'Upgradable NOP found - this is discouraged');
507
                            }
508
                            break;
509
510 654
                        case Opcodes::OP_NOP:
511 12
                            break;
512
513 642
                        case Opcodes::OP_IF:
514 642
                        case Opcodes::OP_NOTIF:
515
                            // <expression> if [statements] [else [statements]] endif
516 18
                            $value = false;
517 18
                            if ($fExec) {
518 18
                                if ($mainStack->isEmpty()) {
519 6
                                    throw new \RuntimeException('Unbalanced conditional');
520
                                }
521
                                // todo
522 12
                                $buffer = Number::buffer($mainStack->pop(), $this->minimalPush)->getBuffer();
523 12
                                $value = $this->castToBool($buffer);
524 12
                                if ($opCode === Opcodes::OP_NOTIF) {
525 6
                                    $value = !$value;
526 6
                                }
527 12
                            }
528 12
                            $vfStack->push($value ? $this->vchTrue : $this->vchFalse);
529 12
                            break;
530
531 636
                        case Opcodes::OP_ELSE:
532 18
                            if ($vfStack->isEmpty()) {
533 6
                                throw new \RuntimeException('Unbalanced conditional');
534
                            }
535 12
                            $vfStack[-1] = !$vfStack->end() ? $this->vchTrue : $this->vchFalse;
536 12
                            break;
537
538 630
                        case Opcodes::OP_ENDIF:
539 18
                            if ($vfStack->isEmpty()) {
540 6
                                throw new \RuntimeException('Unbalanced conditional');
541
                            }
542 12
                            break;
543
544 624
                        case Opcodes::OP_VERIFY:
545 24
                            if ($mainStack->isEmpty()) {
546 6
                                throw new \RuntimeException('Invalid stack operation');
547
                            }
548 18
                            $value = $this->castToBool($mainStack[-1]);
549 18
                            if (!$value) {
550 6
                                throw new \RuntimeException('Error: verify');
551
                            }
552 12
                            $mainStack->pop();
553 12
                            break;
554
555 600
                        case Opcodes::OP_RESERVED:
556
                            // todo
557 12
                            break;
558
559 588
                        case Opcodes::OP_TOALTSTACK:
560 18
                            if ($mainStack->isEmpty()) {
561 6
                                throw new \RuntimeException('Invalid stack operation OP_TOALTSTACK');
562
                            }
563 12
                            $altStack->push($mainStack->pop());
564 12
                            break;
565
566 582
                        case Opcodes::OP_FROMALTSTACK:
567 12
                            if ($altStack->isEmpty()) {
568 6
                                throw new \RuntimeException('Invalid alt-stack operation OP_FROMALTSTACK');
569
                            }
570 6
                            $mainStack->push($altStack->pop());
571 6
                            break;
572
573 576
                        case Opcodes::OP_IFDUP:
574
                            // If top value not zero, duplicate it.
575 12
                            if ($mainStack->isEmpty()) {
576 6
                                throw new \RuntimeException('Invalid stack operation OP_IFDUP');
577
                            }
578 6
                            $vch = $mainStack[-1];
579 6
                            if ($this->castToBool($vch)) {
580 6
                                $mainStack->push($vch);
581 6
                            }
582 6
                            break;
583
584 570
                        case Opcodes::OP_DEPTH:
585 72
                            $num = count($mainStack);
586 72
                            if ($num === 0) {
587 24
                                $depth = $this->vchFalse;
588 24
                            } else {
589 54
                                $depth = Number::int($num)->getBuffer();
590
                            }
591
592 72
                            $mainStack->push($depth);
593 72
                            break;
594
595 570
                        case Opcodes::OP_DROP:
596 6
                            if ($mainStack->isEmpty()) {
597 6
                                throw new \RuntimeException('Invalid stack operation OP_DROP');
598
                            }
599
                            $mainStack->pop();
600
                            break;
601
602 564
                        case Opcodes::OP_DUP:
603 18
                            if ($mainStack->isEmpty()) {
604 6
                                throw new \RuntimeException('Invalid stack operation OP_DUP');
605
                            }
606 12
                            $vch = $mainStack[-1];
607 12
                            $mainStack->push($vch);
608 12
                            break;
609
610 558
                        case Opcodes::OP_NIP:
611 18
                            if (count($mainStack) < 2) {
612 6
                                throw new \RuntimeException('Invalid stack operation OP_NIP');
613
                            }
614 12
                            unset($mainStack[-2]);
615 12
                            break;
616
617 552
                        case Opcodes::OP_OVER:
618 18
                            if (count($mainStack) < 2) {
619 6
                                throw new \RuntimeException('Invalid stack operation OP_OVER');
620
                            }
621 12
                            $vch = $mainStack[-2];
622 12
                            $mainStack->push($vch);
623 12
                            break;
624
    
625 546
                        case Opcodes::OP_ROT:
626 12
                            if (count($mainStack) < 3) {
627 6
                                throw new \RuntimeException('Invalid stack operation OP_ROT');
628
                            }
629 6
                            $mainStack->swap(-3, -2);
630 6
                            $mainStack->swap(-2, -1);
631 6
                            break;
632
633 540
                        case Opcodes::OP_SWAP:
634 12
                            if (count($mainStack) < 2) {
635 6
                                throw new \RuntimeException('Invalid stack operation OP_SWAP');
636
                            }
637 6
                            $mainStack->swap(-2, -1);
638 6
                            break;
639
640 534
                        case Opcodes::OP_TUCK:
641 12
                            if (count($mainStack) < 2) {
642 6
                                throw new \RuntimeException('Invalid stack operation OP_TUCK');
643
                            }
644 6
                            $vch = $mainStack[-1];
645 6
                            $mainStack->add(count($mainStack) - 1 - 2, $vch);
646
                            break;
647
648 522
                        case Opcodes::OP_PICK:
649 522
                        case Opcodes::OP_ROLL:
650 24
                            if (count($mainStack) < 2) {
651 6
                                throw new \RuntimeException('Invalid stack operation OP_PICK');
652
                            }
653
654 18
                            $n = Number::buffer($mainStack[-1], $this->minimalPush, 4)->getInt();
655 18
                            $mainStack->pop();
656 18
                            if ($math->cmp($n, 0) < 0 || $math->cmp($n, count($mainStack)) >= 0) {
657 6
                                throw new \RuntimeException('Invalid stack operation OP_PICK');
658
                            }
659
660 12
                            $pos = (int) $math->sub($math->sub(0, $n), 1);
661 12
                            $vch = $mainStack[$pos];
662 12
                            if ($opCode === Opcodes::OP_ROLL) {
663 6
                                unset($mainStack[$pos]);
664 6
                            }
665 12
                            $mainStack->push($vch);
666 12
                            break;
667
668 510
                        case Opcodes::OP_2DROP:
669 12
                            if (count($mainStack) < 2) {
670 6
                                throw new \RuntimeException('Invalid stack operation OP_2DROP');
671
                            }
672 6
                            $mainStack->pop();
673 6
                            $mainStack->pop();
674 6
                            break;
675
676 504
                        case Opcodes::OP_2DUP:
677 18
                            if (count($mainStack) < 2) {
678 6
                                throw new \RuntimeException('Invalid stack operation OP_2DUP');
679
                            }
680 12
                            $string1 = $mainStack[-2];
681 12
                            $string2 = $mainStack[-1];
682 12
                            $mainStack->push($string1);
683 12
                            $mainStack->push($string2);
684 12
                            break;
685
686 498
                        case Opcodes::OP_3DUP:
687 18
                            if (count($mainStack) < 3) {
688 6
                                throw new \RuntimeException('Invalid stack operation OP_3DUP');
689
                            }
690 12
                            $string1 = $mainStack[-3];
691 12
                            $string2 = $mainStack[-2];
692 12
                            $string3 = $mainStack[-1];
693 12
                            $mainStack->push($string1);
694 12
                            $mainStack->push($string2);
695 12
                            $mainStack->push($string3);
696 12
                            break;
697
698 492
                        case Opcodes::OP_2OVER:
699 18
                            if (count($mainStack) < 4) {
700 6
                                throw new \RuntimeException('Invalid stack operation OP_2OVER');
701
                            }
702 12
                            $string1 = $mainStack[-4];
703 12
                            $string2 = $mainStack[-3];
704 12
                            $mainStack->push($string1);
705 12
                            $mainStack->push($string2);
706 12
                            break;
707
708 486
                        case Opcodes::OP_2ROT:
709 12
                            if (count($mainStack) < 6) {
710 6
                                throw new \RuntimeException('Invalid stack operation OP_2ROT');
711
                            }
712 6
                            $string1 = $mainStack[-6];
713 6
                            $string2 = $mainStack[-5];
714 6
                            unset($mainStack[-6], $mainStack[-5]);
715 6
                            $mainStack->push($string1);
716 6
                            $mainStack->push($string2);
717 6
                            break;
718
719 480
                        case Opcodes::OP_2SWAP:
720 12
                            if (count($mainStack) < 4) {
721 6
                                throw new \RuntimeException('Invalid stack operation OP_2SWAP');
722
                            }
723 6
                            $mainStack->swap(-3, -1);
724 6
                            $mainStack->swap(-4, -2);
725 6
                            break;
726
727 474
                        case Opcodes::OP_SIZE:
728 12
                            if ($mainStack->isEmpty()) {
729 6
                                throw new \RuntimeException('Invalid stack operation OP_SIZE');
730
                            }
731
                            // todo: Int sizes?
732 6
                            $vch = $mainStack[-1];
733 6
                            $mainStack->push(Number::int($vch->getSize())->getBuffer());
734 6
                            break;
735
736 468
                        case Opcodes::OP_EQUAL:
737 468
                        case Opcodes::OP_EQUALVERIFY:
738 396
                            if (count($mainStack) < 2) {
739 6
                                throw new \RuntimeException('Invalid stack operation OP_EQUAL');
740
                            }
741 390
                            $vch1 = $mainStack[-2];
742 390
                            $vch2 = $mainStack[-1];
743
744 390
                            $equal = ($vch1->getBinary() === $vch2->getBinary());
745
746 390
                            $mainStack->pop();
747 390
                            $mainStack->pop();
748 390
                            $mainStack->push(($equal ? $this->vchTrue : $this->vchFalse));
749 390
                            if ($opCode === Opcodes::OP_EQUALVERIFY) {
750 114
                                if ($equal) {
751 102
                                    $mainStack->pop();
752 102
                                } else {
753 12
                                    throw new \RuntimeException('Error EQUALVERIFY');
754
                                }
755 102
                            }
756
757 378
                            break;
758
759
                        // Arithmetic operations
760 282
                        case $opCode >= Opcodes::OP_1ADD && $opCode <= Opcodes::OP_0NOTEQUAL:
761 48
                            if ($mainStack->isEmpty()) {
762 6
                                throw new \Exception('Invalid stack operation 1ADD-OP_0NOTEQUAL');
763
                            }
764
765 42
                            $num = Number::buffer($mainStack[-1], $this->minimalPush)->getInt();
766
767 42
                            if ($opCode === Opcodes::OP_1ADD) {
768 6
                                $num = $math->add($num, '1');
769 42
                            } elseif ($opCode === Opcodes::OP_1SUB) {
770 6
                                $num = $math->sub($num, '1');
771 36
                            } elseif ($opCode === Opcodes::OP_2MUL) {
772
                                $num = $math->mul(2, $num);
773 30
                            } elseif ($opCode === Opcodes::OP_NEGATE) {
774
                                $num = $math->sub(0, $num);
775 30
                            } elseif ($opCode === Opcodes::OP_ABS) {
776
                                if ($math->cmp($num, '0') < 0) {
777
                                    $num = $math->sub(0, $num);
778
                                }
779 30
                            } elseif ($opCode === Opcodes::OP_NOT) {
780 18
                                $num = (int) $math->cmp($num, '0') === 0;
781 18
                            } else {
782
                                // is OP_0NOTEQUAL
783 12
                                $num = (int) ($math->cmp($num, '0') !== 0);
784
                            }
785
786 42
                            $mainStack->pop();
787
788 42
                            $buffer = Number::int($num)->getBuffer();
789
790 42
                            $mainStack->push($buffer);
791 42
                            break;
792
793 234
                        case $opCode >= Opcodes::OP_ADD && $opCode <= Opcodes::OP_MAX:
794 150
                            if (count($mainStack) < 2) {
795 24
                                throw new \Exception('Invalid stack operation (OP_ADD - OP_MAX)');
796
                            }
797
798 126
                            $num1 = Number::buffer($mainStack[-2], $this->minimalPush)->getInt();
799 126
                            $num2 = Number::buffer($mainStack[-1], $this->minimalPush)->getInt();
800
801 126
                            if ($opCode === Opcodes::OP_ADD) {
802 6
                                $num = $math->add($num1, $num2);
803 126
                            } else if ($opCode === Opcodes::OP_SUB) {
804 6
                                $num = $math->sub($num1, $num2);
805 120
                            } else if ($opCode === Opcodes::OP_BOOLAND) {
806 12
                                $num = $math->cmp($num1, $this->int0->getInt()) !== 0 && $math->cmp($num2, $this->int0->getInt()) !== 0;
807 114
                            } else if ($opCode === Opcodes::OP_BOOLOR) {
808 18
                                $num = $math->cmp($num1, $this->int0->getInt()) !== 0 || $math->cmp($num2, $this->int0->getInt()) !== 0;
809 102
                            } elseif ($opCode === Opcodes::OP_NUMEQUAL) {
810 18
                                $num = $math->cmp($num1, $num2) === 0;
811 84
                            } elseif ($opCode === Opcodes::OP_NUMEQUALVERIFY) {
812
                                $num = $math->cmp($num1, $num2) === 0;
813 66
                            } elseif ($opCode === Opcodes::OP_NUMNOTEQUAL) {
814 6
                                $num = $math->cmp($num1, $num2) !== 0;
815 66
                            } elseif ($opCode === Opcodes::OP_LESSTHAN) {
816 12
                                $num = $math->cmp($num1, $num2) < 0;
817 60
                            } elseif ($opCode === Opcodes::OP_GREATERTHAN) {
818 12
                                $num = $math->cmp($num1, $num2) > 0;
819 48
                            } elseif ($opCode === Opcodes::OP_LESSTHANOREQUAL) {
820 12
                                $num = $math->cmp($num1, $num2) <= 0;
821 36
                            } elseif ($opCode === Opcodes::OP_GREATERTHANOREQUAL) {
822 12
                                $num = $math->cmp($num1, $num2) >= 0;
823 24
                            } elseif ($opCode === Opcodes::OP_MIN) {
824 6
                                $num = ($math->cmp($num1, $num2) <= 0) ? $num1 : $num2;
825 6
                            } else {
826 6
                                $num = ($math->cmp($num1, $num2) >= 0) ? $num1 : $num2;
827
                            }
828
829 126
                            $mainStack->pop();
830 126
                            $mainStack->pop();
831 126
                            $buffer = Number::int($num)->getBuffer();
832 126
                            $mainStack->push($buffer);
833
834 126
                            if ($opCode === Opcodes::OP_NUMEQUALVERIFY) {
835
                                if ($this->castToBool($mainStack[-1])) {
836
                                    $mainStack->pop();
837
                                } else {
838
                                    throw new \RuntimeException('NUM EQUAL VERIFY error');
839
                                }
840
                            }
841 126
                            break;
842
843 84
                        case Opcodes::OP_WITHIN:
844 12
                            if (count($mainStack) < 3) {
845 6
                                throw new \RuntimeException('Invalid stack operation');
846
                            }
847
848 6
                            $num1 = Number::buffer($mainStack[-3], $this->minimalPush)->getInt();
849 6
                            $num2 = Number::buffer($mainStack[-2], $this->minimalPush)->getInt();
850 6
                            $num3 = Number::buffer($mainStack[-1], $this->minimalPush)->getInt();
851
852 6
                            $value = $math->cmp($num2, $num1) <= 0 && $math->cmp($num1, $num3) < 0;
853 6
                            $mainStack->pop();
854 6
                            $mainStack->pop();
855 6
                            $mainStack->pop();
856 6
                            $mainStack->push($value ? $this->vchFalse : $this->vchTrue);
857 6
                            break;
858
859
                        // Hash operation
860 72
                        case Opcodes::OP_RIPEMD160:
861 72
                        case Opcodes::OP_SHA1:
862 72
                        case Opcodes::OP_SHA256:
863 72
                        case Opcodes::OP_HASH160:
864 72
                        case Opcodes::OP_HASH256:
865 48
                            if ($mainStack->isEmpty()) {
866 6
                                throw new \RuntimeException('Invalid stack operation');
867
                            }
868
869 42
                            $buffer = $mainStack[-1];
870 42
                            if ($opCode === Opcodes::OP_RIPEMD160) {
871 6
                                $hash = Hash::ripemd160($buffer);
872 42
                            } elseif ($opCode === Opcodes::OP_SHA1) {
873 6
                                $hash = Hash::sha1($buffer);
874 36
                            } elseif ($opCode === Opcodes::OP_SHA256) {
875 6
                                $hash = Hash::sha256($buffer);
876 30
                            } elseif ($opCode === Opcodes::OP_HASH160) {
877 18
                                $hash = Hash::sha256ripe160($buffer);
878 18
                            } else {
879 6
                                $hash = Hash::sha256d($buffer);
880
                            }
881
882 42
                            $mainStack->pop();
883 42
                            $mainStack->push($hash);
884 42
                            break;
885
886 30
                        case Opcodes::OP_CODESEPARATOR:
887
                            $this->hashStartPos = $parser->getPosition();
888
                            break;
889
890 30
                        case Opcodes::OP_CHECKSIG:
891 30
                        case Opcodes::OP_CHECKSIGVERIFY:
892 24
                            if (count($mainStack) < 2) {
893 6
                                throw new \RuntimeException('Invalid stack operation');
894
                            }
895
896 18
                            $vchPubKey = $mainStack[-1];
897 18
                            $vchSig = $mainStack[-2];
898
899 18
                            $scriptCode = new Script($this->script->getBuffer()->slice($this->hashStartPos));
900 18
                            $success = $this->checkSig($scriptCode, $vchSig, $vchPubKey);
901
902 12
                            $mainStack->pop();
903 12
                            $mainStack->pop();
904 12
                            $mainStack->push($success ? $this->vchTrue : $this->vchFalse);
905
906 12
                            if ($opCode === Opcodes::OP_CHECKSIGVERIFY) {
907
                                if ($success) {
908
                                    $mainStack->pop();
909
                                } else {
910
                                    throw new \RuntimeException('Checksig verify');
911
                                }
912
                            }
913 12
                            break;
914
915 6
                        case Opcodes::OP_CHECKMULTISIG:
916 6
                        case Opcodes::OP_CHECKMULTISIGVERIFY:
917
                            $i = 1;
918
                            if (count($mainStack) < $i) {
919
                                throw new \RuntimeException('Invalid stack operation');
920
                            }
921
922
                            $keyCount = Number::buffer($mainStack[-$i], $this->minimalPush)->getInt();
923
                            if ($math->cmp($keyCount, 0) < 0 || $math->cmp($keyCount, 20) > 0) {
924
                                throw new \RuntimeException('OP_CHECKMULTISIG: Public key count exceeds 20');
925
                            }
926
                            $this->opCount += $keyCount;
927
                            $this->checkOpcodeCount();
928
929
                            // Extract positions of the keys, and signatures, from the stack.
930
                            $ikey = ++$i;
931
                            $i += $keyCount; /** @var int $i */
932
                            if (count($mainStack) < $i) {
933
                                throw new \RuntimeException('Invalid stack operation');
934
                            }
935
936
                            $sigCount = Number::buffer($mainStack[-$i], $this->minimalPush)->getInt();
937
                            if ($math->cmp($sigCount, 0) < 0 || $math->cmp($sigCount, $keyCount) > 0) {
938
                                throw new \RuntimeException('Invalid Signature count');
939
                            }
940
                            $isig = ++$i;
941
                            $i += $sigCount;
942
943
                            // Extract the script since the last OP_CODESEPARATOR
944
                            $scriptCode = new Script($this->script->getBuffer()->slice($this->hashStartPos));
945
946
                            $fSuccess = true;
947
                            while ($fSuccess && $sigCount > 0) {
948
                                // Fetch the signature and public key
949
                                $sig = $mainStack[-$isig];
950
                                $pubkey = $mainStack[-$ikey];
951
952
                                // Erase the signature and public key.
953
                                unset($mainStack[-$isig], $mainStack[-$ikey]);
954
955
                                // Decrement $i, since we are consuming stack values.
956
                                $i -= 2;
957
958
                                if ($this->checkSig($scriptCode, $sig, $pubkey)) {
959
                                    $isig++;
960
                                    $sigCount--;
961
                                }
962
963
                                $ikey++;
964
                                $keyCount--;
965
966
                                // If there are more signatures left than keys left,
967
                                // then too many signatures have failed. Exit early,
968
                                // without checking any further signatures.
969
                                if ($sigCount > $keyCount) {
970
                                    $fSuccess = false;
971
                                }
972
                            }
973
974
                            while ($i-- > 1) {
975
                                $mainStack->pop();
976
                            }
977
978
                            // A bug causes CHECKMULTISIG to consume one extra argument
979
                            // whose contents were not checked in any way.
980
                            //
981
                            // Unfortunately this is a potential source of mutability,
982
                            // so optionally verify it is exactly equal to zero prior
983
                            // to removing it from the stack.
984
                            if ($mainStack->isEmpty()) {
985
                                throw new \RuntimeException('Invalid stack operation');
986
                            }
987
988
                            if ($flags->checkFlags(self::VERIFY_NULL_DUMMY) && $mainStack[-1]->getSize()) {
989
                                throw new ScriptRuntimeException(self::VERIFY_NULL_DUMMY, 'Extra P2SH stack value should be OP_0');
990
                            }
991
992
                            $mainStack->pop();
993
                            $mainStack->push($fSuccess ? $this->vchTrue : $this->vchFalse);
994
995
                            if ($opCode === Opcodes::OP_CHECKMULTISIGVERIFY) {
996
                                if ($fSuccess) {
997
                                    $mainStack->pop();
998
                                } else {
999
                                    throw new \RuntimeException('OP_CHECKMULTISIG verify');
1000
                                }
1001
                            }
1002
                            break;
1003
1004 6
                        default:
1005 6
                            throw new \RuntimeException('Opcode not found');
1006 6
                    }
1007
1008 426
                    if (count($mainStack) + count($altStack) > 1000) {
1009
                        throw new \RuntimeException('Invalid stack size, exceeds 1000');
1010
                    }
1011 426
                }
1012 684
            }
1013
1014 684
            if (!$vfStack->end() === 0) {
1015
                throw new \RuntimeException('Unbalanced conditional at script end');
1016
            }
1017
1018 684
            return true;
1019 258
        } catch (ScriptRuntimeException $e) {
1020
            // echo "\n Runtime: " . $e->getMessage() . "\n";
1021
            // Failure due to script tags, can access flag: $e->getFailureFlag()
1022 18
            return false;
1023 240
        } catch (\Exception $e) {
1024
            // echo "\n General: " . $e->getMessage() ;
1025 240
            return false;
1026
        }
1027
    }
1028
}
1029