@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.
Files changed (293) hide show
  1. package/.cjs2esm.json +18 -0
  2. package/.mocharc.yaml +1 -1
  3. package/CHANGELOG.md +13 -0
  4. package/README.md +6 -0
  5. package/{lib/address.js → cjs/address.cjs} +77 -72
  6. package/cjs/block/block.cjs +332 -0
  7. package/{lib/block/blockheader.js → cjs/block/blockheader.cjs} +8 -7
  8. package/cjs/block/index.cjs +2 -0
  9. package/{lib/block/merkleblock.js → cjs/block/merkleblock.cjs} +23 -15
  10. package/cjs/bn.cjs +3411 -0
  11. package/{lib/crypto/bn.js → cjs/crypto/bn.cjs} +3 -3
  12. package/{lib/crypto/ecdsa.js → cjs/crypto/ecdsa.cjs} +150 -14
  13. package/{lib/crypto/hash.node.js → cjs/crypto/hash.cjs} +13 -2
  14. package/cjs/crypto/index.cjs +16 -0
  15. package/{lib/crypto/point.js → cjs/crypto/point.cjs} +11 -4
  16. package/cjs/crypto/random.cjs +18 -0
  17. package/{lib/crypto/signature.js → cjs/crypto/signature.cjs} +158 -8
  18. package/{lib/encoding/base58.js → cjs/encoding/base58.cjs} +58 -2
  19. package/cjs/encoding/base58check.cjs +192 -0
  20. package/cjs/encoding/bufferreader.cjs +333 -0
  21. package/cjs/encoding/bufferwriter.cjs +244 -0
  22. package/{lib/encoding/decode-asm.js → cjs/encoding/decode-asm.cjs} +4 -4
  23. package/{lib/encoding/decode-hex.js → cjs/encoding/decode-hex.cjs} +1 -1
  24. package/cjs/encoding/index.cjs +14 -0
  25. package/cjs/encoding/varint.cjs +116 -0
  26. package/{lib/errors/index.js → cjs/errors/index.cjs} +9 -9
  27. package/{lib/errors/spec.js → cjs/errors/spec.cjs} +2 -2
  28. package/cjs/hash-cache.cjs +98 -0
  29. package/{lib/hdprivatekey.js → cjs/hdprivatekey.cjs} +232 -140
  30. package/{lib/hdpublickey.js → cjs/hdpublickey.cjs} +120 -93
  31. package/cjs/index.cjs +94 -0
  32. package/cjs/interpreter/index.cjs +2 -0
  33. package/cjs/interpreter/interpreter.cjs +1988 -0
  34. package/{lib/script/stack.js → cjs/interpreter/stack.cjs} +9 -2
  35. package/{lib/message/message.js → cjs/message/message.cjs} +62 -25
  36. package/cjs/mnemonic/index.cjs +3 -0
  37. package/{lib/mnemonic/mnemonic.js → cjs/mnemonic/mnemonic.cjs} +44 -13
  38. package/{lib/mnemonic/pbkdf2.node.js → cjs/mnemonic/pbkdf2.cjs} +9 -2
  39. package/cjs/mnemonic/words/index.cjs +66 -0
  40. package/cjs/network.cjs +13 -0
  41. package/cjs/networks.cjs +321 -0
  42. package/{lib/opcode.js → cjs/opcode.cjs} +69 -5
  43. package/cjs/privatekey.cjs +422 -0
  44. package/{lib/publickey.js → cjs/publickey.cjs} +14 -16
  45. package/cjs/script/index.cjs +2 -0
  46. package/{lib/script/script.js → cjs/script/script.cjs} +322 -67
  47. package/cjs/transaction/index.cjs +5 -0
  48. package/cjs/transaction/input/index.cjs +34 -0
  49. package/cjs/transaction/input/input.cjs +396 -0
  50. package/{lib/transaction/input/multisig.js → cjs/transaction/input/multisig.cjs} +112 -18
  51. package/{lib/transaction/input/publickey.js → cjs/transaction/input/publickey.cjs} +29 -19
  52. package/{lib/transaction/input/publickeyhash.js → cjs/transaction/input/publickeyhash.cjs} +25 -17
  53. package/{lib/transaction/output.js → cjs/transaction/output.cjs} +100 -15
  54. package/cjs/transaction/sighash.cjs +187 -0
  55. package/{lib/transaction/signature.js → cjs/transaction/signature.cjs} +30 -6
  56. package/cjs/transaction/transaction.cjs +2000 -0
  57. package/{lib/transaction/unspentoutput.js → cjs/transaction/unspentoutput.cjs} +5 -5
  58. package/cjs/util/derivation.cjs +53 -0
  59. package/cjs/util/index.cjs +11 -0
  60. package/cjs/util/js.cjs +95 -0
  61. package/{lib/util/preconditions.js → cjs/util/preconditions.cjs} +2 -2
  62. package/esm/address.js +483 -0
  63. package/{lib → esm}/block/block.js +82 -27
  64. package/esm/block/blockheader.js +296 -0
  65. package/esm/block/index.js +2 -0
  66. package/esm/block/merkleblock.js +331 -0
  67. package/esm/bn.js +3411 -0
  68. package/esm/crypto/bn.js +278 -0
  69. package/esm/crypto/ecdsa.js +475 -0
  70. package/{lib/crypto/hash.browser.js → esm/crypto/hash.js} +18 -7
  71. package/esm/crypto/index.js +16 -0
  72. package/esm/crypto/point.js +228 -0
  73. package/esm/crypto/random.js +18 -0
  74. package/esm/crypto/signature.js +475 -0
  75. package/esm/encoding/base58.js +167 -0
  76. package/esm/encoding/base58check.js +192 -0
  77. package/esm/encoding/bufferreader.js +333 -0
  78. package/esm/encoding/bufferwriter.js +243 -0
  79. package/esm/encoding/decode-asm.js +24 -0
  80. package/esm/encoding/decode-hex.js +32 -0
  81. package/esm/encoding/decode-script-chunks.js +43 -0
  82. package/esm/encoding/encode-hex.js +284 -0
  83. package/esm/encoding/index.js +14 -0
  84. package/esm/encoding/is-hex.js +7 -0
  85. package/esm/encoding/varint.js +116 -0
  86. package/esm/errors/index.js +54 -0
  87. package/esm/errors/spec.js +314 -0
  88. package/esm/hash-cache.js +98 -0
  89. package/esm/hdprivatekey.js +768 -0
  90. package/esm/hdpublickey.js +549 -0
  91. package/esm/index.js +66 -0
  92. package/esm/interpreter/index.js +2 -0
  93. package/{lib/script → esm/interpreter}/interpreter.js +219 -66
  94. package/esm/interpreter/stack.js +116 -0
  95. package/esm/message/message.js +228 -0
  96. package/esm/mnemonic/index.js +3 -0
  97. package/esm/mnemonic/mnemonic.js +332 -0
  98. package/{lib/mnemonic/pbkdf2.browser.js → esm/mnemonic/pbkdf2.js} +13 -6
  99. package/esm/mnemonic/words/chinese.js +2054 -0
  100. package/esm/mnemonic/words/english.js +2054 -0
  101. package/esm/mnemonic/words/french.js +2054 -0
  102. package/esm/mnemonic/words/index.js +66 -0
  103. package/esm/mnemonic/words/italian.js +2054 -0
  104. package/esm/mnemonic/words/japanese.js +2054 -0
  105. package/esm/mnemonic/words/spanish.js +2054 -0
  106. package/esm/network.js +13 -0
  107. package/{lib → esm}/networks.js +61 -120
  108. package/esm/opcode.js +319 -0
  109. package/{lib → esm}/privatekey.js +76 -28
  110. package/esm/publickey.js +384 -0
  111. package/esm/script/index.js +2 -0
  112. package/esm/script/script.js +1329 -0
  113. package/esm/script/write-i32-le.js +17 -0
  114. package/esm/script/write-push-data.js +35 -0
  115. package/esm/script/write-u16-le.js +12 -0
  116. package/esm/script/write-u32-le.js +16 -0
  117. package/esm/script/write-u64-le.js +24 -0
  118. package/esm/script/write-u8-le.js +8 -0
  119. package/esm/script/write-varint.js +46 -0
  120. package/esm/transaction/index.js +5 -0
  121. package/esm/transaction/input/index.js +33 -0
  122. package/{lib → esm}/transaction/input/input.js +132 -90
  123. package/esm/transaction/input/multisig.js +335 -0
  124. package/esm/transaction/input/publickey.js +108 -0
  125. package/esm/transaction/input/publickeyhash.js +124 -0
  126. package/esm/transaction/output.js +316 -0
  127. package/{lib → esm}/transaction/sighash.js +42 -22
  128. package/esm/transaction/signature.js +120 -0
  129. package/{lib → esm}/transaction/transaction.js +522 -163
  130. package/esm/transaction/unspentoutput.js +112 -0
  131. package/esm/util/_.js +47 -0
  132. package/esm/util/derivation.js +53 -0
  133. package/esm/util/index.js +12 -0
  134. package/esm/util/js.js +95 -0
  135. package/esm/util/preconditions.js +33 -0
  136. package/fixup.cjs +17 -0
  137. package/package.json +40 -26
  138. package/test/{address.js → address.cjs} +14 -43
  139. package/test/block/{block.js → block.cjs} +3 -5
  140. package/test/block/{blockheader.js → blockheader.cjs} +2 -2
  141. package/test/block/{merklebloack.js → merklebloack.cjs} +2 -2
  142. package/test/crypto/{ecdsa.js → ecdsa.cjs} +9 -9
  143. package/test/crypto/{hash.browser.js → hash.browser.cjs} +2 -1
  144. package/test/crypto/{signature.js → signature.cjs} +2 -2
  145. package/test/data/bitcoind/script_tests.json +5 -5
  146. package/test/{hashCache.js → hashCache.cjs} +2 -1
  147. package/test/{hdkeys.js → hdkeys.cjs} +4 -2
  148. package/test/{hdprivatekey.js → hdprivatekey.cjs} +7 -6
  149. package/test/{hdpublickey.js → hdpublickey.cjs} +2 -7
  150. package/test/mnemonic/{pbkdf2.test.js → pbkdf2.test.cjs} +2 -2
  151. package/test/{networks.js → networks.cjs} +12 -31
  152. package/test/{publickey.js → publickey.cjs} +2 -2
  153. package/test/script/{interpreter.js → interpreter.cjs} +5 -5
  154. package/test/script/{script.js → script.cjs} +8 -2
  155. package/test/transaction/{deserialize.js → deserialize.cjs} +2 -2
  156. package/test/transaction/input/{input.js → input.cjs} +1 -1
  157. package/test/transaction/input/{multisig.js → multisig.cjs} +2 -1
  158. package/test/transaction/input/{publickeyhash.js → publickeyhash.cjs} +1 -1
  159. package/test/transaction/{sighash.js → sighash.cjs} +1 -1
  160. package/test/transaction/{transaction.js → transaction.cjs} +2 -2
  161. package/tsconfig.json +13 -0
  162. package/types/address.d.cts +252 -0
  163. package/types/block/block.d.cts +139 -0
  164. package/types/block/blockheader.d.cts +125 -0
  165. package/types/block/index.d.cts +2 -0
  166. package/types/block/merkleblock.d.cts +95 -0
  167. package/types/bn.d.cts +202 -0
  168. package/types/crypto/bn.d.cts +2 -0
  169. package/types/crypto/ecdsa.d.cts +187 -0
  170. package/types/crypto/hash.d.cts +118 -0
  171. package/types/crypto/index.d.cts +7 -0
  172. package/types/crypto/point.d.cts +134 -0
  173. package/types/crypto/random.d.cts +13 -0
  174. package/types/crypto/signature.d.cts +160 -0
  175. package/types/encoding/base58.d.cts +106 -0
  176. package/types/encoding/base58check.d.cts +107 -0
  177. package/types/encoding/bufferreader.d.cts +164 -0
  178. package/types/encoding/bufferwriter.d.cts +126 -0
  179. package/types/encoding/decode-asm.d.cts +2 -0
  180. package/types/encoding/decode-hex.d.cts +2 -0
  181. package/types/encoding/decode-script-chunks.d.cts +14 -0
  182. package/types/encoding/encode-hex.d.cts +2 -0
  183. package/types/encoding/index.d.cts +6 -0
  184. package/types/encoding/is-hex.d.cts +2 -0
  185. package/types/encoding/varint.d.cts +66 -0
  186. package/types/errors/index.d.cts +4 -0
  187. package/types/errors/spec.d.cts +22 -0
  188. package/types/hash-cache.d.cts +65 -0
  189. package/types/hdprivatekey.d.cts +281 -0
  190. package/types/hdpublickey.d.cts +240 -0
  191. package/types/index.d.cts +26 -0
  192. package/types/interpreter/index.d.cts +2 -0
  193. package/types/interpreter/interpreter.d.cts +228 -0
  194. package/types/interpreter/stack.d.cts +35 -0
  195. package/types/message/message.d.cts +110 -0
  196. package/types/mnemonic/index.d.cts +2 -0
  197. package/types/mnemonic/mnemonic.d.cts +171 -0
  198. package/types/mnemonic/pbkdf2.d.cts +14 -0
  199. package/types/mnemonic/words/chinese.d.cts +2 -0
  200. package/types/mnemonic/words/english.d.cts +2 -0
  201. package/types/mnemonic/words/french.d.cts +2 -0
  202. package/types/mnemonic/words/index.d.cts +22 -0
  203. package/types/mnemonic/words/italian.d.cts +2 -0
  204. package/types/mnemonic/words/japanese.d.cts +2 -0
  205. package/types/mnemonic/words/spanish.d.cts +2 -0
  206. package/types/network.d.cts +11 -0
  207. package/types/networks.d.cts +76 -0
  208. package/types/opcode.d.cts +93 -0
  209. package/types/privatekey.d.cts +169 -0
  210. package/types/publickey.d.cts +202 -0
  211. package/types/script/index.d.cts +2 -0
  212. package/types/script/script.d.cts +449 -0
  213. package/types/script/write-i32-le.d.cts +2 -0
  214. package/types/script/write-push-data.d.cts +2 -0
  215. package/types/script/write-u16-le.d.cts +2 -0
  216. package/types/script/write-u32-le.d.cts +2 -0
  217. package/types/script/write-u64-le.d.cts +2 -0
  218. package/types/script/write-u8-le.d.cts +2 -0
  219. package/types/script/write-varint.d.cts +2 -0
  220. package/types/transaction/index.d.cts +2 -0
  221. package/types/transaction/input/index.d.cts +2 -0
  222. package/types/transaction/input/input.d.cts +178 -0
  223. package/types/transaction/input/multisig.d.cts +127 -0
  224. package/types/transaction/input/publickey.d.cts +44 -0
  225. package/types/transaction/input/publickeyhash.d.cts +45 -0
  226. package/types/transaction/output.d.cts +118 -0
  227. package/types/transaction/sighash.d.cts +61 -0
  228. package/types/transaction/signature.d.cts +43 -0
  229. package/types/transaction/transaction.d.cts +716 -0
  230. package/types/transaction/unspentoutput.d.cts +83 -0
  231. package/types/util/_.d.cts +26 -0
  232. package/types/util/derivation.d.cts +21 -0
  233. package/types/util/index.d.cts +5 -0
  234. package/types/util/js.d.cts +50 -0
  235. package/types/util/preconditions.d.cts +3 -0
  236. package/index.d.ts +0 -1541
  237. package/index.js +0 -74
  238. package/lib/block/index.js +0 -4
  239. package/lib/bn.js +0 -3423
  240. package/lib/crypto/hash.js +0 -2
  241. package/lib/crypto/random.browser.js +0 -28
  242. package/lib/crypto/random.js +0 -2
  243. package/lib/crypto/random.node.js +0 -11
  244. package/lib/encoding/base58check.js +0 -121
  245. package/lib/encoding/bufferreader.js +0 -212
  246. package/lib/encoding/bufferwriter.js +0 -140
  247. package/lib/encoding/varint.js +0 -75
  248. package/lib/hash-cache.js +0 -50
  249. package/lib/mnemonic/pbkdf2.js +0 -2
  250. package/lib/mnemonic/words/index.js +0 -8
  251. package/lib/script/index.js +0 -5
  252. package/lib/transaction/index.js +0 -7
  253. package/lib/transaction/input/index.js +0 -5
  254. package/lib/util/js.js +0 -90
  255. /package/{lib/encoding/decode-script-chunks.js → cjs/encoding/decode-script-chunks.cjs} +0 -0
  256. /package/{lib/encoding/encode-hex.js → cjs/encoding/encode-hex.cjs} +0 -0
  257. /package/{lib/encoding/is-hex.js → cjs/encoding/is-hex.cjs} +0 -0
  258. /package/{lib/mnemonic/words/chinese.js → cjs/mnemonic/words/chinese.cjs} +0 -0
  259. /package/{lib/mnemonic/words/english.js → cjs/mnemonic/words/english.cjs} +0 -0
  260. /package/{lib/mnemonic/words/french.js → cjs/mnemonic/words/french.cjs} +0 -0
  261. /package/{lib/mnemonic/words/italian.js → cjs/mnemonic/words/italian.cjs} +0 -0
  262. /package/{lib/mnemonic/words/japanese.js → cjs/mnemonic/words/japanese.cjs} +0 -0
  263. /package/{lib/mnemonic/words/spanish.js → cjs/mnemonic/words/spanish.cjs} +0 -0
  264. /package/{lib/script/write-i32-le.js → cjs/script/write-i32-le.cjs} +0 -0
  265. /package/{lib/script/write-push-data.js → cjs/script/write-push-data.cjs} +0 -0
  266. /package/{lib/script/write-u16-le.js → cjs/script/write-u16-le.cjs} +0 -0
  267. /package/{lib/script/write-u32-le.js → cjs/script/write-u32-le.cjs} +0 -0
  268. /package/{lib/script/write-u64-le.js → cjs/script/write-u64-le.cjs} +0 -0
  269. /package/{lib/script/write-u8-le.js → cjs/script/write-u8-le.cjs} +0 -0
  270. /package/{lib/script/write-varint.js → cjs/script/write-varint.cjs} +0 -0
  271. /package/{lib/util/_.js → cjs/util/_.cjs} +0 -0
  272. /package/test/crypto/{bn.js → bn.cjs} +0 -0
  273. /package/test/crypto/{hash.js → hash.cjs} +0 -0
  274. /package/test/crypto/{point.js → point.cjs} +0 -0
  275. /package/test/crypto/{random.js → random.cjs} +0 -0
  276. /package/test/data/{blk86756-testnet.js → blk86756-testnet.cjs} +0 -0
  277. /package/test/data/{merkleblocks.js → merkleblocks.cjs} +0 -0
  278. /package/test/encoding/{base58.js → base58.cjs} +0 -0
  279. /package/test/encoding/{base58check.js → base58check.cjs} +0 -0
  280. /package/test/encoding/{bufferreader.js → bufferreader.cjs} +0 -0
  281. /package/test/encoding/{bufferwriter.js → bufferwriter.cjs} +0 -0
  282. /package/test/encoding/{varint.js → varint.cjs} +0 -0
  283. /package/test/{index.js → index.cjs} +0 -0
  284. /package/test/message/{message.js → message.cjs} +0 -0
  285. /package/test/mnemonic/{mnemonic.js → mnemonic.cjs} +0 -0
  286. /package/test/{opcode.js → opcode.cjs} +0 -0
  287. /package/test/{privatekey.js → privatekey.cjs} +0 -0
  288. /package/test/transaction/input/{publickey.js → publickey.cjs} +0 -0
  289. /package/test/transaction/{output.js → output.cjs} +0 -0
  290. /package/test/transaction/{signature.js → signature.cjs} +0 -0
  291. /package/test/transaction/{unspentoutput.js → unspentoutput.cjs} +0 -0
  292. /package/test/util/{js.js → js.cjs} +0 -0
  293. /package/test/util/{preconditions.js → preconditions.cjs} +0 -0
