Completed
Pull Request — master (#201)
by thomas
106:09 queued 102:54
created

Interpreter::getStackState()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

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