@smartledger/bsv 5.5.0 → 5.5.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 (93) hide show
  1. package/.mocharc.json +5 -0
  2. package/CHANGELOG.md +40 -0
  3. package/README.md +38 -38
  4. package/bsv-covenant.min.js +2 -2
  5. package/bsv-gdaf.min.js +2 -2
  6. package/bsv-ltp.min.js +2 -2
  7. package/bsv-smartcontract.min.js +2 -2
  8. package/bsv.bundle.js +2 -2
  9. package/bsv.min.js +2 -2
  10. package/docs/MODULE_REFERENCE_COMPLETE.md +27 -27
  11. package/docs/advanced/UTXO_MANAGER_GUIDE.md +1 -1
  12. package/docs/getting-started/INSTALLATION.md +23 -23
  13. package/docs/getting-started/QUICK_START.md +7 -7
  14. package/docs/migration/FROM_BSV_1_5_6.md +5 -5
  15. package/lib/smart_contract/covenant_helpers.js +3 -3
  16. package/lib/smart_contract/index.js +4 -5
  17. package/package.json +5 -1
  18. package/test/address.js +629 -0
  19. package/test/block/block.js +239 -0
  20. package/test/block/blockheader.js +270 -0
  21. package/test/block/merkleblock.js +207 -0
  22. package/test/cli/smoke.js +261 -0
  23. package/test/credentials-test.js +329 -0
  24. package/test/crypto/bn.js +168 -0
  25. package/test/crypto/ecdsa.js +328 -0
  26. package/test/crypto/elliptic-fixed.js +61 -0
  27. package/test/crypto/hash.browser.js +121 -0
  28. package/test/crypto/hash.js +122 -0
  29. package/test/crypto/point.js +193 -0
  30. package/test/crypto/random.js +32 -0
  31. package/test/crypto/security.js +127 -0
  32. package/test/crypto/shamir.js +169 -0
  33. package/test/crypto/signature.js +318 -0
  34. package/test/data/bip69.json +215 -0
  35. package/test/data/bitcoind/base58_keys_invalid.json +152 -0
  36. package/test/data/bitcoind/base58_keys_valid.json +452 -0
  37. package/test/data/bitcoind/blocks.json +27 -0
  38. package/test/data/bitcoind/script_tests.json +2244 -0
  39. package/test/data/bitcoind/sig_canonical.json +7 -0
  40. package/test/data/bitcoind/sig_noncanonical.json +22 -0
  41. package/test/data/bitcoind/tx_invalid.json +177 -0
  42. package/test/data/bitcoind/tx_valid.json +224 -0
  43. package/test/data/blk86756-testnet.dat +0 -0
  44. package/test/data/blk86756-testnet.js +12 -0
  45. package/test/data/blk86756-testnet.json +684 -0
  46. package/test/data/ecdsa.json +230 -0
  47. package/test/data/merkleblocks.js +486 -0
  48. package/test/data/messages.json +22 -0
  49. package/test/data/sighash.json +1004 -0
  50. package/test/data/tx_creation.json +85 -0
  51. package/test/ecies/bitcore-ecies.js +170 -0
  52. package/test/ecies/electrum-ecies.js +206 -0
  53. package/test/encoding/base58.js +131 -0
  54. package/test/encoding/base58check.js +136 -0
  55. package/test/encoding/bufferreader.js +328 -0
  56. package/test/encoding/bufferwriter.js +160 -0
  57. package/test/encoding/varint.js +104 -0
  58. package/test/gdaf/canonicalize.js +140 -0
  59. package/test/hdkeys.js +365 -0
  60. package/test/hdprivatekey.js +330 -0
  61. package/test/hdpublickey.js +293 -0
  62. package/test/index.js +16 -0
  63. package/test/ltp/right.js +198 -0
  64. package/test/message/message.js +190 -0
  65. package/test/mnemonic/data/fixtures.json +300 -0
  66. package/test/mnemonic/mnemonic.js +245 -0
  67. package/test/mnemonic/mocha.opts +1 -0
  68. package/test/mnemonic/pbkdf2.test.js +43 -0
  69. package/test/networks.js +162 -0
  70. package/test/opcode.js +161 -0
  71. package/test/privatekey.js +430 -0
  72. package/test/publickey.js +411 -0
  73. package/test/script/genesis_limits.js +80 -0
  74. package/test/script/interpreter.js +723 -0
  75. package/test/script/script.js +1256 -0
  76. package/test/script/string_ops.js +72 -0
  77. package/test/smart_contract/covenants.js +247 -0
  78. package/test/smart_contract/dsl_debugger.js +103 -0
  79. package/test/smart_contract/token_generalized.js +187 -0
  80. package/test/transaction/deserialize.js +33 -0
  81. package/test/transaction/input/input.js +92 -0
  82. package/test/transaction/input/multisig.js +174 -0
  83. package/test/transaction/input/multisigscripthash.js +111 -0
  84. package/test/transaction/input/publickey.js +68 -0
  85. package/test/transaction/input/publickeyhash.js +59 -0
  86. package/test/transaction/output.js +185 -0
  87. package/test/transaction/sighash.js +71 -0
  88. package/test/transaction/signature.js +127 -0
  89. package/test/transaction/transaction.js +1299 -0
  90. package/test/transaction/unspentoutput.js +92 -0
  91. package/test/util/js.js +76 -0
  92. package/test/util/preconditions.js +79 -0
  93. package/test/vcjwt/interop.js +126 -0