@@ -0,0 +1,1988 @@
1
+ 'use strict';
2
+
3
+ var _ = require('../util/_.cjs');
4
+
5
+ var Script = require('../script/index.cjs');
6
+ var Opcode = require('../opcode.cjs');
7
+ var BN = require('../crypto/bn.cjs');
8
+ var Hash = require('../crypto/hash.cjs');
9
+ var Signature = require('../crypto/signature.cjs');
10
+ var PublicKey = require('../publickey.cjs');
11
+ var Stack = require('./stack.cjs');
12
+ var Transaction = require('../transaction/index.cjs');
13
+
14
+ /**
15
+ * Bitcoin transactions contain scripts. Each input has a script called the
16
+ * scriptSig, and each output has a script called the scriptPubkey. To validate
17
+ * an input, the input's script is concatenated with the referenced output script,
18
+ * and the result is executed. If at the end of execution the stack contains a
19
+ * "true" value, then the transaction is valid.
20
+ *
21
+ * The primary way to use this class is via the verify function.
22
+ * e.g., Interpreter().verify( ... );
23
+ * @constructor
24
+ * @param {Object} [obj] - Optional object to initialize the interpreter with.
25
+ * @returns {Interpreter} A new Interpreter instance.
26
+ */
27
+ function Interpreter(obj) {
28
+ if (!(this instanceof Interpreter)) {
29
+ return new Interpreter(obj);
30
+ }
31
+ if (obj) {
32
+ this.initialize();
33
+ this.set(obj);
34
+ } else {
35
+ this.initialize();
36
+ }
37
+ };
38
+
39
+ /**
40
+ * Verifies a Script by executing it and returns true if it is valid.
41
+ * This function needs to be provided with the scriptSig and the scriptPubkey
42
+ * separately.
43
+ * @param {Script} scriptSig - the script's first part (corresponding to the tx input)
44
+ * @param {Script} scriptPubkey - the script's last part (corresponding to the tx output)
45
+ * @param {Transaction=} tx - the Transaction containing the scriptSig in one input (used
46
+ * to check signature validity for some opcodes like OP_CHECKSIG)
47
+ * @param {number} nin - index of the transaction input containing the scriptSig verified.
48
+ * @param {number} flags - evaluation flags. See Interpreter.SCRIPT_* constants
49
+ * @param {number} satoshisBN - amount in satoshis of the input to be verified (when FORKID signhash is used)
50
+ *
51
+ * Translated from bitcoind's VerifyScript
52
+ */
53
+ Interpreter.prototype.verify = function (
54
+ scriptSig,
55
+ scriptPubkey,
56
+ tx,
57
+ nin,
58
+ flags,
59
+ satoshisBN,
60
+ ) {
61
+
62
+ if (_.isUndefined(tx)) {
63
+ tx = new Transaction();
64
+ }
65
+ if (_.isUndefined(nin)) {
66
+ nin = 0;
67
+ }
68
+ if (_.isUndefined(flags)) {
69
+ flags = 0;
70
+ }
71
+
72
+ this.set({
73
+ script: scriptSig,
74
+ tx: tx,
75
+ nin: nin,
76
+ flags: flags,
77
+ satoshisBN: satoshisBN,
78
+ });
79
+
80
+ if ((flags & Interpreter.SCRIPT_VERIFY_SIGPUSHONLY) !== 0 && !scriptSig.isPushOnly()) {
81
+ this.errstr = 'SCRIPT_ERR_SIG_PUSHONLY';
82
+ return false;
83
+ }
84
+
85
+ // evaluate scriptSig
86
+ if (!this.evaluate('scriptSig')) {
87
+ return false;
88
+ }
89
+
90
+ var stack = this.stack;
91
+ this.initialize();
92
+ this.set({
93
+ script: scriptPubkey,
94
+ stack: stack,
95
+ tx: tx,
96
+ nin: nin,
97
+ flags: flags,
98
+ satoshisBN: satoshisBN,
99
+ });
100
+
101
+ // evaluate scriptPubkey
102
+ if (!this.evaluate('scriptPubkey')) {
103
+ return false;
104
+ }
105
+
106
+ if (this.stack.length === 0) {
107
+ this.errstr = 'SCRIPT_ERR_EVAL_FALSE_NO_RESULT';
108
+ return false;
109
+ }
110
+
111
+ var buf = this.stack.stacktop(-1);
112
+ if (!Interpreter.castToBool(buf)) {
113
+ this.errstr = 'SCRIPT_ERR_EVAL_FALSE_IN_STACK';
114
+ return false;
115
+ }
116
+
117
+ return true;
118
+ };
119
+
120
+
121
+ /**
122
+ * Initializes the interpreter instance with default values.
123
+ * Sets up empty stacks, resets program counter and execution flags,
124
+ * and initializes state tracking variables for script execution.
125
+ */
126
+ Interpreter.prototype.initialize = function () {
127
+ this.stack = new Stack([]);
128
+ this.altstack = new Stack([]);
129
+ this.pc = 0;
130
+ this.pbegincodehash = 0;
131
+ this.nOpCount = 0;
132
+ this.vfExec = [];
133
+ this.vfElse = [];
134
+ this.errstr = '';
135
+ this.flags = 0;
136
+ // if OP_RETURN is found in executed branches after genesis is activated,
137
+ // we still have to check if the rest of the script is valid
138
+ this.nonTopLevelReturnAfterGenesis = false;
139
+ this.returned = false;
140
+ };
141
+
142
+ /**
143
+ * Updates the interpreter's state with provided values.
144
+ * @param {Object} obj - Object containing properties to update
145
+ * @param {Buffer} [obj.script] - Script buffer
146
+ * @param {Object} [obj.tx] - Transaction object
147
+ * @param {boolean} [obj.nin] - Non-input flag
148
+ * @param {BN} [obj.satoshisBN] - Satoshis as BN.js instance
149
+ * @param {Array} [obj.stack] - Main stack
150
+ * @param {Array} [obj.altstack] - Alternate stack
151
+ * @param {number} [obj.pc] - Program counter
152
+ * @param {number} [obj.pbegincodehash] - Begin code hash position
153
+ * @param {number} [obj.nOpCount] - Operation count
154
+ * @param {Array} [obj.vfExec] - Execution flags
155
+ * @param {Array} [obj.vfElse] - Else flags
156
+ * @param {string} [obj.errstr] - Error string
157
+ * @param {number} [obj.flags] - Interpreter flags
158
+ */
159
+ Interpreter.prototype.set = function (obj) {
160
+ this.script = obj.script || this.script;
161
+ this.tx = obj.tx || this.tx;
162
+ this.nin = typeof obj.nin !== 'undefined' ? obj.nin : this.nin;
163
+ this.satoshisBN = obj.satoshisBN || this.satoshisBN;
164
+ this.stack = obj.stack || this.stack;
165
+ this.altstack = obj.altstack || this.altstack;
166
+ this.pc = typeof obj.pc !== 'undefined' ? obj.pc : this.pc;
167
+ this.pbegincodehash =
168
+ typeof obj.pbegincodehash !== 'undefined' ? obj.pbegincodehash : this.pbegincodehash;
169
+ this.nOpCount = typeof obj.nOpCount !== 'undefined' ? obj.nOpCount : this.nOpCount;
170
+ this.vfExec = obj.vfExec || this.vfExec;
171
+ this.vfElse = obj.vfElse || this.vfElse;
172
+ this.errstr = obj.errstr || this.errstr;
173
+ this.flags = typeof obj.flags !== 'undefined' ? obj.flags : this.flags;
174
+ };
175
+
176
+ /**
177
+ * Returns a subset of the script starting from the most recent OP_CODESEPARATOR.
178
+ * @returns {Script} A new Script instance containing the sliced chunks.
179
+ */
180
+ Interpreter.prototype.subscript = function () {
181
+ // Subset of script starting at the most recent codeseparator
182
+ // CScript scriptCode(pbegincodehash, pend);
183
+ return Script.fromChunks(this.script.chunks.slice(this.pbegincodehash));
184
+ };
185
+
186
+ Interpreter.getTrue = () => Buffer.from([1]);
187
+ Interpreter.getFalse = () => Buffer.from([]);
188
+
189
+ /**
190
+ * Maximum allowed size for script elements in the interpreter.
191
+ * Set to the maximum safe integer value by default.
192
+ */
193
+ Interpreter.MAX_SCRIPT_ELEMENT_SIZE = Number.MAX_SAFE_INTEGER;
194
+ /**
195
+ * The maximum allowed size for an element in the interpreter.
196
+ * @type {number}
197
+ */
198
+ Interpreter.MAXIMUM_ELEMENT_SIZE = Number.MAX_SAFE_INTEGER;
199
+
200
+ /**
201
+ * The threshold value used to distinguish between block height and timestamp in locktime.
202
+ * Values below this threshold are interpreted as block numbers, while values equal or above are treated as timestamps.
203
+ */
204
+ Interpreter.LOCKTIME_THRESHOLD = 500000000;
205
+ /**
206
+ * The locktime threshold value as a BN.js BigNumber instance.
207
+ * @type {BN}
208
+ */
209
+ Interpreter.LOCKTIME_THRESHOLD_BN = new BN(Interpreter.LOCKTIME_THRESHOLD);
210
+
211
+ /**
212
+ * Flag indicating no script verification rules should be enforced.
213
+ * flags taken from bitcoind
214
+ * bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104
215
+ * @constant {number}
216
+ */
217
+ Interpreter.SCRIPT_VERIFY_NONE = 0;
218
+
219
+ /**
220
+ * Passing a non-strict-DER signature or one with undefined hashtype to a checksig operation causes script failure.
221
+ * Passing a pubkey that is not (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) to checksig causes that pubkey to be
222
+ * skipped (not softfork safe: this flag can widen the validity of OP_CHECKSIG OP_NOT).
223
+ */
224
+ Interpreter.SCRIPT_VERIFY_STRICTENC = 1 << 1;
225
+
226
+
227
+ /**
228
+ * Passing a non-strict-DER signature to a checksig operation causes script failure (softfork safe, BIP62 rule 1)
229
+ */
230
+ Interpreter.SCRIPT_VERIFY_DERSIG = 1 << 2;
231
+
232
+ /**
233
+ * Passing a non-strict-DER signature or one with S > order/2 to a checksig operation causes script failure
234
+ * (softfork safe, BIP62 rule 5).
235
+ */
236
+ Interpreter.SCRIPT_VERIFY_LOW_S = 1 << 3;
237
+
238
+ /**
239
+ * verify dummy stack item consumed by CHECKMULTISIG is of zero-length (softfork safe, BIP62 rule 7).
240
+ */
241
+ Interpreter.SCRIPT_VERIFY_NULLDUMMY = 1 << 4;
242
+
243
+ /**
244
+ * Using a non-push operator in the scriptSig causes script failure (softfork safe, BIP62 rule 2).
245
+ */
246
+ Interpreter.SCRIPT_VERIFY_SIGPUSHONLY = 1 << 5;
247
+
248
+ /**
249
+ * Require minimal encodings for all push operations (OP_0... OP_16, OP_1NEGATE where possible, direct
250
+ * pushes up to 75 bytes, OP_PUSHDATA up to 255 bytes, OP_PUSHDATA2 for anything larger). Evaluating
251
+ * any other push causes the script to fail (BIP62 rule 3).
252
+ * In addition, whenever a stack element is interpreted as a number, it must be of minimal length (BIP62 rule 4).
253
+ * (softfork safe)
254
+ *
255
+ */
256
+ Interpreter.SCRIPT_VERIFY_MINIMALDATA = 1 << 6;
257
+
258
+ /**
259
+ * Discourage use of NOPs reserved for upgrades (NOP1-10)
260
+ *
261
+ * Provided so that nodes can avoid accepting or mining transactions
262
+ * containing executed NOP's whose meaning may change after a soft-fork,
263
+ * thus rendering the script invalid; with this flag set executing
264
+ * discouraged NOPs fails the script. This verification flag will never be
265
+ * a mandatory flag applied to scripts in a block. NOPs that are not
266
+ * executed, e.g. within an unexecuted IF ENDIF block, are *not* rejected.
267
+ */
268
+ Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = 1 << 7;
269
+
270
+
271
+
272
+ /**
273
+ * CLTV See BIP65 for details.
274
+ */
275
+ Interpreter.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = 1 << 9;
276
+
277
+ /**
278
+ * support CHECKSEQUENCEVERIFY opcode
279
+ * See BIP112 for details
280
+ */
281
+ Interpreter.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY = 1 << 10;
282
+
283
+
284
+ /**
285
+ * Flag indicating that script verification should fail if a null input is encountered.
286
+ * This is a bitmask value (1 << 14) used in script verification rules.
287
+ */
288
+ Interpreter.SCRIPT_VERIFY_NULLFAIL = 1 << 14;
289
+
290
+ /**
291
+ * Flag indicating that compressed public key type should be verified in scripts.
292
+ * This is a bit flag used in script verification (1 << 15).
293
+ * @type {number}
294
+ */
295
+ Interpreter.SCRIPT_VERIFY_COMPRESSED_PUBKEYTYPE = 1 << 15;
296
+
297
+
298
+ /**
299
+ * Enable new opcodes.
300
+ * @type {number}
301
+ */
302
+ Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES = 1 << 18;
303
+
304
+
305
+ /**
306
+ * Are the Magnetic upgrade opcodes enabled?
307
+ * @type {number}
308
+ */
309
+ Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES = 1 << 19;
310
+
311
+ /* Below flags apply in the context of BIP 68 */
312
+ /**
313
+ * If this flag set, CTxIn::nSequence is NOT interpreted as a relative
314
+ * lock-time.
315
+ * @type {number}
316
+ */
317
+ Interpreter.SEQUENCE_LOCKTIME_DISABLE_FLAG = 1 << 31;
318
+
319
+ /**
320
+ * If CTxIn::nSequence encodes a relative lock-time and this flag is set,
321
+ * the relative lock-time has units of 512 seconds, otherwise it specifies
322
+ * blocks with a granularity of 1.
323
+ * @type {number}
324
+ */
325
+ Interpreter.SEQUENCE_LOCKTIME_TYPE_FLAG = 1 << 22;
326
+
327
+ /**
328
+ * If CTxIn::nSequence encodes a relative lock-time, this mask is applied to
329
+ * extract that lock-time from the sequence field.
330
+ * @type {number}
331
+ */
332
+ Interpreter.SEQUENCE_LOCKTIME_MASK = 0x0000ffff;
333
+
334
+ /**
335
+ * Maximum allowed script size for the interpreter, set to the largest safe integer in JavaScript.
336
+ * @type {number}
337
+ */
338
+ Interpreter.MAX_SCRIPT_SIZE = Number.MAX_SAFE_INTEGER;
339
+
340
+ /**
341
+ * Maximum number of opcodes that can be executed before stopping the interpreter.
342
+ * Defaults to Number.MAX_SAFE_INTEGER (effectively unlimited).
343
+ * @type {number}
344
+ */
345
+ Interpreter.MAX_OPCODE_COUNT = Number.MAX_SAFE_INTEGER;
346
+
347
+ /**
348
+ * Default flags used by the interpreter.
349
+ * @type {number}
350
+ */
351
+ Interpreter.DEFAULT_FLAGS =
352
+ Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES |
353
+ Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES |
354
+ Interpreter.SCRIPT_VERIFY_STRICTENC |
355
+ Interpreter.SCRIPT_VERIFY_LOW_S |
356
+ Interpreter.SCRIPT_VERIFY_NULLFAIL |
357
+ Interpreter.SCRIPT_VERIFY_DERSIG |
358
+ Interpreter.SCRIPT_VERIFY_MINIMALDATA |
359
+ Interpreter.SCRIPT_VERIFY_NULLDUMMY |
360
+ Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS |
361
+ Interpreter.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY |
362
+ Interpreter.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY;
363
+
364
+
365
+ /**
366
+ * Casts a buffer to a boolean value.
367
+ * Returns true if any byte in the buffer is non-zero (except for the special case of negative zero).
368
+ * Returns false if all bytes are zero or if the last byte is 0x80 (negative zero case).
369
+ * @param {Buffer} buf - The input buffer to check
370
+ * @returns {boolean} The boolean representation of the buffer
371
+ */
372
+ Interpreter.castToBool = function (buf) {
373
+ for (var i = 0; i < buf.length; i++) {
374
+ if (buf[i] !== 0) {
375
+ // can be negative zero
376
+ if (i === buf.length - 1 && buf[i] === 0x80) {
377
+ return false;
378
+ }
379
+ return true;
380
+ }
381
+ }
382
+ return false;
383
+ };
384
+
385
+
386
+ /**
387
+ * Checks if a signature encoding is valid according to the interpreter's flags.
388
+ * - For empty signatures: always valid (used for compact invalid signatures in CHECK(MULTI)SIG)
389
+ * - With DERSIG/STRICTENC flags: validates DER encoding and strict encoding rules
390
+ * - With LOW_S flag: ensures signature uses low S value
391
+ * - With STRICTENC flag: validates defined hash type
392
+ * @param {Buffer} buf - The signature buffer to validate
393
+ * @returns {boolean} True if valid, false otherwise (sets errstr on failure)
394
+ */
395
+ Interpreter.prototype.checkSignatureEncoding = function (buf) {
396
+ var sig;
397
+
398
+ // Empty signature. Not strictly DER encoded, but allowed to provide a
399
+ // compact way to provide an invalid signature for use with CHECK(MULTI)SIG
400
+ if (buf.length === 0) {
401
+ return true;
402
+ }
403
+
404
+ if (
405
+ (this.flags &
406
+ (Interpreter.SCRIPT_VERIFY_DERSIG |
407
+ Interpreter.SCRIPT_VERIFY_LOW_S |
408
+ Interpreter.SCRIPT_VERIFY_STRICTENC)) !==
409
+ 0 &&
410
+ !Signature.isTxDER(buf)
411
+ ) {
412
+ this.errstr = 'SCRIPT_ERR_SIG_DER_INVALID_FORMAT';
413
+ return false;
414
+ } else if ((this.flags & Interpreter.SCRIPT_VERIFY_LOW_S) !== 0) {
415
+ sig = Signature.fromTxFormat(buf);
416
+ if (!sig.hasLowS()) {
417
+ this.errstr = 'SCRIPT_ERR_SIG_DER_HIGH_S';
418
+ return false;
419
+ }
420
+ } else if ((this.flags & Interpreter.SCRIPT_VERIFY_STRICTENC) !== 0) {
421
+ sig = Signature.fromTxFormat(buf);
422
+ if (!sig.hasDefinedHashtype()) {
423
+ this.errstr = 'SCRIPT_ERR_SIG_HASHTYPE';
424
+ return false;
425
+ }
426
+ }
427
+
428
+ return true;
429
+ };
430
+
431
+
432
+ /**
433
+ * Checks if the provided public key buffer is valid according to strict encoding rules.
434
+ * Sets an error message if validation fails under SCRIPT_VERIFY_STRICTENC flag.
435
+ * @param {Buffer} buf - The public key buffer to validate.
436
+ * @returns {boolean} True if valid, false otherwise (with error string set).
437
+ */
438
+ Interpreter.prototype.checkPubkeyEncoding = function (buf) {
439
+ if ((this.flags & Interpreter.SCRIPT_VERIFY_STRICTENC) !== 0 && !PublicKey.isValid(buf)) {
440
+ this.errstr = 'SCRIPT_ERR_PUBKEYTYPE';
441
+ return false;
442
+ }
443
+ return true;
444
+ };
445
+
446
+ /**
447
+ * 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.
448
+ * @param {Buffer} buf - The buffer to check.
449
+ * @param {number} [nMaxNumSize=Interpreter.MAXIMUM_ELEMENT_SIZE] - Maximum allowed size for the buffer.
450
+ * @returns {boolean} True if the buffer is minimally encoded, false otherwise.
451
+ * @private
452
+ */
453
+ Interpreter._isMinimallyEncoded = function (buf, nMaxNumSize) {
454
+ nMaxNumSize = nMaxNumSize || Interpreter.MAXIMUM_ELEMENT_SIZE;
455
+ if (buf.length > nMaxNumSize) {
456
+ return false;
457
+ }
458
+
459
+ if (buf.length > 0) {
460
+ // Check that the number is encoded with the minimum possible number
461
+ // of bytes.
462
+ //
463
+ // If the most-significant-byte - excluding the sign bit - is zero
464
+ // then we're not minimal. Note how this test also rejects the
465
+ // negative-zero encoding, 0x80.
466
+ if ((buf[buf.length - 1] & 0x7f) === 0) {
467
+ // One exception: if there's more than one byte and the most
468
+ // significant bit of the second-most-significant-byte is set it
469
+ // would conflict with the sign bit. An example of this case is
470
+ // +-255, which encode to 0xff00 and 0xff80 respectively.
471
+ // (big-endian).
472
+ if (buf.length <= 1 || (buf[buf.length - 2] & 0x80) === 0) {
473
+ return false;
474
+ }
475
+ }
476
+ }
477
+ return true;
478
+ };
479
+
480
+
481
+ /**
482
+ * Minimally encodes a buffer by removing unnecessary trailing zeros.
483
+ *
484
+ * This function implements minimal encoding rules for script numbers:
485
+ * - Empty buffer remains empty
486
+ * - Last byte must not be 0x00 or 0x80 unless necessary
487
+ * - Single zero byte encodes as empty buffer
488
+ * - Preserves sign bit when trimming
489
+ *
490
+ * @param {Buffer} buf - The input buffer to encode
491
+ * @returns {Buffer} Minimally encoded buffer (may be empty)
492
+ */
493
+ Interpreter._minimallyEncode = function (buf) {
494
+ if (buf.length === 0) {
495
+ return buf;
496
+ }
497
+
498
+ // If the last byte is not 0x00 or 0x80, we are minimally encoded.
499
+ var last = buf[buf.length - 1];
500
+ if (last & 0x7f) {
501
+ return buf;
502
+ }
503
+
504
+ // If the script is one byte long, then we have a zero, which encodes as an
505
+ // empty array.
506
+ if (buf.length === 1) {
507
+ return Buffer.from('');
508
+ }
509
+
510
+ // If the next byte has it sign bit set, then we are minimaly encoded.
511
+ if (buf[buf.length - 2] & 0x80) {
512
+ return buf;
513
+ }
514
+
515
+ // We are not minimally encoded, we need to figure out how much to trim.
516
+ for (var i = buf.length - 1; i > 0; i--) {
517
+ // We found a non zero byte, time to encode.
518
+ if (buf[i - 1] !== 0) {
519
+ if (buf[i - 1] & 0x80) {
520
+ // We found a byte with it sign bit set so we need one more
521
+ // byte.
522
+ buf[i++] = last;
523
+ } else {
524
+ // the sign bit is clear, we can use it.
525
+ buf[i - 1] |= last;
526
+ }
527
+
528
+ return buf.slice(0, i);
529
+ }
530
+ }
531
+
532
+ // If we found the whole thing is zeros, then we have a zero.
533
+ return Buffer.from('');
534
+ };
535
+
536
+
537
+ /**
538
+ * Evaluates a script by executing each opcode step-by-step.
539
+ * Performs size checks on the script and stacks before execution.
540
+ *
541
+ * Based on bitcoind's EvalScript function, with the inner loop moved to `Interpreter.prototype.step()`
542
+ * bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104
543
+ * @param {string} scriptType - The type of script being evaluated
544
+ * @returns {boolean} True if evaluation succeeds, false if any error occurs
545
+ * @throws {Error} If an unknown error occurs during evaluation
546
+ */
547
+ Interpreter.prototype.evaluate = function (scriptType) {
548
+ // TODO: script size should be configurable. no magic numbers
549
+ if (this.script.toBuffer().length > Interpreter.MAX_SCRIPT_SIZE) {
550
+ this.errstr = 'SCRIPT_ERR_SCRIPT_SIZE';
551
+ return false;
552
+ }
553
+
554
+ try {
555
+ while (!this.returned && this.pc < this.script.chunks.length) {
556
+ // fExec: if the opcode will be executed, i.e., not in a false branch
557
+ let thisStep = {
558
+ pc: this.pc,
559
+ fExec: this.vfExec.indexOf(false) === -1,
560
+ opcode: Opcode.fromNumber(this.script.chunks[this.pc].opcodenum),
561
+ };
562
+
563
+ var fSuccess = this.step(scriptType);
564
+
565
+ this._callbackStep(thisStep);
566
+
567
+ if (!fSuccess) {
568
+ return false;
569
+ }
570
+ }
571
+
572
+ // Size limits
573
+ if (this.stack.length + this.altstack.length > 1000) {
574
+ this.errstr = 'SCRIPT_ERR_STACK_SIZE';
575
+ return false;
576
+ }
577
+ } catch (e) {
578
+ this.errstr = 'SCRIPT_ERR_UNKNOWN_ERROR: ' + e;
579
+ return false;
580
+ }
581
+
582
+ if (this.vfExec.length > 0) {
583
+ this.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL';
584
+ return false;
585
+ }
586
+
587
+ return true;
588
+ };
589
+
590
+ /**
591
+ * Handles step callback execution for the interpreter.
592
+ * @private
593
+ * @param {Object} thisStep - The current step object to pass to the listener
594
+ * @throws {Error} Logs any errors that occur during callback execution
595
+ */
596
+ Interpreter.prototype._callbackStep = function (thisStep) {
597
+ if (typeof this.stepListener === 'function') {
598
+ try {
599
+ this.stepListener(thisStep);
600
+ } catch (err) {
601
+ console.log(`Error in Step callback:${err}`);
602
+ }
603
+ }
604
+ };
605
+
606
+
607
+ /**
608
+ * Handles stack callbacks by invoking the registered stack listener function.
609
+ * If an error occurs during callback execution, logs the error along with PC and opcode details.
610
+ * @param {Stack} stack - The current execution stack
611
+ * @param {number} pc - Program counter value
612
+ * @param {string} scriptType - Type of script being executed
613
+ * @private
614
+ */
615
+ Interpreter.prototype._callbackStack = function (stack, pc, scriptType) {
616
+ if (typeof this.stackListener === 'function') {
617
+ try {
618
+ this.stackListener(stack, pc, scriptType);
619
+ } catch (err) {
620
+ var chunk = this.script.chunks[pc];
621
+ console.error(
622
+ `Error: ${err} in _updateStack pc: ${pc}, opcode ${Opcode.fromNumber(
623
+ chunk.opcodenum,
624
+ ).toSafeString()}`,
625
+ );
626
+ }
627
+ }
628
+ };
629
+
630
+ /**
631
+ * Checks a locktime parameter with the transaction's locktime.
632
+ * There are two times of nLockTime: lock-by-blockheight and lock-by-blocktime,
633
+ * distinguished by whether nLockTime < LOCKTIME_THRESHOLD = 500000000
634
+ *
635
+ * See the corresponding code on bitcoin core:
636
+ * https://github.com/bitcoin/bitcoin/blob/ffd75adce01a78b3461b3ff05bcc2b530a9ce994/src/script/interpreter.cpp#L1129
637
+ *
638
+ * @param {BN} nLockTime the locktime read from the script
639
+ * @return {boolean} true if the transaction's locktime is less than or equal to
640
+ * the transaction's locktime
641
+ */
642
+ Interpreter.prototype.checkLockTime = function (nLockTime) {
643
+ // We want to compare apples to apples, so fail the script
644
+ // unless the type of nLockTime being tested is the same as
645
+ // the nLockTime in the transaction.
646
+ if (
647
+ !(
648
+ (this.tx.nLockTime < Interpreter.LOCKTIME_THRESHOLD &&
649
+ nLockTime.lt(Interpreter.LOCKTIME_THRESHOLD_BN)) ||
650
+ (this.tx.nLockTime >= Interpreter.LOCKTIME_THRESHOLD &&
651
+ nLockTime.gte(Interpreter.LOCKTIME_THRESHOLD_BN))
652
+ )
653
+ ) {
654
+ return false;
655
+ }
656
+
657
+ // Now that we know we're comparing apples-to-apples, the
658
+ // comparison is a simple numeric one.
659
+ if (nLockTime.gt(new BN(this.tx.nLockTime))) {
660
+ return false;
661
+ }
662
+
663
+ // Finally the nLockTime feature can be disabled and thus
664
+ // CHECKLOCKTIMEVERIFY bypassed if every txin has been
665
+ // finalized by setting nSequence to maxint. The
666
+ // transaction would be allowed into the blockchain, making
667
+ // the opcode ineffective.
668
+ //
669
+ // Testing if this vin is not final is sufficient to
670
+ // prevent this condition. Alternatively we could test all
671
+ // inputs, but testing just this input minimizes the data
672
+ // required to prove correct CHECKLOCKTIMEVERIFY execution.
673
+ if (this.tx.inputs[this.nin].isFinal()) {
674
+ return false;
675
+ }
676
+
677
+ return true;
678
+ };
679
+
680
+ /**
681
+ * Checks a sequence parameter with the transaction's sequence.
682
+ * @param {BN} nSequence the sequence read from the script
683
+ * @return {boolean} true if the transaction's sequence is less than or equal to
684
+ * the transaction's sequence
685
+ */
686
+ Interpreter.prototype.checkSequence = function (nSequence) {
687
+ // Relative lock times are supported by comparing the passed in operand to
688
+ // the sequence number of the input.
689
+ var txToSequence = this.tx.inputs[this.nin].sequenceNumber;
690
+
691
+ // Fail if the transaction's version number is not set high enough to
692
+ // trigger BIP 68 rules.
693
+ if (this.tx.version < 2) {
694
+ return false;
695
+ }
696
+
697
+ // Sequence numbers with their most significant bit set are not consensus
698
+ // constrained. Testing that the transaction's sequence number do not have
699
+ // this bit set prevents using this property to get around a
700
+ // CHECKSEQUENCEVERIFY check.
701
+ if (txToSequence & Interpreter.SEQUENCE_LOCKTIME_DISABLE_FLAG) {
702
+ return false;
703
+ }
704
+
705
+ // Mask off any bits that do not have consensus-enforced meaning before
706
+ // doing the integer comparisons
707
+ var nLockTimeMask = Interpreter.SEQUENCE_LOCKTIME_TYPE_FLAG | Interpreter.SEQUENCE_LOCKTIME_MASK;
708
+ var txToSequenceMasked = new BN(txToSequence & nLockTimeMask);
709
+ var nSequenceMasked = nSequence.and(nLockTimeMask);
710
+
711
+ // There are two kinds of nSequence: lock-by-blockheight and
712
+ // lock-by-blocktime, distinguished by whether nSequenceMasked <
713
+ // CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG.
714
+ //
715
+ // We want to compare apples to apples, so fail the script unless the type
716
+ // of nSequenceMasked being tested is the same as the nSequenceMasked in the
717
+ // transaction.
718
+ var SEQUENCE_LOCKTIME_TYPE_FLAG_BN = new BN(Interpreter.SEQUENCE_LOCKTIME_TYPE_FLAG);
719
+
720
+ if (
721
+ !(
722
+ (txToSequenceMasked.lt(SEQUENCE_LOCKTIME_TYPE_FLAG_BN) &&
723
+ nSequenceMasked.lt(SEQUENCE_LOCKTIME_TYPE_FLAG_BN)) ||
724
+ (txToSequenceMasked.gte(SEQUENCE_LOCKTIME_TYPE_FLAG_BN) &&
725
+ nSequenceMasked.gte(SEQUENCE_LOCKTIME_TYPE_FLAG_BN))
726
+ )
727
+ ) {
728
+ return false;
729
+ }
730
+
731
+ // Now that we know we're comparing apples-to-apples, the comparison is a
732
+ // simple numeric one.
733
+ if (nSequenceMasked.gt(txToSequenceMasked)) {
734
+ return false;
735
+ }
736
+ return true;
737
+ };
738
+
739
+ function padBufferToSize(buf, len) {
740
+ let b = buf;
741
+ while (b.length < len) {
742
+ b = Buffer.concat([Buffer.from([0x00]), b]);
743
+ }
744
+ return b;
745
+ }
746
+
747
+
748
+ /**
749
+ * Executes a single step in the script interpreter.
750
+ *
751
+ * This method processes the current opcode in the script, performs the corresponding operation,
752
+ * and updates the stack or interpreter state accordingly. It handles various opcode types including
753
+ * stack operations, arithmetic, bitwise logic, cryptographic operations, and control flow.
754
+ *
755
+ * Based on the inner loop of bitcoind's EvalScript function
756
+ * bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104
757
+ * @param {string} scriptType - The type of script being executed (e.g., scriptPubkey, scriptSig).
758
+ * @returns {boolean} Returns `true` if the step executed successfully, or `false` if an error occurred.
759
+ * Errors are stored in `this.errstr`.
760
+ */
761
+ Interpreter.prototype.step = function (scriptType) {
762
+ var self = this;
763
+
764
+ function stacktop(i) {
765
+ return self.stack.stacktop(i);
766
+ }
767
+
768
+ function vartop(i) {
769
+ return self.stack.vartop(i);
770
+ }
771
+
772
+ function isOpcodeDisabled(opcode) {
773
+ switch (opcode) {
774
+ case Opcode.OP_2MUL:
775
+ case Opcode.OP_2DIV:
776
+ // Disabled opcodes.
777
+ return true;
778
+
779
+ case Opcode.OP_INVERT:
780
+ case Opcode.OP_MUL:
781
+ case Opcode.OP_LSHIFT:
782
+ case Opcode.OP_RSHIFT:
783
+ // Opcodes that have been reenabled.
784
+ if ((self.flags & Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES) === 0) {
785
+ return true;
786
+ }
787
+ break;
788
+ case Opcode.OP_DIV:
789
+ case Opcode.OP_MOD:
790
+ case Opcode.OP_SPLIT:
791
+ case Opcode.OP_CAT:
792
+ case Opcode.OP_AND:
793
+ case Opcode.OP_OR:
794
+ case Opcode.OP_XOR:
795
+ case Opcode.OP_BIN2NUM:
796
+ case Opcode.OP_NUM2BIN:
797
+ // Opcodes that have been reenabled.
798
+ if ((self.flags & Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES) === 0) {
799
+ return true;
800
+ }
801
+ break;
802
+ default:
803
+ break;
804
+ }
805
+
806
+ return false;
807
+ }
808
+
809
+ var fRequireMinimal = (this.flags & Interpreter.SCRIPT_VERIFY_MINIMALDATA) !== 0;
810
+
811
+ // bool fExec = !count(vfExec.begin(), vfExec.end(), false);
812
+
813
+ var buf, buf1, buf2, spliced, n, x1, x2, bn, bn1, bn2, bufSig, bufPubkey, subscript;
814
+ var sig, pubkey;
815
+ var fValue, fSuccess;
816
+ var var1, var2, var3;
817
+
818
+ // Read instruction
819
+ var chunk = this.script.chunks[this.pc];
820
+ this.pc++;
821
+ var opcodenum = chunk.opcodenum;
822
+ if (_.isUndefined(opcodenum)) {
823
+ this.errstr = 'SCRIPT_ERR_UNDEFINED_OPCODE';
824
+ return false;
825
+ }
826
+ if (chunk.buf && chunk.buf.length > Interpreter.MAX_SCRIPT_ELEMENT_SIZE) {
827
+ this.errstr = 'SCRIPT_ERR_PUSH_SIZE';
828
+ return false;
829
+ }
830
+
831
+ // Do not execute instructions if Genesis OP_RETURN was found in executed branches.
832
+ var fExec =
833
+ this.vfExec.indexOf(false) === -1 &&
834
+ (!this.nonTopLevelReturnAfterGenesis || opcodenum === Opcode.OP_RETURN);
835
+
836
+ // Note how Opcode.OP_RESERVED does not count towards the opcode limit.
837
+ if (opcodenum > Opcode.OP_16 && ++this.nOpCount > Interpreter.MAX_OPCODE_COUNT) {
838
+ this.errstr = 'SCRIPT_ERR_OP_COUNT';
839
+ return false;
840
+ }
841
+
842
+ if (isOpcodeDisabled(opcodenum)) {
843
+ this.errstr = 'SCRIPT_ERR_DISABLED_OPCODE';
844
+ return false;
845
+ }
846
+
847
+ if (fExec && opcodenum >= 0 && opcodenum <= Opcode.OP_PUSHDATA4) {
848
+ if (fRequireMinimal && !this.script.checkMinimalPush(this.pc - 1)) {
849
+ this.errstr = 'SCRIPT_ERR_MINIMALDATA';
850
+ return false;
851
+ }
852
+ if (!chunk.buf) {
853
+ this.stack.push(Interpreter.getFalse());
854
+ } else if (chunk.len !== chunk.buf.length) {
855
+ throw new Error(
856
+ `Length of push value not equal to length of data (${chunk.len},${chunk.buf.length})`,
857
+ );
858
+ } else {
859
+ this.stack.push(chunk.buf);
860
+ }
861
+ } else if (fExec || (Opcode.OP_IF <= opcodenum && opcodenum <= Opcode.OP_ENDIF)) {
862
+ switch (opcodenum) {
863
+ // Push value
864
+ case Opcode.OP_1NEGATE:
865
+ case Opcode.OP_1:
866
+ case Opcode.OP_2:
867
+ case Opcode.OP_3:
868
+ case Opcode.OP_4:
869
+ case Opcode.OP_5:
870
+ case Opcode.OP_6:
871
+ case Opcode.OP_7:
872
+ case Opcode.OP_8:
873
+ case Opcode.OP_9:
874
+ case Opcode.OP_10:
875
+ case Opcode.OP_11:
876
+ case Opcode.OP_12:
877
+ case Opcode.OP_13:
878
+ case Opcode.OP_14:
879
+ case Opcode.OP_15:
880
+ case Opcode.OP_16:
881
+ // ( -- value)
882
+ // ScriptNum bn((int)opcode - (int)(Opcode.OP_1 - 1));
883
+ n = opcodenum - (Opcode.OP_1 - 1);
884
+ buf = new BN(n).toScriptNumBuffer();
885
+ this.stack.push(buf);
886
+ // The result of these opcodes should always be the minimal way to push the data
887
+ // they push, so no need for a CheckMinimalPush here.
888
+ break;
889
+
890
+ //
891
+ // Control
892
+ //
893
+ case Opcode.OP_NOP:
894
+ break;
895
+
896
+ case Opcode.OP_NOP2:
897
+ case Opcode.OP_CHECKLOCKTIMEVERIFY:
898
+ if (!(this.flags & Interpreter.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) {
899
+ // not enabled; treat as a NOP2
900
+ if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
901
+ this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS';
902
+ return false;
903
+ }
904
+ break;
905
+ }
906
+
907
+ if (this.stack.length < 1) {
908
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
909
+ return false;
910
+ }
911
+
912
+ // Note that elsewhere numeric opcodes are limited to
913
+ // operands in the range -2**31+1 to 2**31-1, however it is
914
+ // legal for opcodes to produce results exceeding that
915
+ // range. This limitation is implemented by CScriptNum's
916
+ // default 4-byte limit.
917
+ //
918
+ // If we kept to that limit we'd have a year 2038 problem,
919
+ // even though the nLockTime field in transactions
920
+ // themselves is uint32 which only becomes meaningless
921
+ // after the year 2106.
922
+ //
923
+ // Thus as a special case we tell CScriptNum to accept up
924
+ // to 5-byte bignums, which are good until 2**39-1, well
925
+ // beyond the 2**32-1 limit of the nLockTime field itself.
926
+ var nLockTime = BN.fromScriptNumBuffer(this.stack.stacktop(-1), fRequireMinimal, 5);
927
+
928
+ // In the rare event that the argument may be < 0 due to
929
+ // some arithmetic being done first, you can always use
930
+ // 0 MAX CHECKLOCKTIMEVERIFY.
931
+ if (nLockTime.lt(new BN(0))) {
932
+ this.errstr = 'SCRIPT_ERR_NEGATIVE_LOCKTIME';
933
+ return false;
934
+ }
935
+
936
+ // Actually compare the specified lock time with the transaction.
937
+ if (!this.checkLockTime(nLockTime)) {
938
+ this.errstr = 'SCRIPT_ERR_UNSATISFIED_LOCKTIME';
939
+ return false;
940
+ }
941
+ break;
942
+
943
+ case Opcode.OP_NOP3:
944
+ case Opcode.OP_CHECKSEQUENCEVERIFY:
945
+ if (!(this.flags & Interpreter.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) {
946
+ // not enabled; treat as a NOP3
947
+ if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
948
+ this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS';
949
+ return false;
950
+ }
951
+ break;
952
+ }
953
+
954
+ if (this.stack.length < 1) {
955
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
956
+ return false;
957
+ }
958
+
959
+ // nSequence, like nLockTime, is a 32-bit unsigned
960
+ // integer field. See the comment in CHECKLOCKTIMEVERIFY
961
+ // regarding 5-byte numeric operands.
962
+
963
+ var nSequence = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, 5);
964
+
965
+ // In the rare event that the argument may be < 0 due to
966
+ // some arithmetic being done first, you can always use
967
+ // 0 MAX CHECKSEQUENCEVERIFY.
968
+ if (nSequence.lt(new BN(0))) {
969
+ this.errstr = 'SCRIPT_ERR_NEGATIVE_LOCKTIME';
970
+ return false;
971
+ }
972
+
973
+ // To provide for future soft-fork extensibility, if the
974
+ // operand has the disabled lock-time flag set,
975
+ // CHECKSEQUENCEVERIFY behaves as a NOP.
976
+ if ((nSequence & Interpreter.SEQUENCE_LOCKTIME_DISABLE_FLAG) !== 0) {
977
+ break;
978
+ }
979
+
980
+ // Actually compare the specified lock time with the transaction.
981
+ if (!this.checkSequence(nSequence)) {
982
+ this.errstr = 'SCRIPT_ERR_UNSATISFIED_LOCKTIME';
983
+ return false;
984
+ }
985
+ break;
986
+
987
+ case Opcode.OP_NOP1:
988
+ case Opcode.OP_NOP4:
989
+ case Opcode.OP_NOP5:
990
+ case Opcode.OP_NOP6:
991
+ case Opcode.OP_NOP7:
992
+ case Opcode.OP_NOP8:
993
+ case Opcode.OP_NOP9:
994
+ case Opcode.OP_NOP10:
995
+ if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
996
+ this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS';
997
+ return false;
998
+ }
999
+ break;
1000
+
1001
+ case Opcode.OP_IF:
1002
+ case Opcode.OP_NOTIF:
1003
+ // <expression> if [statements] [else [statements]] endif
1004
+ // bool fValue = false;
1005
+ fValue = false;
1006
+ if (fExec) {
1007
+ if (this.stack.length < 1) {
1008
+ this.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL';
1009
+ return false;
1010
+ }
1011
+ buf = stacktop(-1);
1012
+
1013
+ fValue = Interpreter.castToBool(buf);
1014
+ if (opcodenum === Opcode.OP_NOTIF) {
1015
+ fValue = !fValue;
1016
+ }
1017
+ this.stack.pop();
1018
+ }
1019
+ this.vfExec.push(fValue);
1020
+ this.vfElse.push(false);
1021
+ break;
1022
+
1023
+ case Opcode.OP_ELSE:
1024
+ if (this.vfExec.length === 0 || this.vfElse[this.vfElse.length - 1] === true) {
1025
+ this.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL';
1026
+ return false;
1027
+ }
1028
+ this.vfExec[this.vfExec.length - 1] = !this.vfExec[this.vfExec.length - 1];
1029
+ this.vfElse[this.vfElse.length - 1] = true;
1030
+ break;
1031
+
1032
+ case Opcode.OP_ENDIF:
1033
+ if (this.vfExec.length === 0) {
1034
+ this.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL';
1035
+ return false;
1036
+ }
1037
+ this.vfExec.pop();
1038
+ this.vfElse.pop();
1039
+ break;
1040
+
1041
+ case Opcode.OP_VERIFY:
1042
+ // (true -- ) or
1043
+ // (false -- false) and return
1044
+ if (this.stack.length < 1) {
1045
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1046
+ return false;
1047
+ }
1048
+ buf = stacktop(-1);
1049
+ fValue = Interpreter.castToBool(buf);
1050
+ if (fValue) {
1051
+ this.stack.pop();
1052
+ } else {
1053
+ this.errstr = 'SCRIPT_ERR_VERIFY';
1054
+ return false;
1055
+ }
1056
+ break;
1057
+
1058
+ case Opcode.OP_RETURN:
1059
+ // utxo_after_genesis
1060
+ if (this.vfExec.length === 0) {
1061
+ // Terminate the execution as successful. The remaining of the script does not affect the validity (even in
1062
+ // presence of unbalanced IFs, invalid opcodes etc)
1063
+ this.returned = true;
1064
+ return true;
1065
+ }
1066
+ // op_return encountered inside if statement after genesis --> check for invalid grammar
1067
+ this.nonTopLevelReturnAfterGenesis = true;
1068
+ break;
1069
+
1070
+ //
1071
+ // Stack ops
1072
+ //
1073
+ case Opcode.OP_TOALTSTACK:
1074
+ if (this.stack.length < 1) {
1075
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1076
+ return false;
1077
+ }
1078
+ var1 = vartop(-1);
1079
+ this.altstack.push(this.stack.pop(), var1);
1080
+ break;
1081
+
1082
+ case Opcode.OP_FROMALTSTACK:
1083
+ if (this.altstack.length < 1) {
1084
+ this.errstr = 'SCRIPT_ERR_INVALID_ALTSTACK_OPERATION';
1085
+ return false;
1086
+ }
1087
+ const varAlt = this.altstack.vartop(-1);
1088
+ this.stack.push(this.altstack.pop(), varAlt);
1089
+ break;
1090
+
1091
+ case Opcode.OP_2DROP:
1092
+ // (x1 x2 -- )
1093
+ if (this.stack.length < 2) {
1094
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1095
+ return false;
1096
+ }
1097
+ this.stack.pop();
1098
+ this.stack.pop();
1099
+ break;
1100
+
1101
+ case Opcode.OP_2DUP:
1102
+ // (x1 x2 -- x1 x2 x1 x2)
1103
+ if (this.stack.length < 2) {
1104
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1105
+ return false;
1106
+ }
1107
+ buf1 = stacktop(-2);
1108
+ buf2 = stacktop(-1);
1109
+ var1 = vartop(-2);
1110
+ var2 = vartop(-1);
1111
+ this.stack.push(Buffer.from(buf1), `$${var1}`);
1112
+ this.stack.push(Buffer.from(buf2), `$${var2}`);
1113
+ break;
1114
+
1115
+ case Opcode.OP_3DUP:
1116
+ // (x1 x2 x3 -- x1 x2 x3 x1 x2 x3)
1117
+ if (this.stack.length < 3) {
1118
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1119
+ return false;
1120
+ }
1121
+ buf1 = stacktop(-3);
1122
+ buf2 = stacktop(-2);
1123
+ var buf3 = stacktop(-1);
1124
+ var1 = vartop(-3);
1125
+ var2 = vartop(-2);
1126
+ var3 = vartop(-1);
1127
+ this.stack.push(Buffer.from(buf1), `$${var1}`);
1128
+ this.stack.push(Buffer.from(buf2), `$${var2}`);
1129
+ this.stack.push(Buffer.from(buf3), `$${var3}`);
1130
+ break;
1131
+
1132
+ case Opcode.OP_2OVER:
1133
+ // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2)
1134
+ if (this.stack.length < 4) {
1135
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1136
+ return false;
1137
+ }
1138
+ buf1 = stacktop(-4);
1139
+ buf2 = stacktop(-3);
1140
+ var1 = vartop(-4);
1141
+ var2 = vartop(-3);
1142
+ this.stack.push(Buffer.from(buf1), `$${var1}`);
1143
+ this.stack.push(Buffer.from(buf2), `$${var2}`);
1144
+ break;
1145
+
1146
+ case Opcode.OP_2ROT:
1147
+ // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2)
1148
+ if (this.stack.length < 6) {
1149
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1150
+ return false;
1151
+ }
1152
+
1153
+ var1 = vartop(-6);
1154
+ var2 = vartop(-5);
1155
+
1156
+ spliced = this.stack.splice(this.stack.length - 6, 2);
1157
+ this.stack.push(spliced[0], var1);
1158
+ this.stack.push(spliced[1], var2);
1159
+ break;
1160
+
1161
+ case Opcode.OP_2SWAP:
1162
+ // (x1 x2 x3 x4 -- x3 x4 x1 x2)
1163
+ if (this.stack.length < 4) {
1164
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1165
+ return false;
1166
+ }
1167
+ var1 = vartop(-4);
1168
+ var2 = vartop(-3);
1169
+ spliced = this.stack.splice(this.stack.length - 4, 2);
1170
+ this.stack.push(spliced[0], var1);
1171
+ this.stack.push(spliced[1], var2);
1172
+ break;
1173
+
1174
+ case Opcode.OP_IFDUP:
1175
+ // (x - 0 | x x)
1176
+ if (this.stack.length < 1) {
1177
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1178
+ return false;
1179
+ }
1180
+ buf = stacktop(-1);
1181
+ fValue = Interpreter.castToBool(buf);
1182
+ if (fValue) {
1183
+ var1 = vartop(-1);
1184
+ this.stack.push(Buffer.from(buf), `$${var1}`);
1185
+ }
1186
+ break;
1187
+
1188
+ case Opcode.OP_DEPTH:
1189
+ // -- stacksize
1190
+ buf = new BN(this.stack.length).toScriptNumBuffer();
1191
+ this.stack.push(buf, '$depth');
1192
+ break;
1193
+
1194
+ case Opcode.OP_DROP:
1195
+ // (x -- )
1196
+ if (this.stack.length < 1) {
1197
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1198
+ return false;
1199
+ }
1200
+ this.stack.pop();
1201
+ break;
1202
+
1203
+ case Opcode.OP_DUP:
1204
+ // (x -- x x)
1205
+ if (this.stack.length < 1) {
1206
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1207
+ return false;
1208
+ }
1209
+ var1 = vartop(-1);
1210
+ this.stack.push(Buffer.from(stacktop(-1)), `$${var1}`);
1211
+ break;
1212
+
1213
+ case Opcode.OP_NIP:
1214
+ // (x1 x2 -- x2)
1215
+ if (this.stack.length < 2) {
1216
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1217
+ return false;
1218
+ }
1219
+ this.stack.splice(this.stack.length - 2, 1);
1220
+ break;
1221
+
1222
+ case Opcode.OP_OVER:
1223
+ // (x1 x2 -- x1 x2 x1)
1224
+ if (this.stack.length < 2) {
1225
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1226
+ return false;
1227
+ }
1228
+ var2 = vartop(-2);
1229
+ this.stack.push(Buffer.from(stacktop(-2)), `$${var2}`);
1230
+ break;
1231
+
1232
+ case Opcode.OP_PICK:
1233
+ case Opcode.OP_ROLL:
1234
+ // (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn)
1235
+ // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn)
1236
+ if (this.stack.length < 2) {
1237
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1238
+ return false;
1239
+ }
1240
+ buf = stacktop(-1);
1241
+ bn = BN.fromScriptNumBuffer(buf, fRequireMinimal, 4);
1242
+ n = bn.toNumber();
1243
+ this.stack.pop();
1244
+ if (n < 0 || n >= this.stack.length) {
1245
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1246
+ return false;
1247
+ }
1248
+ buf = stacktop(-n - 1);
1249
+ var1 = vartop(-n - 1);
1250
+ if (opcodenum === Opcode.OP_ROLL) {
1251
+ this.stack.splice(this.stack.length - n - 1, 1);
1252
+ this.stack.push(Buffer.from(buf), var1);
1253
+ } else {
1254
+ this.stack.push(Buffer.from(buf), `$${var1}`);
1255
+ }
1256
+
1257
+ break;
1258
+
1259
+ case Opcode.OP_ROT:
1260
+ // (x1 x2 x3 -- x2 x3 x1)
1261
+ // x2 x1 x3 after first swap
1262
+ // x2 x3 x1 after second swap
1263
+ if (this.stack.length < 3) {
1264
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1265
+ return false;
1266
+ }
1267
+ x1 = stacktop(-3);
1268
+ x2 = stacktop(-2);
1269
+ var x3 = stacktop(-1);
1270
+ var1 = vartop(-3);
1271
+ var2 = vartop(-2);
1272
+ var3 = vartop(-1);
1273
+ this.stack.write(-3, x2);
1274
+ this.stack.write(-2, x3);
1275
+ this.stack.write(-1, x1);
1276
+ this.stack.updateTopVars([var1, var3, var2]);
1277
+ break;
1278
+
1279
+ case Opcode.OP_SWAP:
1280
+ // (x1 x2 -- x2 x1)
1281
+ if (this.stack.length < 2) {
1282
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1283
+ return false;
1284
+ }
1285
+ x1 = stacktop(-2);
1286
+ x2 = stacktop(-1);
1287
+ var1 = vartop(-2);
1288
+ var2 = vartop(-1);
1289
+ this.stack.write(-2, x2);
1290
+ this.stack.write(-1, x1);
1291
+ this.stack.updateTopVars([var1, var2]);
1292
+ break;
1293
+
1294
+ case Opcode.OP_TUCK:
1295
+ // (x1 x2 -- x2 x1 x2)
1296
+ if (this.stack.length < 2) {
1297
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1298
+ return false;
1299
+ }
1300
+
1301
+ var1 = vartop(-2);
1302
+ var2 = vartop(-1);
1303
+
1304
+ this.stack.splice(this.stack.length - 2, 0, Buffer.from(stacktop(-1)));
1305
+ this.stack.updateTopVars([var2, var1, `$${var2}`]);
1306
+ break;
1307
+
1308
+ case Opcode.OP_SIZE:
1309
+ // (in -- in size)
1310
+ if (this.stack.length < 1) {
1311
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1312
+ return false;
1313
+ }
1314
+ bn = new BN(stacktop(-1).length);
1315
+ this.stack.push(bn.toScriptNumBuffer(), `$size`);
1316
+ break;
1317
+
1318
+ //
1319
+ // Bitwise logic
1320
+ //
1321
+ case Opcode.OP_AND:
1322
+ case Opcode.OP_OR:
1323
+ case Opcode.OP_XOR:
1324
+ // (x1 x2 - out)
1325
+ if (this.stack.length < 2) {
1326
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1327
+ return false;
1328
+ }
1329
+ buf1 = stacktop(-2);
1330
+ buf2 = stacktop(-1);
1331
+
1332
+ // Inputs must be the same size
1333
+ if (buf1.length !== buf2.length) {
1334
+ this.errstr = 'SCRIPT_ERR_INVALID_OPERAND_SIZE';
1335
+ return false;
1336
+ }
1337
+
1338
+ // To avoid allocating, we modify vch1 in place.
1339
+ switch (opcodenum) {
1340
+ case Opcode.OP_AND:
1341
+ for (let i = 0; i < buf1.length; i++) {
1342
+ buf1[i] &= buf2[i];
1343
+ }
1344
+ break;
1345
+ case Opcode.OP_OR:
1346
+ for (let i = 0; i < buf1.length; i++) {
1347
+ buf1[i] |= buf2[i];
1348
+ }
1349
+ break;
1350
+ case Opcode.OP_XOR:
1351
+ for (let i = 0; i < buf1.length; i++) {
1352
+ buf1[i] ^= buf2[i];
1353
+ }
1354
+ break;
1355
+ default:
1356
+ break;
1357
+ }
1358
+
1359
+ // And pop vch2.
1360
+ this.stack.pop();
1361
+ break;
1362
+
1363
+ case Opcode.OP_INVERT:
1364
+ // (x -- out)
1365
+ if (this.stack.length < 1) {
1366
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1367
+ }
1368
+ buf = stacktop(-1);
1369
+ for (let i = 0; i < buf.length; i++) {
1370
+ buf[i] = ~buf[i];
1371
+ }
1372
+ break;
1373
+
1374
+ case Opcode.OP_LSHIFT:
1375
+ case Opcode.OP_RSHIFT:
1376
+ // (x n -- out)
1377
+ if (this.stack.length < 2) {
1378
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1379
+ return false;
1380
+ }
1381
+ buf1 = stacktop(-2);
1382
+ if (buf1.length === 0) {
1383
+ this.stack.pop();
1384
+ } else {
1385
+ bn1 = new BN(buf1);
1386
+ bn2 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, 4);
1387
+ n = bn2.toNumber();
1388
+ if (n < 0) {
1389
+ this.errstr = 'SCRIPT_ERR_INVALID_NUMBER_RANGE';
1390
+ return false;
1391
+ }
1392
+ this.stack.pop();
1393
+ this.stack.pop();
1394
+ let shifted;
1395
+ if (opcodenum === Opcode.OP_LSHIFT) {
1396
+ shifted = bn1.ushln(n);
1397
+ }
1398
+ if (opcodenum === Opcode.OP_RSHIFT) {
1399
+ shifted = bn1.ushrn(n);
1400
+ }
1401
+ // bitcoin client implementation of l/rshift is unconventional, therefore this implementation is a bit unconventional
1402
+ // bn library has shift functions however it expands the carried bits into a new byte
1403
+ // in contrast to the bitcoin client implementation which drops off the carried bits
1404
+ // in other words, if operand was 1 byte then we put 1 byte back on the stack instead of expanding to more shifted bytes
1405
+ let bufShifted = padBufferToSize(
1406
+ Buffer.from(shifted.toArray().slice(buf1.length * -1)),
1407
+ buf1.length,
1408
+ );
1409
+ this.stack.push(bufShifted);
1410
+ }
1411
+ break;
1412
+
1413
+ case Opcode.OP_EQUAL:
1414
+ case Opcode.OP_EQUALVERIFY:
1415
+ // case Opcode.OP_NOTEQUAL: // use Opcode.OP_NUMNOTEQUAL
1416
+ // (x1 x2 - bool)
1417
+ if (this.stack.length < 2) {
1418
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1419
+ return false;
1420
+ }
1421
+ buf1 = stacktop(-2);
1422
+ buf2 = stacktop(-1);
1423
+ var fEqual = buf1.toString('hex') === buf2.toString('hex');
1424
+ this.stack.pop();
1425
+ this.stack.pop();
1426
+ this.stack.push(fEqual ? Interpreter.getTrue() : Interpreter.getFalse());
1427
+ if (opcodenum === Opcode.OP_EQUALVERIFY) {
1428
+ if (fEqual) {
1429
+ this.stack.pop();
1430
+ } else {
1431
+ this.errstr = 'SCRIPT_ERR_EQUALVERIFY';
1432
+ return false;
1433
+ }
1434
+ }
1435
+ break;
1436
+
1437
+ //
1438
+ // Numeric
1439
+ //
1440
+ case Opcode.OP_1ADD:
1441
+ case Opcode.OP_1SUB:
1442
+ case Opcode.OP_NEGATE:
1443
+ case Opcode.OP_ABS:
1444
+ case Opcode.OP_NOT:
1445
+ case Opcode.OP_0NOTEQUAL:
1446
+ // (in -- out)
1447
+ if (this.stack.length < 1) {
1448
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1449
+ return false;
1450
+ }
1451
+ buf = stacktop(-1);
1452
+ bn = BN.fromScriptNumBuffer(buf, fRequireMinimal);
1453
+ switch (opcodenum) {
1454
+ case Opcode.OP_1ADD:
1455
+ bn = bn.add(BN.One);
1456
+ break;
1457
+ case Opcode.OP_1SUB:
1458
+ bn = bn.sub(BN.One);
1459
+ break;
1460
+ case Opcode.OP_NEGATE:
1461
+ bn = bn.neg();
1462
+ break;
1463
+ case Opcode.OP_ABS:
1464
+ if (bn.cmp(BN.Zero) < 0) {
1465
+ bn = bn.neg();
1466
+ }
1467
+ break;
1468
+ case Opcode.OP_NOT:
1469
+ bn = new BN((bn.cmp(BN.Zero) === 0) + 0);
1470
+ break;
1471
+ case Opcode.OP_0NOTEQUAL:
1472
+ bn = new BN((bn.cmp(BN.Zero) !== 0) + 0);
1473
+ break;
1474
+ // default: assert(!'invalid opcode'); break; // TODO: does this ever occur?
1475
+ }
1476
+ this.stack.pop();
1477
+ this.stack.push(bn.toScriptNumBuffer());
1478
+ break;
1479
+
1480
+ case Opcode.OP_ADD:
1481
+ case Opcode.OP_SUB:
1482
+ case Opcode.OP_MUL:
1483
+ case Opcode.OP_MOD:
1484
+ case Opcode.OP_DIV:
1485
+ case Opcode.OP_BOOLAND:
1486
+ case Opcode.OP_BOOLOR:
1487
+ case Opcode.OP_NUMEQUAL:
1488
+ case Opcode.OP_NUMEQUALVERIFY:
1489
+ case Opcode.OP_NUMNOTEQUAL:
1490
+ case Opcode.OP_LESSTHAN:
1491
+ case Opcode.OP_GREATERTHAN:
1492
+ case Opcode.OP_LESSTHANOREQUAL:
1493
+ case Opcode.OP_GREATERTHANOREQUAL:
1494
+ case Opcode.OP_MIN:
1495
+ case Opcode.OP_MAX:
1496
+ // (x1 x2 -- out)
1497
+ if (this.stack.length < 2) {
1498
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1499
+ return false;
1500
+ }
1501
+ bn1 = BN.fromScriptNumBuffer(stacktop(-2), fRequireMinimal);
1502
+ bn2 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal);
1503
+ bn = new BN(0);
1504
+
1505
+ switch (opcodenum) {
1506
+ case Opcode.OP_ADD:
1507
+ bn = bn1.add(bn2);
1508
+ break;
1509
+
1510
+ case Opcode.OP_SUB:
1511
+ bn = bn1.sub(bn2);
1512
+ break;
1513
+
1514
+ case Opcode.OP_MUL:
1515
+ bn = bn1.mul(bn2);
1516
+ break;
1517
+
1518
+ case Opcode.OP_DIV:
1519
+ // denominator must not be 0
1520
+ if (bn2 === 0) {
1521
+ this.errstr = 'SCRIPT_ERR_DIV_BY_ZERO';
1522
+ return false;
1523
+ }
1524
+ bn = bn1.div(bn2);
1525
+ break;
1526
+
1527
+ case Opcode.OP_MOD:
1528
+ // divisor must not be 0
1529
+ if (bn2 === 0) {
1530
+ this.errstr = 'SCRIPT_ERR_DIV_BY_ZERO';
1531
+ return false;
1532
+ }
1533
+ bn = bn1.mod(bn2);
1534
+ break;
1535
+
1536
+ case Opcode.OP_BOOLAND:
1537
+ bn = new BN((bn1.cmp(BN.Zero) !== 0 && bn2.cmp(BN.Zero) !== 0) + 0);
1538
+ break;
1539
+ // case Opcode.OP_BOOLOR: bn = (bn1 !== bnZero || bn2 !== bnZero); break;
1540
+ case Opcode.OP_BOOLOR:
1541
+ bn = new BN((bn1.cmp(BN.Zero) !== 0 || bn2.cmp(BN.Zero) !== 0) + 0);
1542
+ break;
1543
+ // case Opcode.OP_NUMEQUAL: bn = (bn1 === bn2); break;
1544
+ case Opcode.OP_NUMEQUAL:
1545
+ bn = new BN((bn1.cmp(bn2) === 0) + 0);
1546
+ break;
1547
+ // case Opcode.OP_NUMEQUALVERIFY: bn = (bn1 === bn2); break;
1548
+ case Opcode.OP_NUMEQUALVERIFY:
1549
+ bn = new BN((bn1.cmp(bn2) === 0) + 0);
1550
+ break;
1551
+ // case Opcode.OP_NUMNOTEQUAL: bn = (bn1 !== bn2); break;
1552
+ case Opcode.OP_NUMNOTEQUAL:
1553
+ bn = new BN((bn1.cmp(bn2) !== 0) + 0);
1554
+ break;
1555
+ // case Opcode.OP_LESSTHAN: bn = (bn1 < bn2); break;
1556
+ case Opcode.OP_LESSTHAN:
1557
+ bn = new BN((bn1.cmp(bn2) < 0) + 0);
1558
+ break;
1559
+ // case Opcode.OP_GREATERTHAN: bn = (bn1 > bn2); break;
1560
+ case Opcode.OP_GREATERTHAN:
1561
+ bn = new BN((bn1.cmp(bn2) > 0) + 0);
1562
+ break;
1563
+ // case Opcode.OP_LESSTHANOREQUAL: bn = (bn1 <= bn2); break;
1564
+ case Opcode.OP_LESSTHANOREQUAL:
1565
+ bn = new BN((bn1.cmp(bn2) <= 0) + 0);
1566
+ break;
1567
+ // case Opcode.OP_GREATERTHANOREQUAL: bn = (bn1 >= bn2); break;
1568
+ case Opcode.OP_GREATERTHANOREQUAL:
1569
+ bn = new BN((bn1.cmp(bn2) >= 0) + 0);
1570
+ break;
1571
+ case Opcode.OP_MIN:
1572
+ bn = bn1.cmp(bn2) < 0 ? bn1 : bn2;
1573
+ break;
1574
+ case Opcode.OP_MAX:
1575
+ bn = bn1.cmp(bn2) > 0 ? bn1 : bn2;
1576
+ break;
1577
+ // default: assert(!'invalid opcode'); break; //TODO: does this ever occur?
1578
+ }
1579
+ this.stack.pop();
1580
+ this.stack.pop();
1581
+ this.stack.push(bn.toScriptNumBuffer());
1582
+
1583
+ if (opcodenum === Opcode.OP_NUMEQUALVERIFY) {
1584
+ // if (CastToBool(stacktop(-1)))
1585
+ if (Interpreter.castToBool(stacktop(-1))) {
1586
+ this.stack.pop();
1587
+ } else {
1588
+ this.errstr = 'SCRIPT_ERR_NUMEQUALVERIFY';
1589
+ return false;
1590
+ }
1591
+ }
1592
+ break;
1593
+
1594
+ case Opcode.OP_WITHIN:
1595
+ // (x min max -- out)
1596
+ if (this.stack.length < 3) {
1597
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1598
+ return false;
1599
+ }
1600
+ bn1 = BN.fromScriptNumBuffer(stacktop(-3), fRequireMinimal);
1601
+ bn2 = BN.fromScriptNumBuffer(stacktop(-2), fRequireMinimal);
1602
+ var bn3 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal);
1603
+ // bool fValue = (bn2 <= bn1 && bn1 < bn3);
1604
+ fValue = bn2.cmp(bn1) <= 0 && bn1.cmp(bn3) < 0;
1605
+ this.stack.pop();
1606
+ this.stack.pop();
1607
+ this.stack.pop();
1608
+ this.stack.push(fValue ? Interpreter.getTrue() : Interpreter.getFalse());
1609
+ break;
1610
+
1611
+ //
1612
+ // Crypto
1613
+ //
1614
+ case Opcode.OP_RIPEMD160:
1615
+ case Opcode.OP_SHA1:
1616
+ case Opcode.OP_SHA256:
1617
+ case Opcode.OP_HASH160:
1618
+ case Opcode.OP_HASH256:
1619
+ // (in -- hash)
1620
+ if (this.stack.length < 1) {
1621
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1622
+ return false;
1623
+ }
1624
+ buf = stacktop(-1);
1625
+ // valtype vchHash((opcode === Opcode.OP_RIPEMD160 ||
1626
+ // opcode === Opcode.OP_SHA1 || opcode === Opcode.OP_HASH160) ? 20 : 32);
1627
+ var bufHash;
1628
+ if (opcodenum === Opcode.OP_RIPEMD160) {
1629
+ bufHash = Hash.ripemd160(buf);
1630
+ } else if (opcodenum === Opcode.OP_SHA1) {
1631
+ bufHash = Hash.sha1(buf);
1632
+ } else if (opcodenum === Opcode.OP_SHA256) {
1633
+ bufHash = Hash.sha256(buf);
1634
+ } else if (opcodenum === Opcode.OP_HASH160) {
1635
+ bufHash = Hash.sha256ripemd160(buf);
1636
+ } else if (opcodenum === Opcode.OP_HASH256) {
1637
+ bufHash = Hash.sha256sha256(buf);
1638
+ }
1639
+ this.stack.pop();
1640
+ this.stack.push(bufHash);
1641
+ break;
1642
+
1643
+ case Opcode.OP_CODESEPARATOR:
1644
+ // Hash starts after the code separator
1645
+ this.pbegincodehash = this.pc;
1646
+ break;
1647
+
1648
+ case Opcode.OP_CHECKSIG:
1649
+ case Opcode.OP_CHECKSIGVERIFY:
1650
+ // (sig pubkey -- bool)
1651
+ if (this.stack.length < 2) {
1652
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1653
+ return false;
1654
+ }
1655
+
1656
+ bufSig = stacktop(-2);
1657
+ bufPubkey = stacktop(-1);
1658
+
1659
+ if (!this.checkSignatureEncoding(bufSig) || !this.checkPubkeyEncoding(bufPubkey)) {
1660
+ return false;
1661
+ }
1662
+
1663
+ // Subset of script starting at the most recent codeseparator
1664
+ // CScript scriptCode(pbegincodehash, pend);
1665
+ subscript = this.subscript();
1666
+
1667
+ // Drop the signature, since there's no way for a signature to sign itself
1668
+ var tmpScript = new Script().add(bufSig);
1669
+ subscript.findAndDelete(tmpScript);
1670
+
1671
+ try {
1672
+ sig = Signature.fromTxFormat(bufSig);
1673
+ pubkey = PublicKey.fromBuffer(bufPubkey, false);
1674
+
1675
+ fSuccess = this.tx.verifySignature(
1676
+ sig,
1677
+ pubkey,
1678
+ this.nin,
1679
+ subscript,
1680
+ this.satoshisBN,
1681
+ this.flags,
1682
+ );
1683
+ } catch (e) {
1684
+ console.error('invalid sig or pubkey', e);
1685
+ // invalid sig or pubkey
1686
+ fSuccess = false;
1687
+ }
1688
+
1689
+ if (!fSuccess && this.flags & Interpreter.SCRIPT_VERIFY_NULLFAIL && bufSig.length) {
1690
+ this.errstr = 'SCRIPT_ERR_NULLFAIL';
1691
+ return false;
1692
+ }
1693
+
1694
+ this.stack.pop();
1695
+ this.stack.pop();
1696
+
1697
+ // stack.push_back(fSuccess ? vchTrue : vchFalse);
1698
+ this.stack.push(fSuccess ? Interpreter.getTrue() : Interpreter.getFalse());
1699
+ if (opcodenum === Opcode.OP_CHECKSIGVERIFY) {
1700
+ if (fSuccess) {
1701
+ this.stack.pop();
1702
+ } else {
1703
+ this.errstr = 'SCRIPT_ERR_CHECKSIGVERIFY';
1704
+ return false;
1705
+ }
1706
+ }
1707
+ break;
1708
+
1709
+ case Opcode.OP_CHECKMULTISIG:
1710
+ case Opcode.OP_CHECKMULTISIGVERIFY:
1711
+ // ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool)
1712
+
1713
+ var i = 1;
1714
+ if (this.stack.length < i) {
1715
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1716
+ return false;
1717
+ }
1718
+
1719
+ var nKeysCount = BN.fromScriptNumBuffer(stacktop(-i), fRequireMinimal).toNumber();
1720
+ // TODO: Keys and opcount are parameterized in client. No magic numbers!
1721
+ if (nKeysCount < 0 || nKeysCount > 20) {
1722
+ this.errstr = 'SCRIPT_ERR_PUBKEY_COUNT';
1723
+ return false;
1724
+ }
1725
+ this.nOpCount += nKeysCount;
1726
+ if (this.nOpCount > Interpreter.MAX_OPCODE_COUNT) {
1727
+ this.errstr = 'SCRIPT_ERR_OP_COUNT';
1728
+ return false;
1729
+ }
1730
+ // int ikey = ++i;
1731
+ var ikey = ++i;
1732
+ i += nKeysCount;
1733
+
1734
+ // ikey2 is the position of last non-signature item in
1735
+ // the stack. Top stack item = 1. With
1736
+ // SCRIPT_VERIFY_NULLFAIL, this is used for cleanup if
1737
+ // operation fails.
1738
+ var ikey2 = nKeysCount + 2;
1739
+
1740
+ if (this.stack.length < i) {
1741
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1742
+ return false;
1743
+ }
1744
+
1745
+ var nSigsCount = BN.fromScriptNumBuffer(stacktop(-i), fRequireMinimal).toNumber();
1746
+ if (nSigsCount < 0 || nSigsCount > nKeysCount) {
1747
+ this.errstr = 'SCRIPT_ERR_SIG_COUNT';
1748
+ return false;
1749
+ }
1750
+ // int isig = ++i;
1751
+ var isig = ++i;
1752
+ i += nSigsCount;
1753
+ if (this.stack.length < i) {
1754
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1755
+ return false;
1756
+ }
1757
+
1758
+ // Subset of script starting at the most recent codeseparator
1759
+ subscript = this.subscript();
1760
+
1761
+ // Drop the signatures, since there's no way for a signature to sign itself
1762
+ for (var k = 0; k < nSigsCount; k++) {
1763
+ bufSig = stacktop(-isig - k);
1764
+ subscript.findAndDelete(new Script().add(bufSig));
1765
+ }
1766
+
1767
+ fSuccess = true;
1768
+ while (fSuccess && nSigsCount > 0) {
1769
+ // valtype& vchSig = stacktop(-isig);
1770
+ bufSig = stacktop(-isig);
1771
+ // valtype& vchPubKey = stacktop(-ikey);
1772
+ bufPubkey = stacktop(-ikey);
1773
+
1774
+ if (!this.checkSignatureEncoding(bufSig) || !this.checkPubkeyEncoding(bufPubkey)) {
1775
+ return false;
1776
+ }
1777
+
1778
+ var fOk;
1779
+ try {
1780
+ sig = Signature.fromTxFormat(bufSig);
1781
+ pubkey = PublicKey.fromBuffer(bufPubkey, false);
1782
+ fOk = this.tx.verifySignature(
1783
+ sig,
1784
+ pubkey,
1785
+ this.nin,
1786
+ subscript,
1787
+ this.satoshisBN,
1788
+ this.flags,
1789
+ );
1790
+ } catch (e) {
1791
+ // invalid sig or pubkey
1792
+ fOk = false;
1793
+ }
1794
+
1795
+ if (fOk) {
1796
+ isig++;
1797
+ nSigsCount--;
1798
+ }
1799
+ ikey++;
1800
+ nKeysCount--;
1801
+
1802
+ // If there are more signatures left than keys left,
1803
+ // then too many signatures have failed
1804
+ if (nSigsCount > nKeysCount) {
1805
+ fSuccess = false;
1806
+ }
1807
+ }
1808
+
1809
+ // Clean up stack of actual arguments
1810
+ while (i-- > 1) {
1811
+ if (
1812
+ !fSuccess &&
1813
+ this.flags & Interpreter.SCRIPT_VERIFY_NULLFAIL &&
1814
+ !ikey2 &&
1815
+ stacktop(-1).length
1816
+ ) {
1817
+ this.errstr = 'SCRIPT_ERR_NULLFAIL';
1818
+ return false;
1819
+ }
1820
+
1821
+ if (ikey2 > 0) {
1822
+ ikey2--;
1823
+ }
1824
+
1825
+ this.stack.pop();
1826
+ }
1827
+
1828
+ // A bug causes CHECKMULTISIG to consume one extra argument
1829
+ // whose contents were not checked in any way.
1830
+ //
1831
+ // Unfortunately this is a potential source of mutability,
1832
+ // so optionally verify it is exactly equal to zero prior
1833
+ // to removing it from the stack.
1834
+ if (this.stack.length < 1) {
1835
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1836
+ return false;
1837
+ }
1838
+ if (this.flags & Interpreter.SCRIPT_VERIFY_NULLDUMMY && stacktop(-1).length) {
1839
+ this.errstr = 'SCRIPT_ERR_SIG_NULLDUMMY';
1840
+ return false;
1841
+ }
1842
+ this.stack.pop();
1843
+
1844
+ this.stack.push(fSuccess ? Interpreter.getTrue() : Interpreter.getFalse());
1845
+
1846
+ if (opcodenum === Opcode.OP_CHECKMULTISIGVERIFY) {
1847
+ if (fSuccess) {
1848
+ this.stack.pop();
1849
+ } else {
1850
+ this.errstr = 'SCRIPT_ERR_CHECKMULTISIGVERIFY';
1851
+ return false;
1852
+ }
1853
+ }
1854
+ break;
1855
+
1856
+ //
1857
+ // Byte string operations
1858
+ //
1859
+ case Opcode.OP_CAT:
1860
+ if (this.stack.length < 2) {
1861
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1862
+ return false;
1863
+ }
1864
+
1865
+ buf1 = stacktop(-2);
1866
+ buf2 = stacktop(-1);
1867
+ if (buf1.length + buf2.length > Interpreter.MAX_SCRIPT_ELEMENT_SIZE) {
1868
+ this.errstr = 'SCRIPT_ERR_PUSH_SIZE';
1869
+ return false;
1870
+ }
1871
+ this.stack.write(-2, Buffer.concat([buf1, buf2]));
1872
+ this.stack.pop();
1873
+ break;
1874
+
1875
+ case Opcode.OP_SPLIT:
1876
+ if (this.stack.length < 2) {
1877
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1878
+ return false;
1879
+ }
1880
+ buf1 = stacktop(-2);
1881
+
1882
+ // Make sure the split point is apropriate.
1883
+ var position = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal).toNumber();
1884
+ if (position < 0 || position > buf1.length) {
1885
+ this.errstr = 'SCRIPT_ERR_INVALID_SPLIT_RANGE';
1886
+ return false;
1887
+ }
1888
+
1889
+ // Prepare the results in their own buffer as `data`
1890
+ // will be invalidated.
1891
+ // Copy buffer data, to slice it before
1892
+ var n1 = Buffer.from(buf1);
1893
+
1894
+ // Replace existing stack values by the new values.
1895
+ this.stack.write(-2, n1.slice(0, position));
1896
+ this.stack.write(-1, n1.slice(position));
1897
+ break;
1898
+
1899
+ //
1900
+ // Conversion operations
1901
+ //
1902
+ case Opcode.OP_NUM2BIN:
1903
+ // (in -- out)
1904
+ if (this.stack.length < 2) {
1905
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1906
+ return false;
1907
+ }
1908
+
1909
+ var size = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal).toNumber();
1910
+ if (size > Interpreter.MAX_SCRIPT_ELEMENT_SIZE) {
1911
+ this.errstr = 'SCRIPT_ERR_PUSH_SIZE';
1912
+ return false;
1913
+ }
1914
+
1915
+ this.stack.pop();
1916
+ var rawnum = stacktop(-1);
1917
+
1918
+ // Try to see if we can fit that number in the number of
1919
+ // byte requested.
1920
+ rawnum = Interpreter._minimallyEncode(rawnum);
1921
+
1922
+ if (rawnum.length > size) {
1923
+ // We definitively cannot.
1924
+ this.errstr = 'SCRIPT_ERR_IMPOSSIBLE_ENCODING';
1925
+ return false;
1926
+ }
1927
+
1928
+ // We already have an element of the right size, we
1929
+ // don't need to do anything.
1930
+ if (rawnum.length === size) {
1931
+ this.stack.write(-1, rawnum);
1932
+ break;
1933
+ }
1934
+
1935
+ var signbit = 0x00;
1936
+ if (rawnum.length > 0) {
1937
+ signbit = rawnum[rawnum.length - 1] & 0x80;
1938
+ rawnum[rawnum.length - 1] &= 0x7f;
1939
+ }
1940
+
1941
+ var num = Buffer.alloc(size);
1942
+ rawnum.copy(num, 0);
1943
+
1944
+ var l = rawnum.length - 1;
1945
+ while (l++ < size - 2) {
1946
+ num[l] = 0x00;
1947
+ }
1948
+
1949
+ num[l] = signbit;
1950
+
1951
+ this.stack.write(-1, num);
1952
+ break;
1953
+
1954
+ case Opcode.OP_BIN2NUM:
1955
+ // (in -- out)
1956
+ if (this.stack.length < 1) {
1957
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
1958
+ return false;
1959
+ }
1960
+
1961
+ buf1 = stacktop(-1);
1962
+ buf2 = Interpreter._minimallyEncode(buf1);
1963
+
1964
+ this.stack.write(-1, buf2);
1965
+
1966
+ // The resulting number must be a valid number.
1967
+ if (!Interpreter._isMinimallyEncoded(buf2)) {
1968
+ this.errstr = 'SCRIPT_ERR_INVALID_NUMBER_RANGE';
1969
+ return false;
1970
+ }
1971
+ break;
1972
+
1973
+ default:
1974
+ this.errstr = 'SCRIPT_ERR_BAD_OPCODE';
1975
+ return false;
1976
+ }
1977
+ }
1978
+
1979
+ // only when next opcode is evaluate opcode, we update stack
1980
+ if (this.vfExec.indexOf(false) === -1) {
1981
+ this._callbackStack(this.stack, this.pc, scriptType);
1982
+ }
1983
+
1984
+ return true;
1985
+ };
1986
+
1987
+
1988
+ module.exports = Interpreter;