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