@opcat-labs/opcat 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cjs2esm.json +18 -0
- package/.mocharc.yaml +1 -1
- package/CHANGELOG.md +13 -0
- package/README.md +6 -0
- package/{lib/address.js → cjs/address.cjs} +77 -72
- package/cjs/block/block.cjs +332 -0
- package/{lib/block/blockheader.js → cjs/block/blockheader.cjs} +8 -7
- package/cjs/block/index.cjs +2 -0
- package/{lib/block/merkleblock.js → cjs/block/merkleblock.cjs} +23 -15
- package/cjs/bn.cjs +3411 -0
- package/{lib/crypto/bn.js → cjs/crypto/bn.cjs} +3 -3
- package/{lib/crypto/ecdsa.js → cjs/crypto/ecdsa.cjs} +150 -14
- package/{lib/crypto/hash.node.js → cjs/crypto/hash.cjs} +13 -2
- package/cjs/crypto/index.cjs +16 -0
- package/{lib/crypto/point.js → cjs/crypto/point.cjs} +11 -4
- package/cjs/crypto/random.cjs +18 -0
- package/{lib/crypto/signature.js → cjs/crypto/signature.cjs} +158 -8
- package/{lib/encoding/base58.js → cjs/encoding/base58.cjs} +58 -2
- package/cjs/encoding/base58check.cjs +192 -0
- package/cjs/encoding/bufferreader.cjs +333 -0
- package/cjs/encoding/bufferwriter.cjs +244 -0
- package/{lib/encoding/decode-asm.js → cjs/encoding/decode-asm.cjs} +4 -4
- package/{lib/encoding/decode-hex.js → cjs/encoding/decode-hex.cjs} +1 -1
- package/cjs/encoding/index.cjs +14 -0
- package/cjs/encoding/varint.cjs +116 -0
- package/{lib/errors/index.js → cjs/errors/index.cjs} +9 -9
- package/{lib/errors/spec.js → cjs/errors/spec.cjs} +2 -2
- package/cjs/hash-cache.cjs +98 -0
- package/{lib/hdprivatekey.js → cjs/hdprivatekey.cjs} +232 -140
- package/{lib/hdpublickey.js → cjs/hdpublickey.cjs} +120 -93
- package/cjs/index.cjs +94 -0
- package/cjs/interpreter/index.cjs +2 -0
- package/cjs/interpreter/interpreter.cjs +1988 -0
- package/{lib/script/stack.js → cjs/interpreter/stack.cjs} +9 -2
- package/{lib/message/message.js → cjs/message/message.cjs} +62 -25
- package/cjs/mnemonic/index.cjs +3 -0
- package/{lib/mnemonic/mnemonic.js → cjs/mnemonic/mnemonic.cjs} +44 -13
- package/{lib/mnemonic/pbkdf2.node.js → cjs/mnemonic/pbkdf2.cjs} +9 -2
- package/cjs/mnemonic/words/index.cjs +66 -0
- package/cjs/network.cjs +13 -0
- package/cjs/networks.cjs +321 -0
- package/{lib/opcode.js → cjs/opcode.cjs} +69 -5
- package/cjs/privatekey.cjs +422 -0
- package/{lib/publickey.js → cjs/publickey.cjs} +14 -16
- package/cjs/script/index.cjs +2 -0
- package/{lib/script/script.js → cjs/script/script.cjs} +322 -67
- package/cjs/transaction/index.cjs +5 -0
- package/cjs/transaction/input/index.cjs +34 -0
- package/cjs/transaction/input/input.cjs +396 -0
- package/{lib/transaction/input/multisig.js → cjs/transaction/input/multisig.cjs} +112 -18
- package/{lib/transaction/input/publickey.js → cjs/transaction/input/publickey.cjs} +29 -19
- package/{lib/transaction/input/publickeyhash.js → cjs/transaction/input/publickeyhash.cjs} +25 -17
- package/{lib/transaction/output.js → cjs/transaction/output.cjs} +100 -15
- package/cjs/transaction/sighash.cjs +187 -0
- package/{lib/transaction/signature.js → cjs/transaction/signature.cjs} +30 -6
- package/cjs/transaction/transaction.cjs +2000 -0
- package/{lib/transaction/unspentoutput.js → cjs/transaction/unspentoutput.cjs} +5 -5
- package/cjs/util/derivation.cjs +53 -0
- package/cjs/util/index.cjs +11 -0
- package/cjs/util/js.cjs +95 -0
- package/{lib/util/preconditions.js → cjs/util/preconditions.cjs} +2 -2
- package/esm/address.js +483 -0
- package/{lib → esm}/block/block.js +82 -27
- package/esm/block/blockheader.js +296 -0
- package/esm/block/index.js +2 -0
- package/esm/block/merkleblock.js +331 -0
- package/esm/bn.js +3411 -0
- package/esm/crypto/bn.js +278 -0
- package/esm/crypto/ecdsa.js +475 -0
- package/{lib/crypto/hash.browser.js → esm/crypto/hash.js} +18 -7
- package/esm/crypto/index.js +16 -0
- package/esm/crypto/point.js +228 -0
- package/esm/crypto/random.js +18 -0
- package/esm/crypto/signature.js +475 -0
- package/esm/encoding/base58.js +167 -0
- package/esm/encoding/base58check.js +192 -0
- package/esm/encoding/bufferreader.js +333 -0
- package/esm/encoding/bufferwriter.js +243 -0
- package/esm/encoding/decode-asm.js +24 -0
- package/esm/encoding/decode-hex.js +32 -0
- package/esm/encoding/decode-script-chunks.js +43 -0
- package/esm/encoding/encode-hex.js +284 -0
- package/esm/encoding/index.js +14 -0
- package/esm/encoding/is-hex.js +7 -0
- package/esm/encoding/varint.js +116 -0
- package/esm/errors/index.js +54 -0
- package/esm/errors/spec.js +314 -0
- package/esm/hash-cache.js +98 -0
- package/esm/hdprivatekey.js +768 -0
- package/esm/hdpublickey.js +549 -0
- package/esm/index.js +66 -0
- package/esm/interpreter/index.js +2 -0
- package/{lib/script → esm/interpreter}/interpreter.js +219 -66
- package/esm/interpreter/stack.js +116 -0
- package/esm/message/message.js +228 -0
- package/esm/mnemonic/index.js +3 -0
- package/esm/mnemonic/mnemonic.js +332 -0
- package/{lib/mnemonic/pbkdf2.browser.js → esm/mnemonic/pbkdf2.js} +13 -6
- package/esm/mnemonic/words/chinese.js +2054 -0
- package/esm/mnemonic/words/english.js +2054 -0
- package/esm/mnemonic/words/french.js +2054 -0
- package/esm/mnemonic/words/index.js +66 -0
- package/esm/mnemonic/words/italian.js +2054 -0
- package/esm/mnemonic/words/japanese.js +2054 -0
- package/esm/mnemonic/words/spanish.js +2054 -0
- package/esm/network.js +13 -0
- package/{lib → esm}/networks.js +61 -120
- package/esm/opcode.js +319 -0
- package/{lib → esm}/privatekey.js +76 -28
- package/esm/publickey.js +384 -0
- package/esm/script/index.js +2 -0
- package/esm/script/script.js +1329 -0
- package/esm/script/write-i32-le.js +17 -0
- package/esm/script/write-push-data.js +35 -0
- package/esm/script/write-u16-le.js +12 -0
- package/esm/script/write-u32-le.js +16 -0
- package/esm/script/write-u64-le.js +24 -0
- package/esm/script/write-u8-le.js +8 -0
- package/esm/script/write-varint.js +46 -0
- package/esm/transaction/index.js +5 -0
- package/esm/transaction/input/index.js +33 -0
- package/{lib → esm}/transaction/input/input.js +132 -90
- package/esm/transaction/input/multisig.js +335 -0
- package/esm/transaction/input/publickey.js +108 -0
- package/esm/transaction/input/publickeyhash.js +124 -0
- package/esm/transaction/output.js +316 -0
- package/{lib → esm}/transaction/sighash.js +42 -22
- package/esm/transaction/signature.js +120 -0
- package/{lib → esm}/transaction/transaction.js +522 -163
- package/esm/transaction/unspentoutput.js +112 -0
- package/esm/util/_.js +47 -0
- package/esm/util/derivation.js +53 -0
- package/esm/util/index.js +12 -0
- package/esm/util/js.js +95 -0
- package/esm/util/preconditions.js +33 -0
- package/fixup.cjs +17 -0
- package/package.json +40 -26
- package/test/{address.js → address.cjs} +14 -43
- package/test/block/{block.js → block.cjs} +3 -5
- package/test/block/{blockheader.js → blockheader.cjs} +2 -2
- package/test/block/{merklebloack.js → merklebloack.cjs} +2 -2
- package/test/crypto/{ecdsa.js → ecdsa.cjs} +9 -9
- package/test/crypto/{hash.browser.js → hash.browser.cjs} +2 -1
- package/test/crypto/{signature.js → signature.cjs} +2 -2
- package/test/data/bitcoind/script_tests.json +5 -5
- package/test/{hashCache.js → hashCache.cjs} +2 -1
- package/test/{hdkeys.js → hdkeys.cjs} +4 -2
- package/test/{hdprivatekey.js → hdprivatekey.cjs} +7 -6
- package/test/{hdpublickey.js → hdpublickey.cjs} +2 -7
- package/test/mnemonic/{pbkdf2.test.js → pbkdf2.test.cjs} +2 -2
- package/test/{networks.js → networks.cjs} +12 -31
- package/test/{publickey.js → publickey.cjs} +2 -2
- package/test/script/{interpreter.js → interpreter.cjs} +5 -5
- package/test/script/{script.js → script.cjs} +8 -2
- package/test/transaction/{deserialize.js → deserialize.cjs} +2 -2
- package/test/transaction/input/{input.js → input.cjs} +1 -1
- package/test/transaction/input/{multisig.js → multisig.cjs} +2 -1
- package/test/transaction/input/{publickeyhash.js → publickeyhash.cjs} +1 -1
- package/test/transaction/{sighash.js → sighash.cjs} +1 -1
- package/test/transaction/{transaction.js → transaction.cjs} +2 -2
- package/tsconfig.json +13 -0
- package/types/address.d.cts +252 -0
- package/types/block/block.d.cts +139 -0
- package/types/block/blockheader.d.cts +125 -0
- package/types/block/index.d.cts +2 -0
- package/types/block/merkleblock.d.cts +95 -0
- package/types/bn.d.cts +202 -0
- package/types/crypto/bn.d.cts +2 -0
- package/types/crypto/ecdsa.d.cts +187 -0
- package/types/crypto/hash.d.cts +118 -0
- package/types/crypto/index.d.cts +7 -0
- package/types/crypto/point.d.cts +134 -0
- package/types/crypto/random.d.cts +13 -0
- package/types/crypto/signature.d.cts +160 -0
- package/types/encoding/base58.d.cts +106 -0
- package/types/encoding/base58check.d.cts +107 -0
- package/types/encoding/bufferreader.d.cts +164 -0
- package/types/encoding/bufferwriter.d.cts +126 -0
- package/types/encoding/decode-asm.d.cts +2 -0
- package/types/encoding/decode-hex.d.cts +2 -0
- package/types/encoding/decode-script-chunks.d.cts +14 -0
- package/types/encoding/encode-hex.d.cts +2 -0
- package/types/encoding/index.d.cts +6 -0
- package/types/encoding/is-hex.d.cts +2 -0
- package/types/encoding/varint.d.cts +66 -0
- package/types/errors/index.d.cts +4 -0
- package/types/errors/spec.d.cts +22 -0
- package/types/hash-cache.d.cts +65 -0
- package/types/hdprivatekey.d.cts +281 -0
- package/types/hdpublickey.d.cts +240 -0
- package/types/index.d.cts +26 -0
- package/types/interpreter/index.d.cts +2 -0
- package/types/interpreter/interpreter.d.cts +228 -0
- package/types/interpreter/stack.d.cts +35 -0
- package/types/message/message.d.cts +110 -0
- package/types/mnemonic/index.d.cts +2 -0
- package/types/mnemonic/mnemonic.d.cts +171 -0
- package/types/mnemonic/pbkdf2.d.cts +14 -0
- package/types/mnemonic/words/chinese.d.cts +2 -0
- package/types/mnemonic/words/english.d.cts +2 -0
- package/types/mnemonic/words/french.d.cts +2 -0
- package/types/mnemonic/words/index.d.cts +22 -0
- package/types/mnemonic/words/italian.d.cts +2 -0
- package/types/mnemonic/words/japanese.d.cts +2 -0
- package/types/mnemonic/words/spanish.d.cts +2 -0
- package/types/network.d.cts +11 -0
- package/types/networks.d.cts +76 -0
- package/types/opcode.d.cts +93 -0
- package/types/privatekey.d.cts +169 -0
- package/types/publickey.d.cts +202 -0
- package/types/script/index.d.cts +2 -0
- package/types/script/script.d.cts +449 -0
- package/types/script/write-i32-le.d.cts +2 -0
- package/types/script/write-push-data.d.cts +2 -0
- package/types/script/write-u16-le.d.cts +2 -0
- package/types/script/write-u32-le.d.cts +2 -0
- package/types/script/write-u64-le.d.cts +2 -0
- package/types/script/write-u8-le.d.cts +2 -0
- package/types/script/write-varint.d.cts +2 -0
- package/types/transaction/index.d.cts +2 -0
- package/types/transaction/input/index.d.cts +2 -0
- package/types/transaction/input/input.d.cts +178 -0
- package/types/transaction/input/multisig.d.cts +127 -0
- package/types/transaction/input/publickey.d.cts +44 -0
- package/types/transaction/input/publickeyhash.d.cts +45 -0
- package/types/transaction/output.d.cts +118 -0
- package/types/transaction/sighash.d.cts +61 -0
- package/types/transaction/signature.d.cts +43 -0
- package/types/transaction/transaction.d.cts +716 -0
- package/types/transaction/unspentoutput.d.cts +83 -0
- package/types/util/_.d.cts +26 -0
- package/types/util/derivation.d.cts +21 -0
- package/types/util/index.d.cts +5 -0
- package/types/util/js.d.cts +50 -0
- package/types/util/preconditions.d.cts +3 -0
- package/index.d.ts +0 -1541
- package/index.js +0 -74
- package/lib/block/index.js +0 -4
- package/lib/bn.js +0 -3423
- package/lib/crypto/hash.js +0 -2
- package/lib/crypto/random.browser.js +0 -28
- package/lib/crypto/random.js +0 -2
- package/lib/crypto/random.node.js +0 -11
- package/lib/encoding/base58check.js +0 -121
- package/lib/encoding/bufferreader.js +0 -212
- package/lib/encoding/bufferwriter.js +0 -140
- package/lib/encoding/varint.js +0 -75
- package/lib/hash-cache.js +0 -50
- package/lib/mnemonic/pbkdf2.js +0 -2
- package/lib/mnemonic/words/index.js +0 -8
- package/lib/script/index.js +0 -5
- package/lib/transaction/index.js +0 -7
- package/lib/transaction/input/index.js +0 -5
- package/lib/util/js.js +0 -90
- /package/{lib/encoding/decode-script-chunks.js → cjs/encoding/decode-script-chunks.cjs} +0 -0
- /package/{lib/encoding/encode-hex.js → cjs/encoding/encode-hex.cjs} +0 -0
- /package/{lib/encoding/is-hex.js → cjs/encoding/is-hex.cjs} +0 -0
- /package/{lib/mnemonic/words/chinese.js → cjs/mnemonic/words/chinese.cjs} +0 -0
- /package/{lib/mnemonic/words/english.js → cjs/mnemonic/words/english.cjs} +0 -0
- /package/{lib/mnemonic/words/french.js → cjs/mnemonic/words/french.cjs} +0 -0
- /package/{lib/mnemonic/words/italian.js → cjs/mnemonic/words/italian.cjs} +0 -0
- /package/{lib/mnemonic/words/japanese.js → cjs/mnemonic/words/japanese.cjs} +0 -0
- /package/{lib/mnemonic/words/spanish.js → cjs/mnemonic/words/spanish.cjs} +0 -0
- /package/{lib/script/write-i32-le.js → cjs/script/write-i32-le.cjs} +0 -0
- /package/{lib/script/write-push-data.js → cjs/script/write-push-data.cjs} +0 -0
- /package/{lib/script/write-u16-le.js → cjs/script/write-u16-le.cjs} +0 -0
- /package/{lib/script/write-u32-le.js → cjs/script/write-u32-le.cjs} +0 -0
- /package/{lib/script/write-u64-le.js → cjs/script/write-u64-le.cjs} +0 -0
- /package/{lib/script/write-u8-le.js → cjs/script/write-u8-le.cjs} +0 -0
- /package/{lib/script/write-varint.js → cjs/script/write-varint.cjs} +0 -0
- /package/{lib/util/_.js → cjs/util/_.cjs} +0 -0
- /package/test/crypto/{bn.js → bn.cjs} +0 -0
- /package/test/crypto/{hash.js → hash.cjs} +0 -0
- /package/test/crypto/{point.js → point.cjs} +0 -0
- /package/test/crypto/{random.js → random.cjs} +0 -0
- /package/test/data/{blk86756-testnet.js → blk86756-testnet.cjs} +0 -0
- /package/test/data/{merkleblocks.js → merkleblocks.cjs} +0 -0
- /package/test/encoding/{base58.js → base58.cjs} +0 -0
- /package/test/encoding/{base58check.js → base58check.cjs} +0 -0
- /package/test/encoding/{bufferreader.js → bufferreader.cjs} +0 -0
- /package/test/encoding/{bufferwriter.js → bufferwriter.cjs} +0 -0
- /package/test/encoding/{varint.js → varint.cjs} +0 -0
- /package/test/{index.js → index.cjs} +0 -0
- /package/test/message/{message.js → message.cjs} +0 -0
- /package/test/mnemonic/{mnemonic.js → mnemonic.cjs} +0 -0
- /package/test/{opcode.js → opcode.cjs} +0 -0
- /package/test/{privatekey.js → privatekey.cjs} +0 -0
- /package/test/transaction/input/{publickey.js → publickey.cjs} +0 -0
- /package/test/transaction/{output.js → output.cjs} +0 -0
- /package/test/transaction/{signature.js → signature.cjs} +0 -0
- /package/test/transaction/{unspentoutput.js → unspentoutput.cjs} +0 -0
- /package/test/util/{js.js → js.cjs} +0 -0
- /package/test/util/{preconditions.js → preconditions.cjs} +0 -0
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
import _ from '../util/_.js';
|
|
4
|
+
import Script from '../script/index.js';
|
|
5
|
+
import Opcode from '../opcode.js';
|
|
6
|
+
import BN from '../crypto/bn.js';
|
|
7
|
+
import Hash from '../crypto/hash.js';
|
|
8
|
+
import Signature from '../crypto/signature.js';
|
|
9
|
+
import PublicKey from '../publickey.js';
|
|
10
|
+
import Stack from './stack.js';
|
|
11
|
+
import Transaction from '../transaction/index.js';
|
|
12
|
+
|
|
12
13
|
/**
|
|
13
14
|
* Bitcoin transactions contain scripts. Each input has a script called the
|
|
14
15
|
* scriptSig, and each output has a script called the scriptPubkey. To validate
|
|
@@ -18,8 +19,11 @@ var Stack = require('./stack');
|
|
|
18
19
|
*
|
|
19
20
|
* The primary way to use this class is via the verify function.
|
|
20
21
|
* e.g., Interpreter().verify( ... );
|
|
22
|
+
* @constructor
|
|
23
|
+
* @param {Object} [obj] - Optional object to initialize the interpreter with.
|
|
24
|
+
* @returns {Interpreter} A new Interpreter instance.
|
|
21
25
|
*/
|
|
22
|
-
|
|
26
|
+
function Interpreter(obj) {
|
|
23
27
|
if (!(this instanceof Interpreter)) {
|
|
24
28
|
return new Interpreter(obj);
|
|
25
29
|
}
|
|
@@ -29,7 +33,7 @@ var Interpreter = function Interpreter(obj) {
|
|
|
29
33
|
} else {
|
|
30
34
|
this.initialize();
|
|
31
35
|
}
|
|
32
|
-
}
|
|
36
|
+
}
|
|
33
37
|
|
|
34
38
|
/**
|
|
35
39
|
* Verifies a Script by executing it and returns true if it is valid.
|
|
@@ -53,7 +57,6 @@ Interpreter.prototype.verify = function (
|
|
|
53
57
|
flags,
|
|
54
58
|
satoshisBN,
|
|
55
59
|
) {
|
|
56
|
-
var Transaction = require('../transaction');
|
|
57
60
|
|
|
58
61
|
if (_.isUndefined(tx)) {
|
|
59
62
|
tx = new Transaction();
|
|
@@ -113,9 +116,13 @@ Interpreter.prototype.verify = function (
|
|
|
113
116
|
return true;
|
|
114
117
|
};
|
|
115
118
|
|
|
116
|
-
module.exports = Interpreter;
|
|
117
119
|
|
|
118
|
-
|
|
120
|
+
/**
|
|
121
|
+
* Initializes the interpreter instance with default values.
|
|
122
|
+
* Sets up empty stacks, resets program counter and execution flags,
|
|
123
|
+
* and initializes state tracking variables for script execution.
|
|
124
|
+
*/
|
|
125
|
+
Interpreter.prototype.initialize = function () {
|
|
119
126
|
this.stack = new Stack([]);
|
|
120
127
|
this.altstack = new Stack([]);
|
|
121
128
|
this.pc = 0;
|
|
@@ -131,6 +138,23 @@ Interpreter.prototype.initialize = function (obj) {
|
|
|
131
138
|
this.returned = false;
|
|
132
139
|
};
|
|
133
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Updates the interpreter's state with provided values.
|
|
143
|
+
* @param {Object} obj - Object containing properties to update
|
|
144
|
+
* @param {Buffer} [obj.script] - Script buffer
|
|
145
|
+
* @param {Object} [obj.tx] - Transaction object
|
|
146
|
+
* @param {boolean} [obj.nin] - Non-input flag
|
|
147
|
+
* @param {BN} [obj.satoshisBN] - Satoshis as BN.js instance
|
|
148
|
+
* @param {Array} [obj.stack] - Main stack
|
|
149
|
+
* @param {Array} [obj.altstack] - Alternate stack
|
|
150
|
+
* @param {number} [obj.pc] - Program counter
|
|
151
|
+
* @param {number} [obj.pbegincodehash] - Begin code hash position
|
|
152
|
+
* @param {number} [obj.nOpCount] - Operation count
|
|
153
|
+
* @param {Array} [obj.vfExec] - Execution flags
|
|
154
|
+
* @param {Array} [obj.vfElse] - Else flags
|
|
155
|
+
* @param {string} [obj.errstr] - Error string
|
|
156
|
+
* @param {number} [obj.flags] - Interpreter flags
|
|
157
|
+
*/
|
|
134
158
|
Interpreter.prototype.set = function (obj) {
|
|
135
159
|
this.script = obj.script || this.script;
|
|
136
160
|
this.tx = obj.tx || this.tx;
|
|
@@ -148,8 +172,12 @@ Interpreter.prototype.set = function (obj) {
|
|
|
148
172
|
this.flags = typeof obj.flags !== 'undefined' ? obj.flags : this.flags;
|
|
149
173
|
};
|
|
150
174
|
|
|
175
|
+
/**
|
|
176
|
+
* Returns a subset of the script starting from the most recent OP_CODESEPARATOR.
|
|
177
|
+
* @returns {Script} A new Script instance containing the sliced chunks.
|
|
178
|
+
*/
|
|
151
179
|
Interpreter.prototype.subscript = function () {
|
|
152
|
-
|
|
180
|
+
// Subset of script starting at the most recent codeseparator
|
|
153
181
|
// CScript scriptCode(pbegincodehash, pend);
|
|
154
182
|
return Script.fromChunks(this.script.chunks.slice(this.pbegincodehash));
|
|
155
183
|
};
|
|
@@ -157,79 +185,133 @@ Interpreter.prototype.subscript = function () {
|
|
|
157
185
|
Interpreter.getTrue = () => Buffer.from([1]);
|
|
158
186
|
Interpreter.getFalse = () => Buffer.from([]);
|
|
159
187
|
|
|
160
|
-
|
|
188
|
+
/**
|
|
189
|
+
* Maximum allowed size for script elements in the interpreter.
|
|
190
|
+
* Set to the maximum safe integer value by default.
|
|
191
|
+
*/
|
|
192
|
+
Interpreter.MAX_SCRIPT_ELEMENT_SIZE = Number.MAX_SAFE_INTEGER;
|
|
193
|
+
/**
|
|
194
|
+
* The maximum allowed size for an element in the interpreter.
|
|
195
|
+
* @type {number}
|
|
196
|
+
*/
|
|
161
197
|
Interpreter.MAXIMUM_ELEMENT_SIZE = Number.MAX_SAFE_INTEGER;
|
|
162
198
|
|
|
199
|
+
/**
|
|
200
|
+
* The threshold value used to distinguish between block height and timestamp in locktime.
|
|
201
|
+
* Values below this threshold are interpreted as block numbers, while values equal or above are treated as timestamps.
|
|
202
|
+
*/
|
|
163
203
|
Interpreter.LOCKTIME_THRESHOLD = 500000000;
|
|
204
|
+
/**
|
|
205
|
+
* The locktime threshold value as a BN.js BigNumber instance.
|
|
206
|
+
* @type {BN}
|
|
207
|
+
*/
|
|
164
208
|
Interpreter.LOCKTIME_THRESHOLD_BN = new BN(Interpreter.LOCKTIME_THRESHOLD);
|
|
165
209
|
|
|
166
|
-
|
|
167
|
-
|
|
210
|
+
/**
|
|
211
|
+
* Flag indicating no script verification rules should be enforced.
|
|
212
|
+
* flags taken from bitcoind
|
|
213
|
+
* bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104
|
|
214
|
+
* @constant {number}
|
|
215
|
+
*/
|
|
168
216
|
Interpreter.SCRIPT_VERIFY_NONE = 0;
|
|
169
217
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
218
|
+
/**
|
|
219
|
+
* Passing a non-strict-DER signature or one with undefined hashtype to a checksig operation causes script failure.
|
|
220
|
+
* Passing a pubkey that is not (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) to checksig causes that pubkey to be
|
|
221
|
+
* skipped (not softfork safe: this flag can widen the validity of OP_CHECKSIG OP_NOT).
|
|
222
|
+
*/
|
|
173
223
|
Interpreter.SCRIPT_VERIFY_STRICTENC = 1 << 1;
|
|
174
224
|
|
|
175
|
-
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Passing a non-strict-DER signature to a checksig operation causes script failure (softfork safe, BIP62 rule 1)
|
|
228
|
+
*/
|
|
176
229
|
Interpreter.SCRIPT_VERIFY_DERSIG = 1 << 2;
|
|
177
230
|
|
|
178
|
-
|
|
179
|
-
|
|
231
|
+
/**
|
|
232
|
+
* Passing a non-strict-DER signature or one with S > order/2 to a checksig operation causes script failure
|
|
233
|
+
* (softfork safe, BIP62 rule 5).
|
|
234
|
+
*/
|
|
180
235
|
Interpreter.SCRIPT_VERIFY_LOW_S = 1 << 3;
|
|
181
236
|
|
|
182
|
-
|
|
237
|
+
/**
|
|
238
|
+
* verify dummy stack item consumed by CHECKMULTISIG is of zero-length (softfork safe, BIP62 rule 7).
|
|
239
|
+
*/
|
|
183
240
|
Interpreter.SCRIPT_VERIFY_NULLDUMMY = 1 << 4;
|
|
184
241
|
|
|
185
|
-
|
|
242
|
+
/**
|
|
243
|
+
* Using a non-push operator in the scriptSig causes script failure (softfork safe, BIP62 rule 2).
|
|
244
|
+
*/
|
|
186
245
|
Interpreter.SCRIPT_VERIFY_SIGPUSHONLY = 1 << 5;
|
|
187
246
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
247
|
+
/**
|
|
248
|
+
* Require minimal encodings for all push operations (OP_0... OP_16, OP_1NEGATE where possible, direct
|
|
249
|
+
* pushes up to 75 bytes, OP_PUSHDATA up to 255 bytes, OP_PUSHDATA2 for anything larger). Evaluating
|
|
250
|
+
* any other push causes the script to fail (BIP62 rule 3).
|
|
251
|
+
* In addition, whenever a stack element is interpreted as a number, it must be of minimal length (BIP62 rule 4).
|
|
252
|
+
* (softfork safe)
|
|
253
|
+
*
|
|
254
|
+
*/
|
|
193
255
|
Interpreter.SCRIPT_VERIFY_MINIMALDATA = 1 << 6;
|
|
194
256
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
257
|
+
/**
|
|
258
|
+
* Discourage use of NOPs reserved for upgrades (NOP1-10)
|
|
259
|
+
*
|
|
260
|
+
* Provided so that nodes can avoid accepting or mining transactions
|
|
261
|
+
* containing executed NOP's whose meaning may change after a soft-fork,
|
|
262
|
+
* thus rendering the script invalid; with this flag set executing
|
|
263
|
+
* discouraged NOPs fails the script. This verification flag will never be
|
|
264
|
+
* a mandatory flag applied to scripts in a block. NOPs that are not
|
|
265
|
+
* executed, e.g. within an unexecuted IF ENDIF block, are *not* rejected.
|
|
266
|
+
*/
|
|
203
267
|
Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = 1 << 7;
|
|
204
268
|
|
|
205
269
|
|
|
206
|
-
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* CLTV See BIP65 for details.
|
|
273
|
+
*/
|
|
207
274
|
Interpreter.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = 1 << 9;
|
|
208
275
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
276
|
+
/**
|
|
277
|
+
* support CHECKSEQUENCEVERIFY opcode
|
|
278
|
+
* See BIP112 for details
|
|
279
|
+
*/
|
|
212
280
|
Interpreter.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY = 1 << 10;
|
|
213
281
|
|
|
214
|
-
|
|
215
|
-
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Flag indicating that script verification should fail if a null input is encountered.
|
|
285
|
+
* This is a bitmask value (1 << 14) used in script verification rules.
|
|
286
|
+
*/
|
|
216
287
|
Interpreter.SCRIPT_VERIFY_NULLFAIL = 1 << 14;
|
|
217
288
|
|
|
218
|
-
|
|
289
|
+
/**
|
|
290
|
+
* Flag indicating that compressed public key type should be verified in scripts.
|
|
291
|
+
* This is a bit flag used in script verification (1 << 15).
|
|
292
|
+
* @type {number}
|
|
293
|
+
*/
|
|
219
294
|
Interpreter.SCRIPT_VERIFY_COMPRESSED_PUBKEYTYPE = 1 << 15;
|
|
220
295
|
|
|
221
|
-
|
|
222
|
-
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Enable new opcodes.
|
|
299
|
+
* @type {number}
|
|
300
|
+
*/
|
|
223
301
|
Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES = 1 << 18;
|
|
224
302
|
|
|
225
|
-
|
|
226
|
-
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Are the Magnetic upgrade opcodes enabled?
|
|
306
|
+
* @type {number}
|
|
307
|
+
*/
|
|
227
308
|
Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES = 1 << 19;
|
|
228
309
|
|
|
229
310
|
/* Below flags apply in the context of BIP 68 */
|
|
230
311
|
/**
|
|
231
312
|
* If this flag set, CTxIn::nSequence is NOT interpreted as a relative
|
|
232
313
|
* lock-time.
|
|
314
|
+
* @type {number}
|
|
233
315
|
*/
|
|
234
316
|
Interpreter.SEQUENCE_LOCKTIME_DISABLE_FLAG = 1 << 31;
|
|
235
317
|
|
|
@@ -237,19 +319,34 @@ Interpreter.SEQUENCE_LOCKTIME_DISABLE_FLAG = 1 << 31;
|
|
|
237
319
|
* If CTxIn::nSequence encodes a relative lock-time and this flag is set,
|
|
238
320
|
* the relative lock-time has units of 512 seconds, otherwise it specifies
|
|
239
321
|
* blocks with a granularity of 1.
|
|
322
|
+
* @type {number}
|
|
240
323
|
*/
|
|
241
324
|
Interpreter.SEQUENCE_LOCKTIME_TYPE_FLAG = 1 << 22;
|
|
242
325
|
|
|
243
326
|
/**
|
|
244
327
|
* If CTxIn::nSequence encodes a relative lock-time, this mask is applied to
|
|
245
328
|
* extract that lock-time from the sequence field.
|
|
329
|
+
* @type {number}
|
|
246
330
|
*/
|
|
247
331
|
Interpreter.SEQUENCE_LOCKTIME_MASK = 0x0000ffff;
|
|
248
332
|
|
|
333
|
+
/**
|
|
334
|
+
* Maximum allowed script size for the interpreter, set to the largest safe integer in JavaScript.
|
|
335
|
+
* @type {number}
|
|
336
|
+
*/
|
|
249
337
|
Interpreter.MAX_SCRIPT_SIZE = Number.MAX_SAFE_INTEGER;
|
|
250
338
|
|
|
339
|
+
/**
|
|
340
|
+
* Maximum number of opcodes that can be executed before stopping the interpreter.
|
|
341
|
+
* Defaults to Number.MAX_SAFE_INTEGER (effectively unlimited).
|
|
342
|
+
* @type {number}
|
|
343
|
+
*/
|
|
251
344
|
Interpreter.MAX_OPCODE_COUNT = Number.MAX_SAFE_INTEGER;
|
|
252
345
|
|
|
346
|
+
/**
|
|
347
|
+
* Default flags used by the interpreter.
|
|
348
|
+
* @type {number}
|
|
349
|
+
*/
|
|
253
350
|
Interpreter.DEFAULT_FLAGS =
|
|
254
351
|
Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES |
|
|
255
352
|
Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES |
|
|
@@ -263,6 +360,14 @@ Interpreter.DEFAULT_FLAGS =
|
|
|
263
360
|
Interpreter.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY |
|
|
264
361
|
Interpreter.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY;
|
|
265
362
|
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Casts a buffer to a boolean value.
|
|
366
|
+
* Returns true if any byte in the buffer is non-zero (except for the special case of negative zero).
|
|
367
|
+
* Returns false if all bytes are zero or if the last byte is 0x80 (negative zero case).
|
|
368
|
+
* @param {Buffer} buf - The input buffer to check
|
|
369
|
+
* @returns {boolean} The boolean representation of the buffer
|
|
370
|
+
*/
|
|
266
371
|
Interpreter.castToBool = function (buf) {
|
|
267
372
|
for (var i = 0; i < buf.length; i++) {
|
|
268
373
|
if (buf[i] !== 0) {
|
|
@@ -276,8 +381,15 @@ Interpreter.castToBool = function (buf) {
|
|
|
276
381
|
return false;
|
|
277
382
|
};
|
|
278
383
|
|
|
384
|
+
|
|
279
385
|
/**
|
|
280
|
-
*
|
|
386
|
+
* Checks if a signature encoding is valid according to the interpreter's flags.
|
|
387
|
+
* - For empty signatures: always valid (used for compact invalid signatures in CHECK(MULTI)SIG)
|
|
388
|
+
* - With DERSIG/STRICTENC flags: validates DER encoding and strict encoding rules
|
|
389
|
+
* - With LOW_S flag: ensures signature uses low S value
|
|
390
|
+
* - With STRICTENC flag: validates defined hash type
|
|
391
|
+
* @param {Buffer} buf - The signature buffer to validate
|
|
392
|
+
* @returns {boolean} True if valid, false otherwise (sets errstr on failure)
|
|
281
393
|
*/
|
|
282
394
|
Interpreter.prototype.checkSignatureEncoding = function (buf) {
|
|
283
395
|
var sig;
|
|
@@ -315,8 +427,12 @@ Interpreter.prototype.checkSignatureEncoding = function (buf) {
|
|
|
315
427
|
return true;
|
|
316
428
|
};
|
|
317
429
|
|
|
430
|
+
|
|
318
431
|
/**
|
|
319
|
-
*
|
|
432
|
+
* Checks if the provided public key buffer is valid according to strict encoding rules.
|
|
433
|
+
* Sets an error message if validation fails under SCRIPT_VERIFY_STRICTENC flag.
|
|
434
|
+
* @param {Buffer} buf - The public key buffer to validate.
|
|
435
|
+
* @returns {boolean} True if valid, false otherwise (with error string set).
|
|
320
436
|
*/
|
|
321
437
|
Interpreter.prototype.checkPubkeyEncoding = function (buf) {
|
|
322
438
|
if ((this.flags & Interpreter.SCRIPT_VERIFY_STRICTENC) !== 0 && !PublicKey.isValid(buf)) {
|
|
@@ -327,12 +443,12 @@ Interpreter.prototype.checkPubkeyEncoding = function (buf) {
|
|
|
327
443
|
};
|
|
328
444
|
|
|
329
445
|
/**
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
*
|
|
333
|
-
*
|
|
446
|
+
* Checks if a buffer is minimally encoded (see https://github.com/bitcoincashorg/spec/blob/master/may-2018-reenabled-opcodes.md#op_bin2num) as a number.
|
|
447
|
+
* @param {Buffer} buf - The buffer to check.
|
|
448
|
+
* @param {number} [nMaxNumSize=Interpreter.MAXIMUM_ELEMENT_SIZE] - Maximum allowed size for the buffer.
|
|
449
|
+
* @returns {boolean} True if the buffer is minimally encoded, false otherwise.
|
|
450
|
+
* @private
|
|
334
451
|
*/
|
|
335
|
-
|
|
336
452
|
Interpreter._isMinimallyEncoded = function (buf, nMaxNumSize) {
|
|
337
453
|
nMaxNumSize = nMaxNumSize || Interpreter.MAXIMUM_ELEMENT_SIZE;
|
|
338
454
|
if (buf.length > nMaxNumSize) {
|
|
@@ -360,11 +476,18 @@ Interpreter._isMinimallyEncoded = function (buf, nMaxNumSize) {
|
|
|
360
476
|
return true;
|
|
361
477
|
};
|
|
362
478
|
|
|
479
|
+
|
|
363
480
|
/**
|
|
364
|
-
*
|
|
365
|
-
*
|
|
366
|
-
*
|
|
367
|
-
*
|
|
481
|
+
* Minimally encodes a buffer by removing unnecessary trailing zeros.
|
|
482
|
+
*
|
|
483
|
+
* This function implements minimal encoding rules for script numbers:
|
|
484
|
+
* - Empty buffer remains empty
|
|
485
|
+
* - Last byte must not be 0x00 or 0x80 unless necessary
|
|
486
|
+
* - Single zero byte encodes as empty buffer
|
|
487
|
+
* - Preserves sign bit when trimming
|
|
488
|
+
*
|
|
489
|
+
* @param {Buffer} buf - The input buffer to encode
|
|
490
|
+
* @returns {Buffer} Minimally encoded buffer (may be empty)
|
|
368
491
|
*/
|
|
369
492
|
Interpreter._minimallyEncode = function (buf) {
|
|
370
493
|
if (buf.length === 0) {
|
|
@@ -409,13 +532,19 @@ Interpreter._minimallyEncode = function (buf) {
|
|
|
409
532
|
return Buffer.from('');
|
|
410
533
|
};
|
|
411
534
|
|
|
535
|
+
|
|
412
536
|
/**
|
|
413
|
-
*
|
|
414
|
-
*
|
|
537
|
+
* Evaluates a script by executing each opcode step-by-step.
|
|
538
|
+
* Performs size checks on the script and stacks before execution.
|
|
539
|
+
*
|
|
540
|
+
* Based on bitcoind's EvalScript function, with the inner loop moved to `Interpreter.prototype.step()`
|
|
415
541
|
* bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104
|
|
542
|
+
* @param {string} scriptType - The type of script being evaluated
|
|
543
|
+
* @returns {boolean} True if evaluation succeeds, false if any error occurs
|
|
544
|
+
* @throws {Error} If an unknown error occurs during evaluation
|
|
416
545
|
*/
|
|
417
546
|
Interpreter.prototype.evaluate = function (scriptType) {
|
|
418
|
-
|
|
547
|
+
// TODO: script size should be configurable. no magic numbers
|
|
419
548
|
if (this.script.toBuffer().length > Interpreter.MAX_SCRIPT_SIZE) {
|
|
420
549
|
this.errstr = 'SCRIPT_ERR_SCRIPT_SIZE';
|
|
421
550
|
return false;
|
|
@@ -457,6 +586,12 @@ Interpreter.prototype.evaluate = function (scriptType) {
|
|
|
457
586
|
return true;
|
|
458
587
|
};
|
|
459
588
|
|
|
589
|
+
/**
|
|
590
|
+
* Handles step callback execution for the interpreter.
|
|
591
|
+
* @private
|
|
592
|
+
* @param {Object} thisStep - The current step object to pass to the listener
|
|
593
|
+
* @throws {Error} Logs any errors that occur during callback execution
|
|
594
|
+
*/
|
|
460
595
|
Interpreter.prototype._callbackStep = function (thisStep) {
|
|
461
596
|
if (typeof this.stepListener === 'function') {
|
|
462
597
|
try {
|
|
@@ -467,9 +602,14 @@ Interpreter.prototype._callbackStep = function (thisStep) {
|
|
|
467
602
|
}
|
|
468
603
|
};
|
|
469
604
|
|
|
605
|
+
|
|
470
606
|
/**
|
|
471
|
-
*
|
|
472
|
-
*
|
|
607
|
+
* Handles stack callbacks by invoking the registered stack listener function.
|
|
608
|
+
* If an error occurs during callback execution, logs the error along with PC and opcode details.
|
|
609
|
+
* @param {Stack} stack - The current execution stack
|
|
610
|
+
* @param {number} pc - Program counter value
|
|
611
|
+
* @param {string} scriptType - Type of script being executed
|
|
612
|
+
* @private
|
|
473
613
|
*/
|
|
474
614
|
Interpreter.prototype._callbackStack = function (stack, pc, scriptType) {
|
|
475
615
|
if (typeof this.stackListener === 'function') {
|
|
@@ -603,9 +743,19 @@ function padBufferToSize(buf, len) {
|
|
|
603
743
|
return b;
|
|
604
744
|
}
|
|
605
745
|
|
|
746
|
+
|
|
606
747
|
/**
|
|
748
|
+
* Executes a single step in the script interpreter.
|
|
749
|
+
*
|
|
750
|
+
* This method processes the current opcode in the script, performs the corresponding operation,
|
|
751
|
+
* and updates the stack or interpreter state accordingly. It handles various opcode types including
|
|
752
|
+
* stack operations, arithmetic, bitwise logic, cryptographic operations, and control flow.
|
|
753
|
+
*
|
|
607
754
|
* Based on the inner loop of bitcoind's EvalScript function
|
|
608
755
|
* bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104
|
|
756
|
+
* @param {string} scriptType - The type of script being executed (e.g., scriptPubkey, scriptSig).
|
|
757
|
+
* @returns {boolean} Returns `true` if the step executed successfully, or `false` if an error occurred.
|
|
758
|
+
* Errors are stored in `this.errstr`.
|
|
609
759
|
*/
|
|
610
760
|
Interpreter.prototype.step = function (scriptType) {
|
|
611
761
|
var self = this;
|
|
@@ -1832,3 +1982,6 @@ Interpreter.prototype.step = function (scriptType) {
|
|
|
1832
1982
|
|
|
1833
1983
|
return true;
|
|
1834
1984
|
};
|
|
1985
|
+
|
|
1986
|
+
|
|
1987
|
+
export default Interpreter;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Represents a stack structure with optional variable stack support.
|
|
5
|
+
* @constructor
|
|
6
|
+
* @param {Array} rawstack - The initial stack array
|
|
7
|
+
* @param {Array} [varStack] - Optional variable stack array
|
|
8
|
+
*/
|
|
9
|
+
function Stack(rawstack, varStack) {
|
|
10
|
+
this.stack = rawstack;
|
|
11
|
+
this.varStack = varStack || [];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
Stack.prototype.pushVar = function (varName) {
|
|
16
|
+
this.varStack.push(varName || '$tmp');
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
Stack.prototype.popVar = function () {
|
|
20
|
+
this.varStack.pop();
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
Stack.prototype.push = function (n, varName) {
|
|
24
|
+
this.pushVar(varName);
|
|
25
|
+
this.stack.push(n);
|
|
26
|
+
this.checkConsistency();
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
Stack.prototype.pop = function () {
|
|
30
|
+
this.popVar();
|
|
31
|
+
let top = this.stack.pop();
|
|
32
|
+
this.checkConsistency();
|
|
33
|
+
return top;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
Stack.prototype.updateTopVars = function (vars) {
|
|
37
|
+
if (vars.length > this.varStack.length) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
`updateTopVars fail, stack: ${this.stack.length}, varStack: ${this.varStack.length}, vars:${vars.length}`,
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
vars = vars.reverse();
|
|
43
|
+
this.varStack.splice(this.varStack.length - vars.length, vars.length, ...vars);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
Stack.prototype.stacktop = function (i) {
|
|
47
|
+
return this.stack[this.stack.length + i];
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
Stack.prototype.vartop = function (i) {
|
|
51
|
+
return this.varStack[this.varStack.length + i];
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
Stack.prototype.slice = function (start, end) {
|
|
55
|
+
return this.stack.slice(start, end);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
Stack.prototype.splice = function (start, deleteCount, ...items) {
|
|
59
|
+
this.varStack.splice(start, deleteCount, ...items);
|
|
60
|
+
return this.stack.splice(start, deleteCount, ...items);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
Stack.prototype.write = function (i, value) {
|
|
64
|
+
this.stack[this.stack.length + i] = value;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
Stack.prototype.copy = function () {
|
|
68
|
+
return new Stack(this.stack.slice() || [], this.varStack.slice() || []);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
function bytesToHexString(bytearray) {
|
|
72
|
+
return bytearray.reduce(function (o, c) {
|
|
73
|
+
o += ('0' + (c & 0xff).toString(16)).slice(-2);
|
|
74
|
+
return o;
|
|
75
|
+
}, '');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
Stack.prototype.printVarStack = function () {
|
|
79
|
+
let array = this.varStack.map((v, i) => ({
|
|
80
|
+
name: v,
|
|
81
|
+
value: bytesToHexString(this.rawstack[i].data),
|
|
82
|
+
}));
|
|
83
|
+
console.log(JSON.stringify(array, null, 4));
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
Stack.prototype.checkConsistency = function () {
|
|
87
|
+
if (this.stack.length !== this.varStack.length) {
|
|
88
|
+
this.printVarStack();
|
|
89
|
+
throw new Error(
|
|
90
|
+
`checkConsistency fail, stack: ${this.stack.length}, varStack:${this.varStack.length}`,
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
Stack.prototype.checkConsistencyWithVars = function (varStack) {
|
|
96
|
+
if (this.stack.length < varStack.length) {
|
|
97
|
+
this.printVarStack();
|
|
98
|
+
throw new Error(
|
|
99
|
+
`checkConsistencyWithVars fail, stack: ${this.stack.length}, varStack:${varStack.length}`,
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
Object.defineProperty(Stack.prototype, 'length', {
|
|
105
|
+
get: function () {
|
|
106
|
+
return this.stack.length;
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
Object.defineProperty(Stack.prototype, 'rawstack', {
|
|
111
|
+
get: function () {
|
|
112
|
+
return this.stack;
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
export default Stack;
|