@@ -0,0 +1,723 @@
1
+ 'use strict'
2
+
3
+ var should = require('chai').should()
4
+ var bsv = require('../..')
5
+ var Interpreter = bsv.Script.Interpreter
6
+ var Transaction = bsv.Transaction
7
+ var PrivateKey = bsv.PrivateKey
8
+ var Script = bsv.Script
9
+ var BN = bsv.crypto.BN
10
+ var BufferWriter = bsv.encoding.BufferWriter
11
+ var Opcode = bsv.Opcode
12
+ var _ = require('../../lib/util/_')
13
+
14
+ var scriptTests = require('../data/bitcoind/script_tests')
15
+ var txValid = require('../data/bitcoind/tx_valid')
16
+ var txInvalid = require('../data/bitcoind/tx_invalid')
17
+
18
+ // the script string format used in bitcoind data tests
19
+ Script.fromBitcoindString = function (str) {
20
+ var bw = new BufferWriter()
21
+ var tokens = str.split(' ')
22
+ for (var i = 0; i < tokens.length; i++) {
23
+ var token = tokens[i]
24
+ if (token === '') {
25
+ continue
26
+ }
27
+
28
+ var opstr
29
+ var opcodenum
30
+ var tbuf
31
+ if (token[0] === '0' && token[1] === 'x') {
32
+ var hex = token.slice(2)
33
+ bw.write(Buffer.from(hex, 'hex'))
34
+ } else if (token[0] === '\'') {
35
+ var tstr = token.slice(1, token.length - 1)
36
+ var cbuf = Buffer.from(tstr)
37
+ tbuf = Script().add(cbuf).toBuffer()
38
+ bw.write(tbuf)
39
+ } else if (typeof Opcode['OP_' + token] !== 'undefined') {
40
+ opstr = 'OP_' + token
41
+ opcodenum = Opcode[opstr]
42
+ bw.writeUInt8(opcodenum)
43
+ } else if (typeof Opcode[token] === 'number') {
44
+ opstr = token
45
+ opcodenum = Opcode[opstr]
46
+ bw.writeUInt8(opcodenum)
47
+ } else if (!isNaN(parseInt(token))) {
48
+ var script = Script().add(new BN(token).toScriptNumBuffer())
49
+ tbuf = script.toBuffer()
50
+ bw.write(tbuf)
51
+ } else {
52
+ throw new Error('Could not determine type of script value')
53
+ }
54
+ }
55
+ var buf = bw.concat()
56
+ return this.fromBuffer(buf)
57
+ }
58
+
59
+ describe('Interpreter', function () {
60
+ it('should make a new interp', function () {
61
+ var interp = new Interpreter();
62
+ (interp instanceof Interpreter).should.equal(true)
63
+ interp.stack.length.should.equal(0)
64
+ interp.altstack.length.should.equal(0)
65
+ interp.pc.should.equal(0)
66
+ interp.pbegincodehash.should.equal(0)
67
+ interp.nOpCount.should.equal(0)
68
+ interp.vfExec.length.should.equal(0)
69
+ interp.errstr.should.equal('')
70
+ interp.flags.should.equal(0)
71
+ })
72
+ it('interpreter can set new values for stacks', function () {
73
+ const interp = new Interpreter()
74
+ interp.stack.push(Buffer.from(['stack']))
75
+ interp.stack.length.should.equal(1)
76
+ interp.altstack.push(Buffer.from(['altstack']))
77
+ interp.altstack.length.should.equal(1)
78
+ interp.set({ stack: [], altstack: [] })
79
+ interp.stack.length.should.equal(0)
80
+ interp.altstack.length.should.equal(0)
81
+ })
82
+
83
+ describe('@castToBool', function () {
84
+ it('should cast these bufs to bool correctly', function () {
85
+ Interpreter.castToBool(new BN(0).toSM({
86
+ endian: 'little'
87
+ })).should.equal(false)
88
+ Interpreter.castToBool(Buffer.from('0080', 'hex')).should.equal(false) // negative 0
89
+ Interpreter.castToBool(new BN(1).toSM({
90
+ endian: 'little'
91
+ })).should.equal(true)
92
+ Interpreter.castToBool(new BN(-1).toSM({
93
+ endian: 'little'
94
+ })).should.equal(true)
95
+
96
+ var buf = Buffer.from('00', 'hex')
97
+ var bool = BN.fromSM(buf, {
98
+ endian: 'little'
99
+ }).cmp(BN.Zero) !== 0
100
+ Interpreter.castToBool(buf).should.equal(bool)
101
+ })
102
+ })
103
+
104
+ describe('#verify', function () {
105
+ it('should verify these trivial scripts', function () {
106
+ var verified
107
+ var si = Interpreter()
108
+ verified = si.verify(Script('OP_1'), Script('OP_1'))
109
+ verified.should.equal(true)
110
+ verified = Interpreter().verify(Script('OP_1'), Script('OP_0'))
111
+ verified.should.equal(false)
112
+ verified = Interpreter().verify(Script('OP_0'), Script('OP_1'))
113
+ verified.should.equal(true)
114
+ verified = Interpreter().verify(Script('OP_CODESEPARATOR'), Script('OP_1'))
115
+ verified.should.equal(true)
116
+ verified = Interpreter().verify(Script(''), Script('OP_DEPTH OP_0 OP_EQUAL'))
117
+ verified.should.equal(true)
118
+ verified = Interpreter().verify(Script('OP_1 OP_2'), Script('OP_2 OP_EQUALVERIFY OP_1 OP_EQUAL'))
119
+ verified.should.equal(true)
120
+ verified = Interpreter().verify(Script('9 0x000000000000000010'), Script(''))
121
+ verified.should.equal(true)
122
+ verified = Interpreter().verify(Script('OP_1'), Script('OP_15 OP_ADD OP_16 OP_EQUAL'))
123
+ verified.should.equal(true)
124
+ verified = Interpreter().verify(Script('OP_0'), Script('OP_IF OP_VER OP_ELSE OP_1 OP_ENDIF'))
125
+ verified.should.equal(true)
126
+ })
127
+
128
+ it('should verify these simple transaction', function () {
129
+ // first we create a transaction
130
+ var privateKey = new PrivateKey('cSBnVM4xvxarwGQuAfQFwqDg9k5tErHUHzgWsEfD4zdwUasvqRVY')
131
+ var publicKey = privateKey.publicKey
132
+ var fromAddress = publicKey.toAddress()
133
+ var toAddress = 'mrU9pEmAx26HcbKVrABvgL7AwA5fjNFoDc'
134
+ var scriptPubkey = Script.buildPublicKeyHashOut(fromAddress)
135
+ var utxo = {
136
+ address: fromAddress,
137
+ txId: 'a477af6b2667c29670467e4e0728b685ee07b240235771862318e29ddbe58458',
138
+ outputIndex: 0,
139
+ script: scriptPubkey,
140
+ satoshis: 100000
141
+ }
142
+ var tx = new Transaction()
143
+ .from(utxo)
144
+ .to(toAddress, 100000)
145
+ .sign(privateKey, 1)
146
+
147
+ // we then extract the signature from the first input
148
+ var inputIndex = 0
149
+ var signature = tx.getSignatures(privateKey, 1)[inputIndex].signature
150
+
151
+ var scriptSig = Script.buildPublicKeyHashIn(publicKey, signature)
152
+ var flags = Interpreter.SCRIPT_VERIFY_P2SH | Interpreter.SCRIPT_VERIFY_STRICTENC
153
+ var verified = Interpreter().verify(scriptSig, scriptPubkey, tx, inputIndex, flags)
154
+ verified.should.equal(true)
155
+ })
156
+ })
157
+
158
+ describe('#script debugger', function () {
159
+ it('debugger should fire while executing script', function () {
160
+ var si = Interpreter()
161
+ let debugCount = 0
162
+ si.stepListener = function (step) {
163
+ debugCount += 1
164
+ }
165
+ si.verify(Script('OP_1 OP_2 OP_ADD'), Script('OP_3 OP_EQUAL'))
166
+ si.errstr.should.equal('')
167
+ // two scripts. first one has 3 instructions. second one has 2 instructions
168
+ debugCount.should.equal(3 + 2)
169
+ })
170
+ it('debugger error in callback should not kill executing script', function () {
171
+ var si = Interpreter()
172
+ si.stepListener = function (step) {
173
+ throw new Error('This error is expected.')
174
+ }
175
+ si.verify(Script('OP_1 OP_2 OP_ADD'), Script(''))
176
+ const result = [...si.stack.pop()]
177
+ result.should.to.deep.equal([3])
178
+ si.errstr.should.equal('')
179
+ si.stack.length.should.equal(0)
180
+ })
181
+ it('script debugger should fire and not cause an error', function () {
182
+ var si = Interpreter()
183
+ si.stepListener = debugScript
184
+ si.verify(Script('OP_1 OP_2 OP_ADD'), Script('OP_3 OP_EQUAL'))
185
+ si.errstr.should.equal('')
186
+ })
187
+ it('script debugger should make copies of stack', function () {
188
+ var si = Interpreter()
189
+ let stk, stkval, altstk, altstkval
190
+ si.stepListener = function (step, stack, altstack) {
191
+ // stack is an array of buffers, interpreter must give us copies of stack so we can't mess it up
192
+ console.log(step)
193
+ console.log(stack)
194
+ console.log(altstack)
195
+ // these values will get overwritten each step but we only care about that final values
196
+ stk = (stack === si.stack)
197
+ stkval = (stack[0] === si.stack[0])
198
+ altstk = (altstack === si.altstack)
199
+ altstkval = (altstack[0] === si.altstack[0])
200
+ }
201
+ // alt stack is not copied to second script execution so just do everything in second script
202
+ si.verify(Script(''), Script('OP_2 OP_TOALTSTACK OP_1'))
203
+ console.log(si.stack)
204
+ console.log(si.altstack)
205
+ si.errstr.should.equal('')
206
+ si.stack.length.should.equal(1)
207
+ si.altstack.length.should.equal(1)
208
+ stk.should.equal(false)
209
+ stkval.should.equal(false)
210
+ altstk.should.equal(false)
211
+ altstkval.should.equal(false)
212
+ })
213
+ })
214
+
215
+ var getFlags = function getFlags (flagstr) {
216
+ var flags = 0
217
+ if (flagstr.indexOf('NONE') !== -1) {
218
+ flags = flags | Interpreter.SCRIPT_VERIFY_NONE
219
+ }
220
+ if (flagstr.indexOf('P2SH') !== -1) {
221
+ flags = flags | Interpreter.SCRIPT_VERIFY_P2SH
222
+ }
223
+ if (flagstr.indexOf('STRICTENC') !== -1) {
224
+ flags = flags | Interpreter.SCRIPT_VERIFY_STRICTENC
225
+ }
226
+ if (flagstr.indexOf('DERSIG') !== -1) {
227
+ flags = flags | Interpreter.SCRIPT_VERIFY_DERSIG
228
+ }
229
+ if (flagstr.indexOf('LOW_S') !== -1) {
230
+ flags = flags | Interpreter.SCRIPT_VERIFY_LOW_S
231
+ }
232
+ if (flagstr.indexOf('NULLDUMMY') !== -1) {
233
+ flags = flags | Interpreter.SCRIPT_VERIFY_NULLDUMMY
234
+ }
235
+ if (flagstr.indexOf('SIGPUSHONLY') !== -1) {
236
+ flags = flags | Interpreter.SCRIPT_VERIFY_SIGPUSHONLY
237
+ }
238
+ if (flagstr.indexOf('MINIMALDATA') !== -1) {
239
+ flags = flags | Interpreter.SCRIPT_VERIFY_MINIMALDATA
240
+ }
241
+ if (flagstr.indexOf('DISCOURAGE_UPGRADABLE_NOPS') !== -1) {
242
+ flags = flags | Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS
243
+ }
244
+ if (flagstr.indexOf('CHECKLOCKTIMEVERIFY') !== -1) {
245
+ flags = flags | Interpreter.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY
246
+ }
247
+ if (flagstr.indexOf('CHECKSEQUENCEVERIFY') !== -1) {
248
+ flags = flags | Interpreter.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY
249
+ }
250
+ if (flagstr.indexOf('NULLFAIL') !== -1) {
251
+ flags = flags | Interpreter.SCRIPT_VERIFY_NULLFAIL
252
+ }
253
+
254
+ if (flagstr.indexOf('CLEANSTACK') !== -1) {
255
+ flags = flags | Interpreter.SCRIPT_VERIFY_CLEANSTACK
256
+ }
257
+
258
+ if (flagstr.indexOf('FORKID') !== -1) {
259
+ flags = flags | Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID
260
+ }
261
+
262
+ if (flagstr.indexOf('REPLAY_PROTECTION') !== -1) {
263
+ flags = flags | Interpreter.SCRIPT_ENABLE_REPLAY_PROTECTION
264
+ }
265
+
266
+ if (flagstr.indexOf('MONOLITH') !== -1) {
267
+ flags = flags | Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES
268
+ }
269
+
270
+ if (flagstr.indexOf('MAGNETIC') !== -1) {
271
+ flags = flags | Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES
272
+ }
273
+
274
+ if (flagstr.indexOf('MINIMALIF') !== -1) {
275
+ flags = flags | Interpreter.SCRIPT_VERIFY_MINIMALIF
276
+ }
277
+ return flags
278
+ }
279
+
280
+ var testFixture = function (vector, expected, extraData) {
281
+ var scriptSig = Script.fromBitcoindString(vector[0])
282
+ var scriptPubkey = Script.fromBitcoindString(vector[1])
283
+ var flags = getFlags(vector[2])
284
+ var inputAmount = 0
285
+ if (extraData) {
286
+ inputAmount = extraData[0] * 1e8
287
+ }
288
+
289
+ var hashbuf = Buffer.alloc(32)
290
+ hashbuf.fill(0)
291
+ var credtx = new Transaction()
292
+ credtx.uncheckedAddInput(new Transaction.Input({
293
+ prevTxId: '0000000000000000000000000000000000000000000000000000000000000000',
294
+ outputIndex: 0xffffffff,
295
+ sequenceNumber: 0xffffffff,
296
+ script: Script('OP_0 OP_0')
297
+ }))
298
+ credtx.addOutput(new Transaction.Output({
299
+ script: scriptPubkey,
300
+ satoshis: inputAmount
301
+ }))
302
+ var idbuf = credtx.id
303
+
304
+ var spendtx = new Transaction()
305
+ spendtx.uncheckedAddInput(new Transaction.Input({
306
+ prevTxId: idbuf.toString('hex'),
307
+ outputIndex: 0,
308
+ sequenceNumber: 0xffffffff,
309
+ script: scriptSig
310
+ }))
311
+ spendtx.addOutput(new Transaction.Output({
312
+ script: new Script(),
313
+ satoshis: inputAmount
314
+ }))
315
+
316
+ var interp = new Interpreter()
317
+ var verified = interp.verify(scriptSig, scriptPubkey, spendtx, 0, flags, new BN(inputAmount))
318
+ verified.should.equal(expected, interp.errstr)
319
+ }
320
+
321
+ const CheckMul = function (a, b, expected) {
322
+ // Negative values for multiplication
323
+ CheckBinaryOpMagnetic(a, b, Opcode.OP_MUL, expected)
324
+ CheckBinaryOpMagnetic(a, NegativeValtype(b), Opcode.OP_MUL, NegativeValtype(expected))
325
+ CheckBinaryOpMagnetic(NegativeValtype(a), b, Opcode.OP_MUL, NegativeValtype(expected))
326
+ CheckBinaryOpMagnetic(NegativeValtype(a), NegativeValtype(b), Opcode.OP_MUL, expected)
327
+
328
+ // Commutativity
329
+ CheckBinaryOpMagnetic(b, a, Opcode.OP_MUL, expected)
330
+ CheckBinaryOpMagnetic(b, NegativeValtype(a), Opcode.OP_MUL, NegativeValtype(expected))
331
+ CheckBinaryOpMagnetic(NegativeValtype(b), a, Opcode.OP_MUL, NegativeValtype(expected))
332
+ CheckBinaryOpMagnetic(NegativeValtype(b), NegativeValtype(a), Opcode.OP_MUL, expected)
333
+
334
+ // Multiplication identities
335
+ CheckBinaryOpMagnetic(a, [0x01], Opcode.OP_MUL, a)
336
+ CheckBinaryOpMagnetic(a, [0x81], Opcode.OP_MUL, NegativeValtype(a))
337
+ CheckBinaryOpMagnetic(a, [], Opcode.OP_MUL, [])
338
+
339
+ CheckBinaryOpMagnetic([0x01], b, Opcode.OP_MUL, b)
340
+ CheckBinaryOpMagnetic([0x81], b, Opcode.OP_MUL, NegativeValtype(b))
341
+ CheckBinaryOpMagnetic([], b, Opcode.OP_MUL, [])
342
+ }
343
+
344
+ const CheckBinaryOpMagnetic = function (a, b, op, expected) {
345
+ const interp = evaluateScript(a, b, op)
346
+ const result = [...interp.stack.pop()]
347
+ result.should.to.deep.equal(expected)
348
+ }
349
+
350
+ const NegativeValtype = function (v) {
351
+ let copy = v.slice()
352
+ if (copy.length) {
353
+ copy[copy.length - 1] ^= 0x80
354
+ }
355
+ // TODO: expose minimally encode as public method?
356
+ return Interpreter._minimallyEncode(copy)
357
+ }
358
+
359
+ const evaluateScript = function (arraySig, arrayPubKey, op, funcDebug) {
360
+ const interp = new Interpreter()
361
+ interp.stepListener = funcDebug
362
+ interp.script = new Script().add(Buffer.from(arraySig)).add(Buffer.from(arrayPubKey))
363
+ interp.script.add(op)
364
+ interp.flags = Interpreter.SCRIPT_VERIFY_P2SH |
365
+ Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES | Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES
366
+ interp.evaluate()
367
+ return interp
368
+ }
369
+
370
+ const debugScript = function (step, stack, altstack) {
371
+ const script = (new Script()).add(step.opcode)
372
+ // stack is array of buffers
373
+ let stackTop = '>'
374
+ for (let item in stack.reverse()) {
375
+ console.log(`Step ${step.pc}: ${script}:${stackTop}${stack[item].toString('hex')}`)
376
+ stackTop = ' '
377
+ }
378
+ }
379
+
380
+ const toBitpattern = function (binaryString) {
381
+ return parseInt(binaryString, 2).toString(16).padStart(8, '0')
382
+ }
383
+
384
+ describe('#Empty and null script', function () {
385
+ it('Empty buffer should have value 0x00 in script', function () {
386
+ const s = new Script().add(Buffer.from([]))
387
+ // script does not render anything so it appears invisible
388
+ s.toString().should.equal('')
389
+ // yet there is a script chunk there
390
+ s.chunks.length.should.equal(1)
391
+ s.chunks[0].opcodenum.should.equal(0)
392
+ })
393
+ it('Zero value (0x00) buffer should have value 0x01 0x00 in script', function () {
394
+ const s = new Script().add(Buffer.from([0x00]))
395
+ s.toString().should.equal('1 0x00')
396
+ s.chunks.length.should.equal(1)
397
+ s.chunks[0].opcodenum.should.equal(1)
398
+ })
399
+ })
400
+
401
+ describe('#NegativeValType', function () {
402
+ it('should pass all tests', function () {
403
+ // Test zero values
404
+ new Script().add(Buffer.from(NegativeValtype([]))).should.to.deep.equal(new Script().add(Buffer.from([])))
405
+ new Script().add(Buffer.from(NegativeValtype([0x00]))).should.to.deep.equal(new Script().add(Buffer.from([])))
406
+ new Script().add(Buffer.from(NegativeValtype([0x80]))).should.to.deep.equal(new Script().add(Buffer.from([])))
407
+ new Script().add(Buffer.from(NegativeValtype([0x00, 0x00]))).should.to.deep.equal(new Script().add(Buffer.from([])))
408
+ new Script().add(Buffer.from(NegativeValtype([0x00, 0x80]))).should.to.deep.equal(new Script().add(Buffer.from([])))
409
+
410
+ // Non-zero values
411
+ NegativeValtype([0x01]).should.to.deep.equal([0x81])
412
+ NegativeValtype([0x81]).should.to.deep.equal([0x01])
413
+ NegativeValtype([0x02, 0x01]).should.to.deep.equal([0x02, 0x81])
414
+ NegativeValtype([0x02, 0x81]).should.to.deep.equal([0x02, 0x01])
415
+ NegativeValtype([0xff, 0x02, 0x01]).should.to.deep.equal([0xff, 0x02, 0x81])
416
+ NegativeValtype([0xff, 0x02, 0x81]).should.to.deep.equal([0xff, 0x02, 0x01])
417
+ NegativeValtype([0xff, 0xff, 0x02, 0x01]).should.to.deep.equal([0xff, 0xff, 0x02, 0x81])
418
+ NegativeValtype([0xff, 0xff, 0x02, 0x81]).should.to.deep.equal([0xff, 0xff, 0x02, 0x01])
419
+
420
+ // Should not be overly-minimized
421
+ NegativeValtype([0xff, 0x80]).should.to.deep.equal([0xff, 0x00])
422
+ NegativeValtype([0xff, 0x00]).should.to.deep.equal([0xff, 0x80])
423
+ })
424
+ })
425
+
426
+ describe('#OP_LSHIFT tests from bitcoind', function () {
427
+ it('should not shift when no n value', function () {
428
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [], Opcode.OP_LSHIFT)
429
+ console.log(interp.script)
430
+ const result = interp.stack.pop()
431
+ result.toString('hex').should.equal(toBitpattern('10011111000100011111010101010101'))
432
+ })
433
+ it('should shift left 1', function () {
434
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x01], Opcode.OP_LSHIFT)
435
+ const result = interp.stack.pop()
436
+ result.toString('hex').should.equal(toBitpattern('00111110001000111110101010101010'))
437
+ })
438
+ it('should shift left 2', function () {
439
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x02], Opcode.OP_LSHIFT)
440
+ const result = interp.stack.pop()
441
+ result.toString('hex').should.equal(toBitpattern('01111100010001111101010101010100'))
442
+ })
443
+ it('should shift left 3', function () {
444
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x03], Opcode.OP_LSHIFT)
445
+ const result = interp.stack.pop()
446
+ result.toString('hex').should.equal(toBitpattern('11111000100011111010101010101000'))
447
+ })
448
+ it('should shift left 4', function () {
449
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x04], Opcode.OP_LSHIFT)
450
+ const result = interp.stack.pop()
451
+ result.toString('hex').should.equal(toBitpattern('11110001000111110101010101010000'))
452
+ })
453
+ it('should shift left 5', function () {
454
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x05], Opcode.OP_LSHIFT)
455
+ const result = interp.stack.pop()
456
+ result.toString('hex').should.equal(toBitpattern('11100010001111101010101010100000'))
457
+ })
458
+ it('should shift left 6', function () {
459
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x06], Opcode.OP_LSHIFT)
460
+ const result = interp.stack.pop()
461
+ result.toString('hex').should.equal(toBitpattern('11000100011111010101010101000000'))
462
+ })
463
+ it('should shift left 7', function () {
464
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x07], Opcode.OP_LSHIFT)
465
+ const result = interp.stack.pop()
466
+ result.toString('hex').should.equal(toBitpattern('10001000111110101010101010000000'))
467
+ })
468
+ it('should shift left 08', function () {
469
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x08], Opcode.OP_LSHIFT)
470
+ const result = interp.stack.pop()
471
+ result.toString('hex').should.equal(toBitpattern('00010001111101010101010100000000'))
472
+ })
473
+ it('should shift left 9', function () {
474
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x09], Opcode.OP_LSHIFT)
475
+ const result = interp.stack.pop()
476
+ result.toString('hex').should.equal(toBitpattern('00100011111010101010101000000000'))
477
+ })
478
+ it('should shift left 0A', function () {
479
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x0A], Opcode.OP_LSHIFT)
480
+ const result = interp.stack.pop()
481
+ result.toString('hex').should.equal(toBitpattern('01000111110101010101010000000000'))
482
+ })
483
+ it('should shift left 0B', function () {
484
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x0B], Opcode.OP_LSHIFT)
485
+ const result = interp.stack.pop()
486
+ result.toString('hex').should.equal(toBitpattern('10001111101010101010100000000000'))
487
+ })
488
+ it('should shift left 0C', function () {
489
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x0C], Opcode.OP_LSHIFT)
490
+ const result = interp.stack.pop()
491
+ result.toString('hex').should.equal(toBitpattern('00011111010101010101000000000000'))
492
+ })
493
+ it('should shift left 0D', function () {
494
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x0D], Opcode.OP_LSHIFT)
495
+ const result = interp.stack.pop()
496
+ result.toString('hex').should.equal(toBitpattern('00111110101010101010000000000000'))
497
+ })
498
+ it('should shift left 0E', function () {
499
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x0E], Opcode.OP_LSHIFT)
500
+ const result = interp.stack.pop()
501
+ result.toString('hex').should.equal(toBitpattern('01111101010101010100000000000000'))
502
+ })
503
+ it('should shift left 0F', function () {
504
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x0F], Opcode.OP_LSHIFT)
505
+ const result = interp.stack.pop()
506
+ result.toString('hex').should.equal(toBitpattern('11111010101010101000000000000000'))
507
+ })
508
+ })
509
+
510
+ describe('#OP_RSHIFT tests from bitcoind', function () {
511
+ it('should not shift when no n value', function () {
512
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [], Opcode.OP_RSHIFT)
513
+ const result = interp.stack.pop()
514
+ result.toString('hex').should.equal(toBitpattern('10011111000100011111010101010101'))
515
+ })
516
+ it('should shift right 1', function () {
517
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x01], Opcode.OP_RSHIFT)
518
+ const result = interp.stack.pop()
519
+ result.toString('hex').should.equal(toBitpattern('01001111100010001111101010101010'))
520
+ })
521
+ it('should shift right 2', function () {
522
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x02], Opcode.OP_RSHIFT)
523
+ const result = interp.stack.pop()
524
+ result.toString('hex').should.equal(toBitpattern('00100111110001000111110101010101'))
525
+ })
526
+ it('should shift right 3', function () {
527
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x03], Opcode.OP_RSHIFT)
528
+ const result = interp.stack.pop()
529
+ result.toString('hex').should.equal(toBitpattern('00010011111000100011111010101010'))
530
+ })
531
+ it('should shift right 4', function () {
532
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x04], Opcode.OP_RSHIFT)
533
+ const result = interp.stack.pop()
534
+ result.toString('hex').should.equal(toBitpattern('00001001111100010001111101010101'))
535
+ })
536
+ it('should shift right 5', function () {
537
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x05], Opcode.OP_RSHIFT)
538
+ const result = interp.stack.pop()
539
+ result.toString('hex').should.equal(toBitpattern('00000100111110001000111110101010'))
540
+ })
541
+ it('should shift right 6', function () {
542
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x06], Opcode.OP_RSHIFT)
543
+ const result = interp.stack.pop()
544
+ result.toString('hex').should.equal(toBitpattern('00000010011111000100011111010101'))
545
+ })
546
+ it('should shift right 7', function () {
547
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x07], Opcode.OP_RSHIFT)
548
+ const result = interp.stack.pop()
549
+ result.toString('hex').should.equal(toBitpattern('00000001001111100010001111101010'))
550
+ })
551
+ it('should shift right 08', function () {
552
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x08], Opcode.OP_RSHIFT)
553
+ const result = interp.stack.pop()
554
+ result.toString('hex').should.equal(toBitpattern('00000000100111110001000111110101'))
555
+ })
556
+ it('should shift right 9', function () {
557
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x09], Opcode.OP_RSHIFT)
558
+ const result = interp.stack.pop()
559
+ result.toString('hex').should.equal(toBitpattern('00000000010011111000100011111010'))
560
+ })
561
+ it('should shift right 0A', function () {
562
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x0A], Opcode.OP_RSHIFT)
563
+ const result = interp.stack.pop()
564
+ result.toString('hex').should.equal(toBitpattern('00000000001001111100010001111101'))
565
+ })
566
+ it('should shift right 0B', function () {
567
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x0B], Opcode.OP_RSHIFT)
568
+ const result = interp.stack.pop()
569
+ result.toString('hex').should.equal(toBitpattern('00000000000100111110001000111110'))
570
+ })
571
+ it('should shift right 0C', function () {
572
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x0C], Opcode.OP_RSHIFT)
573
+ const result = interp.stack.pop()
574
+ result.toString('hex').should.equal(toBitpattern('00000000000010011111000100011111'))
575
+ })
576
+ it('should shift right 0D', function () {
577
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x0D], Opcode.OP_RSHIFT)
578
+ const result = interp.stack.pop()
579
+ result.toString('hex').should.equal(toBitpattern('00000000000001001111100010001111'))
580
+ })
581
+ it('should shift right 0E', function () {
582
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x0E], Opcode.OP_RSHIFT)
583
+ const result = interp.stack.pop()
584
+ result.toString('hex').should.equal(toBitpattern('00000000000000100111110001000111'))
585
+ })
586
+ it('should shift right 0F', function () {
587
+ const interp = evaluateScript([0x9F, 0x11, 0xF5, 0x55], [0x0F], Opcode.OP_RSHIFT)
588
+ const result = interp.stack.pop()
589
+ result.toString('hex').should.equal(toBitpattern('00000000000000010011111000100011'))
590
+ })
591
+ })
592
+ describe('#OP_MUL tests from bitcoind', function () {
593
+ it('OP_MUL tests', function () {
594
+ CheckMul([0x05], [0x06], [0x1E])
595
+ CheckMul([0x05], [0x26], [0xBE, 0x00])
596
+ CheckMul([0x45], [0x26], [0x3E, 0x0A])
597
+ CheckMul([0x02], [0x56, 0x24], [0xAC, 0x48])
598
+ CheckMul([0x05], [0x26, 0x03, 0x32], [0xBE, 0x0F, 0xFA, 0x00])
599
+ CheckMul([0x06], [0x26, 0x03, 0x32, 0x04], [0xE4, 0x12, 0x2C, 0x19])
600
+ CheckMul([0xA0, 0xA0], [0xF5, 0xE4], [0x20, 0xB9, 0xDD, 0x0C]) // -20A0*-64F5=0CDDB920
601
+ CheckMul([0x05, 0x26], [0x26, 0x03, 0x32], [0xBE, 0xB3, 0x71, 0x6D, 0x07])
602
+ CheckMul([0x06, 0x26], [0x26, 0x03, 0x32, 0x04], [0xE4, 0xB6, 0xA3, 0x85, 0x9F, 0x00])
603
+ CheckMul([0x05, 0x26, 0x09], [0x26, 0x03, 0x32], [0xBE, 0xB3, 0xC7, 0x89, 0xC9, 0x01])
604
+ CheckMul([0x06, 0x26, 0x09], [0x26, 0x03, 0x32, 0x04], [0xE4, 0xB6, 0xF9, 0xA1, 0x61, 0x26])
605
+ CheckMul([0x06, 0x26, 0x09, 0x34], [0x26, 0x03, 0x32, 0x04], [0xE4, 0xB6, 0xF9, 0x59, 0x05, 0x4F, 0xDA, 0x00])
606
+ })
607
+ })
608
+
609
+ // Known, intentional divergences from the vendored Bitcoin Core
610
+ // script_tests.json. The vendored data is left untouched (it stays a faithful
611
+ // upstream copy); these overrides record where BSV / this implementation's
612
+ // consensus legitimately differs, so the affected vectors assert the correct
613
+ // BSV result instead of the stale upstream one. Keyed by
614
+ // `${scriptSig}|${scriptPubKey}|${flags}` and mapped to the expected error.
615
+ //
616
+ // - CAT/SPLIT/NUM2BIN/BIN2NUM/AND/OR/XOR/DIV/MOD were re-enabled in BSV at
617
+ // the Genesis upgrade, so they are no longer 'DISABLED_OPCODE'. (Note that
618
+ // the surrounding `0 IF <op> ELSE 1 ENDIF` form fails under upstream only
619
+ // because disabled opcodes are rejected even in unexecuted branches; once
620
+ // enabled, the branch is simply skipped and the script is 'OK'.)
621
+ // - 0xba is OP_NOP8 in this build's opcode table (the NOPs are shifted to
622
+ // make room for the OP_SUBSTR/OP_LEFT/OP_RIGHT string ops at 0xb3-0xb5;
623
+ // see lib/opcode.js), so `1 0xba` is a valid no-op, not 'BAD_OPCODE'.
624
+ var BSV_DIVERGENCES = {
625
+ "'a' 'b'|CAT|P2SH,STRICTENC": 'OK',
626
+ "'a' 'b' 0|IF CAT ELSE 1 ENDIF|P2SH,STRICTENC": 'OK',
627
+ "'abc' 1|SPLIT|P2SH,STRICTENC": 'OK',
628
+ "'abc' 1 0|IF SPLIT ELSE 1 ENDIF|P2SH,STRICTENC": 'OK',
629
+ "'abc' 2 0|IF NUM2BIN ELSE 1 ENDIF|P2SH,STRICTENC": 'OK',
630
+ "'abc' 2 0|IF BIN2NUM ELSE 1 ENDIF|P2SH,STRICTENC": 'OK',
631
+ '1 2 0 IF AND ELSE 1 ENDIF|NOP|P2SH,STRICTENC': 'OK',
632
+ '1 2 0 IF OR ELSE 1 ENDIF|NOP|P2SH,STRICTENC': 'OK',
633
+ '1 2 0 IF XOR ELSE 1 ENDIF|NOP|P2SH,STRICTENC': 'OK',
634
+ '2 2 0 IF DIV ELSE 1 ENDIF|NOP|P2SH,STRICTENC': 'OK',
635
+ '2 2 0 IF MOD ELSE 1 ENDIF|NOP|P2SH,STRICTENC': 'OK',
636
+ '2 DUP DIV|1 EQUAL|P2SH,STRICTENC': 'OK',
637
+ '7 3 MOD|1 EQUAL|P2SH,STRICTENC': 'OK',
638
+ '1|0xba|P2SH,STRICTENC': 'OK'
639
+ }
640
+
641
+ describe('bitcoind script evaluation fixtures', function () {
642
+ var testAllFixtures = function (set) {
643
+ var c = 0; var l = set.length
644
+ set.forEach(function (vector) {
645
+ if (vector.length === 1) {
646
+ return
647
+ }
648
+ c++
649
+
650
+ var extraData
651
+ if (_.isArray(vector[0])) {
652
+ extraData = vector.shift()
653
+ }
654
+
655
+ var fullScriptString = `${vector[0]} ${vector[1]}`
656
+ var divergeKey = `${vector[0]}|${vector[1]}|${vector[2]}`
657
+ var expectedError = Object.prototype.hasOwnProperty.call(BSV_DIVERGENCES, divergeKey)
658
+ ? BSV_DIVERGENCES[divergeKey]
659
+ : vector[3]
660
+ var expected = expectedError === 'OK'
661
+ var descstr = vector[4]
662
+ var comment = descstr ? (` (${descstr})`) : ''
663
+ var txt = `should ${expectedError} script_tests vector #${c}/${l}: ${fullScriptString}${comment}`
664
+
665
+ it(txt, function () { testFixture(vector, expected, extraData) })
666
+ })
667
+ }
668
+ testAllFixtures(scriptTests)
669
+ })
670
+ describe('bitcoind transaction evaluation fixtures', function () {
671
+ var testTxs = function (set, expected) {
672
+ var c = 0
673
+ set.forEach(function (vector) {
674
+ if (vector.length === 1) {
675
+ return
676
+ }
677
+ c++
678
+ var cc = c // copy to local
679
+ it('should pass tx_' + (expected ? '' : 'in') + 'valid vector ' + cc, function () {
680
+ var inputs = vector[0]
681
+ var txhex = vector[1]
682
+
683
+ var flags = getFlags(vector[2])
684
+ var map = {}
685
+ inputs.forEach(function (input) {
686
+ var txid = input[0]
687
+ var txoutnum = input[1]
688
+ var scriptPubKeyStr = input[2]
689
+ if (txoutnum === -1) {
690
+ txoutnum = 0xffffffff // bitcoind casts -1 to an unsigned int
691
+ }
692
+ map[txid + ':' + txoutnum] = Script.fromBitcoindString(scriptPubKeyStr)
693
+ })
694
+
695
+ var tx = new Transaction(txhex)
696
+ var allInputsVerified = true
697
+ tx.inputs.forEach(function (txin, j) {
698
+ if (txin.isNull()) {
699
+ return
700
+ }
701
+ var scriptSig = txin.script
702
+ var txidhex = txin.prevTxId.toString('hex')
703
+ var txoutnum = txin.outputIndex
704
+ var scriptPubkey = map[txidhex + ':' + txoutnum]
705
+ should.exist(scriptPubkey);
706
+ (scriptSig !== undefined).should.equal(true)
707
+ var interp = new Interpreter()
708
+ var verified = interp.verify(scriptSig, scriptPubkey, tx, j, flags)
709
+ if (!verified) {
710
+ allInputsVerified = false
711
+ }
712
+ })
713
+ var txVerified = tx.verify()
714
+ txVerified = (txVerified === true)
715
+ allInputsVerified = allInputsVerified && txVerified
716
+ allInputsVerified.should.equal(expected)
717
+ })
718
+ })
719
+ }
720
+ testTxs(txValid, true)
721
+ testTxs(txInvalid, false)
722
+ })
723
+ })