@smartledger/bsv 7.6.2 → 7.8.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 +115 -0
- package/README.md +38 -38
- package/bsv-gdaf.min.js +47 -47
- package/bsv-ltp.min.js +47 -47
- package/bsv-smartcontract.min.js +11 -11
- package/bsv.bundle.js +47 -47
- package/bsv.d.ts +6 -0
- package/bsv.min.js +47 -47
- 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/lib/crypto/signature.js +2 -0
- package/lib/script/interpreter.js +152 -2
- package/lib/transaction/sighash.js +17 -1
- package/package.json +1 -1
- package/test/script/chronicle.js +318 -0
- package/test/script/interpreter.js +4 -9
- package/version.js +1 -1
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
/* global describe, it */
|
|
4
|
+
|
|
5
|
+
// The BSV Chronicle script surface: OP_2MUL/OP_2DIV restored, OP_VER/OP_VERIF/
|
|
6
|
+
// OP_VERNOTIF given meaning, and SIGHASH_CHRONICLE selecting the Original
|
|
7
|
+
// Transaction Digest Algorithm. All of it sits behind SCRIPT_ENABLE_CHRONICLE.
|
|
8
|
+
//
|
|
9
|
+
// The default (flag off) behaviour is pinned just as carefully as the enabled
|
|
10
|
+
// behaviour. Enabling an opcode by accident is a consensus change, and the
|
|
11
|
+
// pre-Chronicle rules are what every existing signature and script was written
|
|
12
|
+
// against.
|
|
13
|
+
|
|
14
|
+
require('chai').should()
|
|
15
|
+
var bsv = require('../..')
|
|
16
|
+
var Interpreter = bsv.Script.Interpreter
|
|
17
|
+
var Opcode = bsv.Opcode
|
|
18
|
+
var Script = bsv.Script
|
|
19
|
+
var BN = bsv.crypto.BN
|
|
20
|
+
var Signature = bsv.crypto.Signature
|
|
21
|
+
|
|
22
|
+
var CHRONICLE = Interpreter.SCRIPT_ENABLE_CHRONICLE
|
|
23
|
+
|
|
24
|
+
/** Evaluate `build`ed script against a tx of `version`, returning the outcome. */
|
|
25
|
+
function run (build, opts) {
|
|
26
|
+
opts = opts || {}
|
|
27
|
+
var tx = new bsv.Transaction()
|
|
28
|
+
if (opts.version != null) tx.version = opts.version
|
|
29
|
+
var script = new Script()
|
|
30
|
+
build(script)
|
|
31
|
+
var interp = new Interpreter()
|
|
32
|
+
var verified = interp.verify(
|
|
33
|
+
new Script(), script, tx, 0, opts.flags == null ? CHRONICLE : opts.flags, new BN(0)
|
|
34
|
+
)
|
|
35
|
+
return {
|
|
36
|
+
verified: verified,
|
|
37
|
+
errstr: interp.errstr || '',
|
|
38
|
+
stack: (interp.stack || []).map(function (b) { return BN.fromScriptNumBuffer(b).toString() })
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
describe('Chronicle script surface', function () {
|
|
43
|
+
describe('SCRIPT_ENABLE_CHRONICLE flag', function () {
|
|
44
|
+
it('is a distinct bit that does not collide with the other opcode flags', function () {
|
|
45
|
+
CHRONICLE.should.be.a('number')
|
|
46
|
+
;[
|
|
47
|
+
Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES,
|
|
48
|
+
Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES,
|
|
49
|
+
Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID,
|
|
50
|
+
Interpreter.SCRIPT_ENABLE_REPLAY_PROTECTION
|
|
51
|
+
].forEach(function (other) {
|
|
52
|
+
(CHRONICLE & other).should.equal(0)
|
|
53
|
+
})
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it('is off by default, so none of this changes existing evaluation', function () {
|
|
57
|
+
(Interpreter.DEFAULT_FLAGS & CHRONICLE).should.equal(0)
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
describe('OP_2MUL / OP_2DIV', function () {
|
|
62
|
+
it('stay DISABLED without the flag, even in an unexecuted branch', function () {
|
|
63
|
+
// "Disabled" is stronger than "unimplemented": a disabled opcode fails the
|
|
64
|
+
// script even where it is never executed. That is why the gate lives in
|
|
65
|
+
// isOpcodeDisabled rather than in the evaluation switch — losing this
|
|
66
|
+
// distinction would silently loosen consensus.
|
|
67
|
+
var r = run(function (s) {
|
|
68
|
+
s.add(Opcode.OP_0).add(Opcode.OP_IF).add(Opcode.OP_2MUL).add(Opcode.OP_ENDIF).add(Opcode.OP_1)
|
|
69
|
+
}, { flags: 0 })
|
|
70
|
+
r.verified.should.equal(false)
|
|
71
|
+
r.errstr.should.match(/DISABLED_OPCODE/)
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
it('are usable in an unexecuted branch once enabled', function () {
|
|
75
|
+
var r = run(function (s) {
|
|
76
|
+
s.add(Opcode.OP_0).add(Opcode.OP_IF).add(Opcode.OP_2MUL).add(Opcode.OP_ENDIF).add(Opcode.OP_1)
|
|
77
|
+
})
|
|
78
|
+
r.verified.should.equal(true)
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
it('OP_2MUL doubles, over positive, negative and zero', function () {
|
|
82
|
+
;[[0, '0'], [1, '2'], [7, '14'], [-3, '-6'], [-1, '-2']].forEach(function (t) {
|
|
83
|
+
var r = run(function (s) { s.add(new BN(t[0]).toScriptNumBuffer()).add(Opcode.OP_2MUL) })
|
|
84
|
+
r.stack[r.stack.length - 1].should.equal(t[1])
|
|
85
|
+
})
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
it('OP_2DIV truncates toward zero, so it agrees with OP_DIV by 2', function () {
|
|
89
|
+
// -5 OP_2DIV is -2, not -3. A shift would give -3; bn.js `shrn` also asserts
|
|
90
|
+
// on negatives. This is the case where a rounding change would hide.
|
|
91
|
+
;[0, 1, 5, -5, 7, -7, -1, 1000, -1000].forEach(function (v) {
|
|
92
|
+
var viaOp = run(function (s) { s.add(new BN(v).toScriptNumBuffer()).add(Opcode.OP_2DIV) })
|
|
93
|
+
var viaDiv = run(function (s) {
|
|
94
|
+
s.add(new BN(v).toScriptNumBuffer()).add(new BN(2).toScriptNumBuffer()).add(Opcode.OP_DIV)
|
|
95
|
+
})
|
|
96
|
+
viaOp.stack[viaOp.stack.length - 1].should.equal(viaDiv.stack[viaDiv.stack.length - 1])
|
|
97
|
+
})
|
|
98
|
+
})
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
describe('OP_VER', function () {
|
|
102
|
+
it('is BAD_OPCODE without the flag', function () {
|
|
103
|
+
var r = run(function (s) { s.add(Opcode.OP_VER) }, { flags: 0 })
|
|
104
|
+
r.verified.should.equal(false)
|
|
105
|
+
r.errstr.should.match(/BAD_OPCODE/)
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it('pushes the executing transaction version', function () {
|
|
109
|
+
;[1, 2, 10].forEach(function (v) {
|
|
110
|
+
var r = run(function (s) { s.add(Opcode.OP_VER) }, { version: v })
|
|
111
|
+
r.stack[r.stack.length - 1].should.equal(String(v))
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
describe('OP_VERIF / OP_VERNOTIF', function () {
|
|
117
|
+
it('are BAD_OPCODE without the flag EVEN IN AN UNEXECUTED BRANCH', function () {
|
|
118
|
+
// A rule Bitcoin applies to no other opcode, which is why the flag check sits
|
|
119
|
+
// outside the fExec guard. If it moved inside, this script would pass.
|
|
120
|
+
var r = run(function (s) {
|
|
121
|
+
s.add(Opcode.OP_0).add(Opcode.OP_IF).add(Opcode.OP_VERIF).add(Opcode.OP_ENDIF).add(Opcode.OP_1)
|
|
122
|
+
}, { flags: 0 })
|
|
123
|
+
r.verified.should.equal(false)
|
|
124
|
+
r.errstr.should.match(/BAD_OPCODE/)
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
it('OP_VERIF takes the branch when the top of stack equals the tx version', function () {
|
|
128
|
+
var taken = run(function (s) {
|
|
129
|
+
s.add(new BN(2).toScriptNumBuffer()).add(Opcode.OP_VERIF).add(Opcode.OP_1).add(Opcode.OP_ENDIF)
|
|
130
|
+
}, { version: 2 })
|
|
131
|
+
taken.verified.should.equal(true)
|
|
132
|
+
|
|
133
|
+
var notTaken = run(function (s) {
|
|
134
|
+
s.add(new BN(9).toScriptNumBuffer()).add(Opcode.OP_VERIF).add(Opcode.OP_1).add(Opcode.OP_ENDIF).add(Opcode.OP_1)
|
|
135
|
+
}, { version: 2 })
|
|
136
|
+
notTaken.verified.should.equal(true)
|
|
137
|
+
notTaken.stack.length.should.equal(1) // only the trailing OP_1
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
it('OP_VERNOTIF is its negation', function () {
|
|
141
|
+
var r = run(function (s) {
|
|
142
|
+
s.add(new BN(9).toScriptNumBuffer()).add(Opcode.OP_VERNOTIF).add(Opcode.OP_1).add(Opcode.OP_ENDIF)
|
|
143
|
+
}, { version: 2 })
|
|
144
|
+
r.verified.should.equal(true)
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
it('CONSUMES its operand, mirroring OP_IF', function () {
|
|
148
|
+
// The spec describes the comparison but not the stack effect. An IF that left
|
|
149
|
+
// its condition behind would unbalance every script using it, so this pops.
|
|
150
|
+
// Pinned so a correction shows up as a failure rather than silently.
|
|
151
|
+
var r = run(function (s) {
|
|
152
|
+
s.add(Opcode.OP_7).add(Opcode.OP_2).add(Opcode.OP_VERIF).add(Opcode.OP_ENDIF)
|
|
153
|
+
}, { version: 2 })
|
|
154
|
+
r.verified.should.equal(true)
|
|
155
|
+
r.stack.should.deep.equal(['7']) // the 2 was consumed, the 7 remains
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
it('fails on an empty stack rather than reading past it', function () {
|
|
159
|
+
var r = run(function (s) {
|
|
160
|
+
s.add(Opcode.OP_VERIF).add(Opcode.OP_ENDIF).add(Opcode.OP_1)
|
|
161
|
+
}, { version: 2 })
|
|
162
|
+
r.verified.should.equal(false)
|
|
163
|
+
r.errstr.should.match(/UNBALANCED_CONDITIONAL/)
|
|
164
|
+
})
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
// Ported from SV Node src/script/interpreter.cpp (OP_LSHIFTNUM / OP_RSHIFTNUM) and
|
|
168
|
+
// the CScriptNum / bsv::bint arithmetic behind it. Each case below corresponds to a
|
|
169
|
+
// specific line of that implementation, so a divergence shows up as a named failure.
|
|
170
|
+
describe('OP_LSHIFTNUM / OP_RSHIFTNUM', function () {
|
|
171
|
+
// Push x then n then the opcode: the node's comment is literally `(x n -- out)`,
|
|
172
|
+
// so the COUNT is on top.
|
|
173
|
+
function shift (x, n, op, flags) {
|
|
174
|
+
return run(function (s) {
|
|
175
|
+
s.add(new BN(x).toScriptNumBuffer()).add(new BN(n).toScriptNumBuffer()).add(op)
|
|
176
|
+
}, { flags: flags == null ? CHRONICLE : flags })
|
|
177
|
+
}
|
|
178
|
+
function value (x, n, op) {
|
|
179
|
+
var r = shift(x, n, op)
|
|
180
|
+
return r.stack[r.stack.length - 1]
|
|
181
|
+
}
|
|
182
|
+
// A zero result makes the script fail EVAL_FALSE, so compare against OP_0 instead.
|
|
183
|
+
function isZero (x, n, op) {
|
|
184
|
+
return run(function (s) {
|
|
185
|
+
s.add(new BN(x).toScriptNumBuffer()).add(new BN(n).toScriptNumBuffer()).add(op)
|
|
186
|
+
.add(Opcode.OP_0).add(Opcode.OP_EQUAL)
|
|
187
|
+
}).verified
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
it('are upgradable NOPs before Chronicle, as the node has them', function () {
|
|
191
|
+
// if(!utxo_after_chronicle) { ... else break; } — a no-op, NOT an error.
|
|
192
|
+
// Rejecting here would refuse scripts the network accepts.
|
|
193
|
+
var r = shift(8, 1, Opcode.OP_LSHIFTNUM, 0)
|
|
194
|
+
r.verified.should.equal(true)
|
|
195
|
+
r.stack.should.deep.equal(['8', '1']) // untouched: no shift, nothing popped
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
it('honour DISCOURAGE_UPGRADABLE_NOPS before Chronicle', function () {
|
|
199
|
+
var r = shift(8, 1, Opcode.OP_LSHIFTNUM, Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
|
|
200
|
+
r.verified.should.equal(false)
|
|
201
|
+
r.errstr.should.match(/DISCOURAGE_UPGRADABLE_NOPS/)
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
it('left shift multiplies by 2^n, carrying the sign', function () {
|
|
205
|
+
value(1, 4, Opcode.OP_LSHIFTNUM).should.equal('16')
|
|
206
|
+
value(3, 3, Opcode.OP_LSHIFTNUM).should.equal('24')
|
|
207
|
+
value(1, 0, Opcode.OP_LSHIFTNUM).should.equal('1')
|
|
208
|
+
value(-1, 4, Opcode.OP_LSHIFTNUM).should.equal('-16')
|
|
209
|
+
value(-3, 3, Opcode.OP_LSHIFTNUM).should.equal('-24')
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
it('right shift TRUNCATES TOWARD ZERO, which is the whole of "preserving sign"', function () {
|
|
213
|
+
// The node spells this out: "Mathematical division by 2^bit_shift, rounding
|
|
214
|
+
// toward zero ... For negative values: n / 2^k = -((-n) >> k)". A two's
|
|
215
|
+
// complement arithmetic shift would FLOOR instead, giving -3 and -4 here.
|
|
216
|
+
value(-5, 1, Opcode.OP_RSHIFTNUM).should.equal('-2')
|
|
217
|
+
value(-7, 1, Opcode.OP_RSHIFTNUM).should.equal('-3')
|
|
218
|
+
value(5, 1, Opcode.OP_RSHIFTNUM).should.equal('2')
|
|
219
|
+
value(-1000, 3, Opcode.OP_RSHIFTNUM).should.equal('-125')
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
it('agrees with OP_DIV by 2^n, the same convention as OP_2DIV', function () {
|
|
223
|
+
[5, -5, 7, -7, 1000, -1000].forEach(function (x) {
|
|
224
|
+
var viaShift = value(x, 1, Opcode.OP_RSHIFTNUM)
|
|
225
|
+
var viaDiv = run(function (s) {
|
|
226
|
+
s.add(new BN(x).toScriptNumBuffer()).add(new BN(2).toScriptNumBuffer()).add(Opcode.OP_DIV)
|
|
227
|
+
})
|
|
228
|
+
viaShift.should.equal(viaDiv.stack[viaDiv.stack.length - 1])
|
|
229
|
+
})
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
it('rejects a negative shift count', function () {
|
|
233
|
+
// if(n < 0) return SCRIPT_ERR_INVALID_NUMBER_RANGE
|
|
234
|
+
;[Opcode.OP_LSHIFTNUM, Opcode.OP_RSHIFTNUM].forEach(function (op) {
|
|
235
|
+
var r = shift(8, -1, op)
|
|
236
|
+
r.verified.should.equal(false)
|
|
237
|
+
r.errstr.should.match(/INVALID_NUMBER_RANGE/)
|
|
238
|
+
})
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
it('right shift past the bit length is zero, not an error', function () {
|
|
242
|
+
isZero(5, 1000, Opcode.OP_RSHIFTNUM).should.equal(true)
|
|
243
|
+
isZero(-5, 1000, Opcode.OP_RSHIFTNUM).should.equal(true) // and no negative zero
|
|
244
|
+
isZero(1, 1, Opcode.OP_RSHIFTNUM).should.equal(true)
|
|
245
|
+
isZero(-1, 1, Opcode.OP_RSHIFTNUM).should.equal(true)
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
it('left shift overflows rather than growing without bound', function () {
|
|
249
|
+
// CScriptNum bounds this BEFORE shifting (current_size + shift_bytes >
|
|
250
|
+
// max_length), so a huge count cannot allocate a huge number first.
|
|
251
|
+
var r = shift(5, 1000, Opcode.OP_LSHIFTNUM)
|
|
252
|
+
r.verified.should.equal(false)
|
|
253
|
+
r.errstr.should.match(/OVERFLOW/)
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
it('fails on a short stack', function () {
|
|
257
|
+
var r = run(function (s) { s.add(new BN(1).toScriptNumBuffer()).add(Opcode.OP_LSHIFTNUM) })
|
|
258
|
+
r.verified.should.equal(false)
|
|
259
|
+
r.errstr.should.match(/INVALID_STACK_OPERATION/)
|
|
260
|
+
})
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
describe('SIGHASH_CHRONICLE selects the original digest algorithm', function () {
|
|
264
|
+
function fixture () {
|
|
265
|
+
var key = bsv.PrivateKey.fromBuffer(Buffer.alloc(32, 5))
|
|
266
|
+
var sub = Script.buildPublicKeyHashOut(key.toAddress())
|
|
267
|
+
var tx = new bsv.Transaction()
|
|
268
|
+
tx.uncheckedAddInput(new bsv.Transaction.Input({
|
|
269
|
+
prevTxId: 'aa'.repeat(32), outputIndex: 0, script: Script.empty()
|
|
270
|
+
}))
|
|
271
|
+
tx.addOutput(new bsv.Transaction.Output({ script: sub, satoshis: 1000 }))
|
|
272
|
+
return { tx: tx, sub: sub, amt: new BN(2000) }
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
it('has the constant at 0x20', function () {
|
|
276
|
+
Signature.SIGHASH_CHRONICLE.should.equal(0x20)
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
it('routes to OTDA when the bit is set AND the flag is enabled', function () {
|
|
280
|
+
var f = fixture()
|
|
281
|
+
var type = Signature.SIGHASH_ALL | Signature.SIGHASH_FORKID | Signature.SIGHASH_CHRONICLE
|
|
282
|
+
var enabled = bsv.Transaction.sighash.sighash(
|
|
283
|
+
f.tx, type, 0, f.sub, f.amt,
|
|
284
|
+
Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID | CHRONICLE
|
|
285
|
+
)
|
|
286
|
+
var forcedOtda = bsv.Transaction.sighash.sighash(f.tx, type, 0, f.sub, f.amt, 0)
|
|
287
|
+
enabled.toString('hex').should.equal(forcedOtda.toString('hex'))
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
it('OVERRIDES FORKID — otherwise the bit could never select OTDA in practice', function () {
|
|
291
|
+
// FORKID is set on essentially every BSV signature written since 2018, so a
|
|
292
|
+
// CHRONICLE bit that only applied when FORKID was absent would mean nothing.
|
|
293
|
+
var f = fixture()
|
|
294
|
+
var type = Signature.SIGHASH_ALL | Signature.SIGHASH_FORKID | Signature.SIGHASH_CHRONICLE
|
|
295
|
+
var chronicle = bsv.Transaction.sighash.sighash(
|
|
296
|
+
f.tx, type, 0, f.sub, f.amt,
|
|
297
|
+
Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID | CHRONICLE
|
|
298
|
+
)
|
|
299
|
+
var bip143 = bsv.Transaction.sighash.sighash(
|
|
300
|
+
f.tx, type, 0, f.sub, f.amt, Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID
|
|
301
|
+
)
|
|
302
|
+
chronicle.toString('hex').should.not.equal(bip143.toString('hex'))
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
it('is IGNORED without the flag, so existing BIP-143 signatures are unaffected', function () {
|
|
306
|
+
// Before the upgrade the 0x20 bit means nothing, so signatures already exist
|
|
307
|
+
// whose type byte happens to set it. Honouring it unconditionally would
|
|
308
|
+
// reinterpret those as OTDA — a silent validity change on historic data.
|
|
309
|
+
var f = fixture()
|
|
310
|
+
var withBit = Signature.SIGHASH_ALL | Signature.SIGHASH_FORKID | Signature.SIGHASH_CHRONICLE
|
|
311
|
+
var viaForkId = bsv.Transaction.sighash.sighash(
|
|
312
|
+
f.tx, withBit, 0, f.sub, f.amt, Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID
|
|
313
|
+
)
|
|
314
|
+
var forcedOtda = bsv.Transaction.sighash.sighash(f.tx, withBit, 0, f.sub, f.amt, 0)
|
|
315
|
+
viaForkId.toString('hex').should.not.equal(forcedOtda.toString('hex'))
|
|
316
|
+
})
|
|
317
|
+
})
|
|
318
|
+
})
|
|
@@ -643,10 +643,9 @@ describe('Interpreter', function () {
|
|
|
643
643
|
// - Chronicle reassigned 0xb3-0xb7 to OP_SUBSTR/OP_LEFT/OP_RIGHT/OP_LSHIFTNUM/
|
|
644
644
|
// OP_RSHIFTNUM, so Core's NOP4..NOP8 no longer exist as no-ops. Vectors that
|
|
645
645
|
// expect those bytes to do nothing now fail here: 0xb3-0xb5 consume stack as
|
|
646
|
-
// string ops (INVALID_STACK_OPERATION)
|
|
647
|
-
//
|
|
648
|
-
//
|
|
649
|
-
// refusing. This is a real consensus divergence from Core, not a quirk.
|
|
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.
|
|
650
649
|
// (0xba is no longer a NOP either; it is unassigned, which now AGREES with
|
|
651
650
|
// Core, so its former override has been removed.)
|
|
652
651
|
var BSV_DIVERGENCES = {
|
|
@@ -670,11 +669,7 @@ describe('Interpreter', function () {
|
|
|
670
669
|
"'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10|'NOP_1_to_10' EQUAL|P2SH,STRICTENC": 'SCRIPT_ERR_INVALID_STACK_OPERATION',
|
|
671
670
|
'NOP|NOP4 1|P2SH,STRICTENC': 'SCRIPT_ERR_INVALID_STACK_OPERATION',
|
|
672
671
|
'NOP|NOP5 1|P2SH,STRICTENC': 'SCRIPT_ERR_INVALID_STACK_OPERATION',
|
|
673
|
-
'NOP|NOP6 1|P2SH,STRICTENC': 'SCRIPT_ERR_INVALID_STACK_OPERATION'
|
|
674
|
-
'NOP|NOP7 1|P2SH,STRICTENC': 'SCRIPT_ERR_BAD_OPCODE',
|
|
675
|
-
'NOP|NOP8 1|P2SH,STRICTENC': 'SCRIPT_ERR_BAD_OPCODE',
|
|
676
|
-
'0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac|HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL|': 'SCRIPT_ERR_BAD_OPCODE',
|
|
677
|
-
'0x47 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb125101 NOP8|0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG|': 'SCRIPT_ERR_BAD_OPCODE'
|
|
672
|
+
'NOP|NOP6 1|P2SH,STRICTENC': 'SCRIPT_ERR_INVALID_STACK_OPERATION'
|
|
678
673
|
}
|
|
679
674
|
|
|
680
675
|
describe('bitcoind script evaluation fixtures', function () {
|
package/version.js
CHANGED