@smartledger/bsv 7.8.1 → 7.10.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 +117 -6
- package/README.md +38 -38
- package/bsv-covenant.min.js +1 -1
- package/bsv-ecies.min.js +1 -1
- package/bsv-gdaf.min.js +54 -54
- package/bsv-ltp.min.js +58 -85
- package/bsv-message.min.js +2 -2
- package/bsv-mnemonic.min.js +12 -14
- package/bsv-script-helper.min.js +1 -1
- package/bsv-shamir.min.js +14 -16
- package/bsv-smartcontract.min.js +23 -25
- package/bsv.bundle.js +54 -54
- package/bsv.min.js +54 -54
- package/build/esbuild.js +84 -4
- 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/index.js +9 -1
- package/lib/covenant/helpers.js +146 -0
- package/lib/covenant/index.js +21 -0
- package/lib/covenant/pushtx.js +243 -0
- package/lib/covenant-interface.js +408 -397
- package/lib/custom-script-helper.js +44 -38
- package/lib/ecies/bitcore-ecies.js +3 -4
- package/lib/ecies/electrum-ecies.js +4 -6
- package/lib/ecies/errors.js +1 -1
- package/lib/gdaf/attestation-signer.js +7 -7
- package/lib/gdaf/attestation-verifier.js +5 -6
- package/lib/gdaf/did-resolver.js +10 -9
- package/lib/gdaf/smartledger-anchor.js +13 -12
- package/lib/gdaf/zk-prover.js +8 -8
- package/lib/ltp/anchor.js +2 -3
- package/lib/ltp/claim.js +2 -3
- package/lib/ltp/index.js +2 -3
- package/lib/ltp/obligation.js +9 -9
- package/lib/ltp/proof.js +7 -7
- package/lib/ltp/registry.js +4 -5
- package/lib/ltp/right.js +11 -11
- package/lib/message/index.js +5 -4
- package/lib/message/message.js +11 -11
- package/lib/mnemonic/errors.js +1 -1
- package/lib/mnemonic/index.js +5 -4
- package/lib/mnemonic/mnemonic.js +22 -10
- package/lib/ordinals/bsv20.js +4 -4
- package/lib/ordinals/inscription.js +8 -12
- package/lib/ordinals/ordlock.js +26 -21
- package/lib/script/interpreter.js +96 -31
- package/lib/smart_contract/authorizers.js +8 -6
- package/lib/smart_contract/builder.js +32 -26
- package/lib/smart_contract/covenant.js +32 -25
- package/lib/smart_contract/covenant_helpers.js +8 -128
- package/lib/smart_contract/debugger.js +9 -6
- package/lib/smart_contract/dsl.js +5 -6
- package/lib/smart_contract/index.js +11 -8
- package/lib/smart_contract/locks.js +3 -4
- package/lib/smart_contract/opcode_list.js +2 -3
- package/lib/smart_contract/pels.js +4 -5
- package/lib/smart_contract/preimage.js +11 -7
- package/lib/smart_contract/pushtx.js +8 -263
- package/lib/smart_contract/script_interpreter.js +112 -105
- package/lib/smart_contract/script_tester.js +24 -18
- package/lib/smart_contract/script_utils.js +15 -14
- package/lib/smart_contract/sighash.js +23 -15
- package/lib/smart_contract/stack_examiner.js +70 -63
- package/lib/smart_contract/token.js +6 -6
- package/lib/smart_contract/utxo_generator.js +21 -15
- package/lib/smartutxo.js +27 -21
- package/lib/spv/headerchain.js +3 -3
- package/lib/spv/merkleproof.js +3 -3
- package/package.json +4 -2
- package/test/script/chronicle.js +53 -10
- package/test/script/interpreter.js +9 -6
- package/test/script/string_ops.js +26 -10
- package/version.js +1 -1
|
@@ -15,7 +15,13 @@
|
|
|
15
15
|
|
|
16
16
|
'use strict'
|
|
17
17
|
|
|
18
|
-
var
|
|
18
|
+
var Output = require('../transaction/output')
|
|
19
|
+
var Input = require('../transaction/input')
|
|
20
|
+
var Interpreter = require('../script/interpreter')
|
|
21
|
+
var BN = require('../crypto/bn')
|
|
22
|
+
var Transaction = require('../transaction')
|
|
23
|
+
var Opcode = require('../opcode')
|
|
24
|
+
var Script = require('../script')
|
|
19
25
|
|
|
20
26
|
/**
|
|
21
27
|
* ScriptTester Class - Local script execution and debugging
|
|
@@ -27,7 +33,7 @@ function ScriptTester(options) {
|
|
|
27
33
|
}
|
|
28
34
|
|
|
29
35
|
this.options = options || {}
|
|
30
|
-
this.flags = this.options.flags ||
|
|
36
|
+
this.flags = this.options.flags || Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID
|
|
31
37
|
this.satoshis = this.options.satoshis || 100000
|
|
32
38
|
}
|
|
33
39
|
|
|
@@ -44,8 +50,8 @@ ScriptTester.prototype.execute = function(config) {
|
|
|
44
50
|
var tx = this._createDummyTransaction()
|
|
45
51
|
|
|
46
52
|
// Create interpreter
|
|
47
|
-
var interpreter = new
|
|
48
|
-
var satoshisBN = new
|
|
53
|
+
var interpreter = new Interpreter()
|
|
54
|
+
var satoshisBN = new BN(this.satoshis)
|
|
49
55
|
|
|
50
56
|
try {
|
|
51
57
|
var verified = interpreter.verify(
|
|
@@ -86,7 +92,7 @@ ScriptTester.prototype.debug = function(config) {
|
|
|
86
92
|
var combinedScript = this._createCombinedScript(config)
|
|
87
93
|
var tx = this._createDummyTransaction()
|
|
88
94
|
|
|
89
|
-
var interpreter = new
|
|
95
|
+
var interpreter = new Interpreter()
|
|
90
96
|
interpreter.script = combinedScript
|
|
91
97
|
interpreter.tx = tx
|
|
92
98
|
interpreter.nIn = 0
|
|
@@ -98,7 +104,7 @@ ScriptTester.prototype.debug = function(config) {
|
|
|
98
104
|
try {
|
|
99
105
|
for (var i = 0; i < chunks.length; i++) {
|
|
100
106
|
var chunk = chunks[i]
|
|
101
|
-
var opname =
|
|
107
|
+
var opname = Opcode.reverseMap[chunk.opcodenum] || 'PUSH'
|
|
102
108
|
|
|
103
109
|
// Capture state before execution
|
|
104
110
|
var beforeStack = interpreter.stack.map(function(b) { return b.toString('hex') })
|
|
@@ -230,7 +236,7 @@ ScriptTester.prototype.testFieldExtraction = function(preimageHex, fieldName) {
|
|
|
230
236
|
* @private
|
|
231
237
|
*/
|
|
232
238
|
ScriptTester.prototype._parseScript = function(input) {
|
|
233
|
-
if (!input) return new
|
|
239
|
+
if (!input) return new Script()
|
|
234
240
|
|
|
235
241
|
var trimmed = input.trim()
|
|
236
242
|
var isHex = /^[0-9a-fA-F]+$/.test(trimmed.replace(/\s+/g, ''))
|
|
@@ -241,13 +247,13 @@ ScriptTester.prototype._parseScript = function(input) {
|
|
|
241
247
|
var hexLength = trimmed.length / 2
|
|
242
248
|
if (hexLength >= 180 && hexLength <= 250) {
|
|
243
249
|
// This is likely preimage data - create a script that pushes it
|
|
244
|
-
return new
|
|
250
|
+
return new Script().add(Buffer.from(trimmed, 'hex'))
|
|
245
251
|
} else {
|
|
246
252
|
// Normal hex script
|
|
247
|
-
return
|
|
253
|
+
return Script.fromHex(trimmed)
|
|
248
254
|
}
|
|
249
255
|
} else {
|
|
250
|
-
return
|
|
256
|
+
return Script.fromASM(trimmed)
|
|
251
257
|
}
|
|
252
258
|
} catch (error) {
|
|
253
259
|
throw new Error('Failed to parse script: ' + error.message)
|
|
@@ -271,7 +277,7 @@ ScriptTester.prototype._createCombinedScript = function(config) {
|
|
|
271
277
|
lockingScript.toBuffer()
|
|
272
278
|
])
|
|
273
279
|
|
|
274
|
-
return
|
|
280
|
+
return Script.fromBuffer(combinedBuffer)
|
|
275
281
|
}
|
|
276
282
|
|
|
277
283
|
/**
|
|
@@ -279,24 +285,24 @@ ScriptTester.prototype._createCombinedScript = function(config) {
|
|
|
279
285
|
* @private
|
|
280
286
|
*/
|
|
281
287
|
ScriptTester.prototype._createDummyTransaction = function() {
|
|
282
|
-
var tx = new
|
|
288
|
+
var tx = new Transaction()
|
|
283
289
|
|
|
284
290
|
// Create dummy input
|
|
285
|
-
var dummyInput = new
|
|
291
|
+
var dummyInput = new Input({
|
|
286
292
|
prevTxId: '0'.repeat(64),
|
|
287
293
|
outputIndex: 0,
|
|
288
|
-
script:
|
|
294
|
+
script: Script.empty(),
|
|
289
295
|
satoshis: this.satoshis,
|
|
290
|
-
output: new
|
|
296
|
+
output: new Output({
|
|
291
297
|
satoshis: this.satoshis,
|
|
292
|
-
script:
|
|
298
|
+
script: Script.empty()
|
|
293
299
|
})
|
|
294
300
|
})
|
|
295
301
|
|
|
296
302
|
tx.addInput(dummyInput)
|
|
297
|
-
tx.addOutput(new
|
|
303
|
+
tx.addOutput(new Output({
|
|
298
304
|
satoshis: this.satoshis,
|
|
299
|
-
script:
|
|
305
|
+
script: Script.empty()
|
|
300
306
|
}))
|
|
301
307
|
|
|
302
308
|
return tx
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
|
|
16
16
|
'use strict'
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
var Opcode = require('../opcode')
|
|
19
|
+
var Script = require('../script')
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
22
|
* Script Format Conversion Utilities
|
|
@@ -23,7 +24,7 @@ const bsv = require('../..')
|
|
|
23
24
|
|
|
24
25
|
function scriptToASM(scriptBuffer) {
|
|
25
26
|
if (Buffer.isBuffer(scriptBuffer)) {
|
|
26
|
-
const script =
|
|
27
|
+
const script = Script.fromBuffer(scriptBuffer)
|
|
27
28
|
return script.toASM()
|
|
28
29
|
} else if (scriptBuffer && typeof scriptBuffer.toASM === 'function') {
|
|
29
30
|
return scriptBuffer.toASM()
|
|
@@ -33,7 +34,7 @@ function scriptToASM(scriptBuffer) {
|
|
|
33
34
|
|
|
34
35
|
function asmToScript(asmString) {
|
|
35
36
|
try {
|
|
36
|
-
return
|
|
37
|
+
return Script.fromASM(asmString)
|
|
37
38
|
} catch (error) {
|
|
38
39
|
throw new Error(`Invalid ASM string: ${error.message}`)
|
|
39
40
|
}
|
|
@@ -41,7 +42,7 @@ function asmToScript(asmString) {
|
|
|
41
42
|
|
|
42
43
|
function asmToHex(asmString) {
|
|
43
44
|
try {
|
|
44
|
-
const script =
|
|
45
|
+
const script = Script.fromASM(asmString)
|
|
45
46
|
return script.toBuffer().toString('hex')
|
|
46
47
|
} catch (error) {
|
|
47
48
|
throw new Error(`Cannot convert ASM to hex: ${error.message}`)
|
|
@@ -51,7 +52,7 @@ function asmToHex(asmString) {
|
|
|
51
52
|
function hexToASM(hexString) {
|
|
52
53
|
try {
|
|
53
54
|
const buffer = Buffer.from(hexString, 'hex')
|
|
54
|
-
const script =
|
|
55
|
+
const script = Script.fromBuffer(buffer)
|
|
55
56
|
return script.toASM()
|
|
56
57
|
} catch (error) {
|
|
57
58
|
throw new Error(`Cannot convert hex to ASM: ${error.message}`)
|
|
@@ -73,7 +74,7 @@ function scriptToHex(script) {
|
|
|
73
74
|
|
|
74
75
|
function validateASM(asmString) {
|
|
75
76
|
try {
|
|
76
|
-
|
|
77
|
+
Script.fromASM(asmString)
|
|
77
78
|
return { valid: true, error: null }
|
|
78
79
|
} catch (error) {
|
|
79
80
|
return { valid: false, error: error.message }
|
|
@@ -84,9 +85,9 @@ function validateScript(script) {
|
|
|
84
85
|
try {
|
|
85
86
|
let scriptObj
|
|
86
87
|
if (typeof script === 'string') {
|
|
87
|
-
scriptObj =
|
|
88
|
+
scriptObj = Script.fromASM(script)
|
|
88
89
|
} else if (Buffer.isBuffer(script)) {
|
|
89
|
-
scriptObj =
|
|
90
|
+
scriptObj = Script.fromBuffer(script)
|
|
90
91
|
} else if (script && typeof script.toBuffer === 'function') {
|
|
91
92
|
scriptObj = script
|
|
92
93
|
} else {
|
|
@@ -123,7 +124,7 @@ function validateSyntax(asmString) {
|
|
|
123
124
|
const op = operations[i]
|
|
124
125
|
|
|
125
126
|
// Check for unknown opcodes
|
|
126
|
-
if (op.startsWith('OP_') && !
|
|
127
|
+
if (op.startsWith('OP_') && !Opcode.map[op]) {
|
|
127
128
|
issues.push(`Unknown opcode: ${op} at position ${i}`)
|
|
128
129
|
}
|
|
129
130
|
|
|
@@ -151,9 +152,9 @@ function estimateScriptSize(script) {
|
|
|
151
152
|
try {
|
|
152
153
|
let scriptObj
|
|
153
154
|
if (typeof script === 'string') {
|
|
154
|
-
scriptObj =
|
|
155
|
+
scriptObj = Script.fromASM(script)
|
|
155
156
|
} else if (Array.isArray(script)) {
|
|
156
|
-
scriptObj =
|
|
157
|
+
scriptObj = Script.fromASM(script.join(' '))
|
|
157
158
|
} else if (Buffer.isBuffer(script)) {
|
|
158
159
|
return script.length
|
|
159
160
|
} else if (script && typeof script.toBuffer === 'function') {
|
|
@@ -292,7 +293,7 @@ function optimizeScript(script) {
|
|
|
292
293
|
// Create script object from optimized ASM
|
|
293
294
|
let optimizedScript = null
|
|
294
295
|
try {
|
|
295
|
-
optimizedScript =
|
|
296
|
+
optimizedScript = Script.fromASM(optimizedASM)
|
|
296
297
|
} catch (err) {
|
|
297
298
|
// If we can't create a script object, that's okay
|
|
298
299
|
optimizedScript = null
|
|
@@ -372,7 +373,7 @@ function compareScripts(scriptA, scriptB) {
|
|
|
372
373
|
let bufferA, bufferB
|
|
373
374
|
|
|
374
375
|
if (typeof scriptA === 'string') {
|
|
375
|
-
bufferA =
|
|
376
|
+
bufferA = Script.fromASM(scriptA).toBuffer()
|
|
376
377
|
} else if (Buffer.isBuffer(scriptA)) {
|
|
377
378
|
bufferA = scriptA
|
|
378
379
|
} else {
|
|
@@ -380,7 +381,7 @@ function compareScripts(scriptA, scriptB) {
|
|
|
380
381
|
}
|
|
381
382
|
|
|
382
383
|
if (typeof scriptB === 'string') {
|
|
383
|
-
bufferB =
|
|
384
|
+
bufferB = Script.fromASM(scriptB).toBuffer()
|
|
384
385
|
} else if (Buffer.isBuffer(scriptB)) {
|
|
385
386
|
bufferB = scriptB
|
|
386
387
|
} else {
|
|
@@ -13,7 +13,15 @@
|
|
|
13
13
|
|
|
14
14
|
'use strict'
|
|
15
15
|
|
|
16
|
-
var
|
|
16
|
+
var Signature = require('../crypto/signature')
|
|
17
|
+
var BN = require('../crypto/bn')
|
|
18
|
+
var Transaction = require('../transaction')
|
|
19
|
+
var PrivateKey = require('../privatekey')
|
|
20
|
+
var Script = require('../script')
|
|
21
|
+
// Named Sighash, not sighash: this file already uses `sighash` as a local
|
|
22
|
+
// variable for a SIGHASH instance further down, and a module-scope binding of
|
|
23
|
+
// the same name would be shadowed inside that function.
|
|
24
|
+
var Sighash = require('../transaction/sighash')
|
|
17
25
|
|
|
18
26
|
/**
|
|
19
27
|
* SIGHASH Class - SIGHASH flag analysis and utilities
|
|
@@ -24,7 +32,7 @@ function SIGHASH(sighashType) {
|
|
|
24
32
|
return new SIGHASH(sighashType)
|
|
25
33
|
}
|
|
26
34
|
|
|
27
|
-
this.sighashType = sighashType || (
|
|
35
|
+
this.sighashType = sighashType || (Signature.SIGHASH_ALL | Signature.SIGHASH_FORKID)
|
|
28
36
|
this.analysis = this._analyzeFlags()
|
|
29
37
|
}
|
|
30
38
|
|
|
@@ -79,30 +87,30 @@ SIGHASH.prototype.getZeroHashBehavior = function() {
|
|
|
79
87
|
*/
|
|
80
88
|
SIGHASH.prototype.generateExample = function() {
|
|
81
89
|
// Create simple single-input transaction to avoid complex script size issues
|
|
82
|
-
var privateKey =
|
|
90
|
+
var privateKey = PrivateKey.fromRandom()
|
|
83
91
|
var address = privateKey.toAddress()
|
|
84
92
|
|
|
85
93
|
// Create simple P2PKH UTXO
|
|
86
94
|
var utxo = {
|
|
87
95
|
txId: 'a'.repeat(64),
|
|
88
96
|
outputIndex: 0,
|
|
89
|
-
script:
|
|
97
|
+
script: Script.buildPublicKeyHashOut(address).toHex(),
|
|
90
98
|
satoshis: 100000
|
|
91
99
|
}
|
|
92
100
|
|
|
93
101
|
// Create simple transaction
|
|
94
|
-
var transaction = new
|
|
102
|
+
var transaction = new Transaction()
|
|
95
103
|
.from(utxo)
|
|
96
104
|
.to(address, 99000)
|
|
97
105
|
|
|
98
106
|
// Generate preimage for the input with our SIGHASH type
|
|
99
|
-
var subscript =
|
|
100
|
-
var preimageBuffer =
|
|
107
|
+
var subscript = Script.fromHex(utxo.script)
|
|
108
|
+
var preimageBuffer = Sighash.sighashPreimage(
|
|
101
109
|
transaction,
|
|
102
110
|
this.sighashType,
|
|
103
111
|
0,
|
|
104
112
|
subscript,
|
|
105
|
-
new
|
|
113
|
+
new BN(utxo.satoshis)
|
|
106
114
|
)
|
|
107
115
|
|
|
108
116
|
var Preimage = require('./preimage')
|
|
@@ -261,15 +269,15 @@ SIGHASH.prototype._analyzeFlags = function() {
|
|
|
261
269
|
* @returns {Array} Array of SIGHASH type objects
|
|
262
270
|
*/
|
|
263
271
|
SIGHASH.getAllTypes = function() {
|
|
264
|
-
var forkId =
|
|
272
|
+
var forkId = Signature.SIGHASH_FORKID
|
|
265
273
|
|
|
266
274
|
return [
|
|
267
|
-
{ name: 'ALL', value:
|
|
268
|
-
{ name: 'NONE', value:
|
|
269
|
-
{ name: 'SINGLE', value:
|
|
270
|
-
{ name: 'ALL | ANYONECANPAY', value:
|
|
271
|
-
{ name: 'NONE | ANYONECANPAY', value:
|
|
272
|
-
{ name: 'SINGLE | ANYONECANPAY', value:
|
|
275
|
+
{ name: 'ALL', value: Signature.SIGHASH_ALL | forkId },
|
|
276
|
+
{ name: 'NONE', value: Signature.SIGHASH_NONE | forkId },
|
|
277
|
+
{ name: 'SINGLE', value: Signature.SIGHASH_SINGLE | forkId },
|
|
278
|
+
{ name: 'ALL | ANYONECANPAY', value: Signature.SIGHASH_ALL | Signature.SIGHASH_ANYONECANPAY | forkId },
|
|
279
|
+
{ name: 'NONE | ANYONECANPAY', value: Signature.SIGHASH_NONE | Signature.SIGHASH_ANYONECANPAY | forkId },
|
|
280
|
+
{ name: 'SINGLE | ANYONECANPAY', value: Signature.SIGHASH_SINGLE | Signature.SIGHASH_ANYONECANPAY | forkId }
|
|
273
281
|
]
|
|
274
282
|
}
|
|
275
283
|
|
|
@@ -13,98 +13,105 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
// Browser-safe require
|
|
16
|
-
const
|
|
17
|
-
const
|
|
16
|
+
const _global = (typeof window !== 'undefined' && window.bsv) ? window.bsv : null
|
|
17
|
+
const Script = _global ? _global.Script : require('../script')
|
|
18
|
+
const Interpreter = _global ? _global.Script.Interpreter : require('../script/interpreter')
|
|
19
|
+
const Opcode = _global ? _global.Opcode : require('../opcode')
|
|
20
|
+
const Transaction = _global ? _global.Transaction : require('../transaction')
|
|
21
|
+
const Input = _global ? _global.Transaction.Input : require('../transaction/input')
|
|
22
|
+
const Output = _global ? _global.Transaction.Output : require('../transaction/output')
|
|
23
|
+
const BN = _global ? _global.crypto.BN : require('../crypto/bn')
|
|
24
|
+
const util = require('util')
|
|
18
25
|
|
|
19
|
-
function bufferToHexArray(stack) {
|
|
20
|
-
return stack.map((buf) => buf.toString('hex'))
|
|
26
|
+
function bufferToHexArray (stack) {
|
|
27
|
+
return stack.map((buf) => buf.toString('hex'))
|
|
21
28
|
}
|
|
22
29
|
|
|
23
30
|
/**
|
|
24
31
|
* Executes a locking/unlocking script and prints intermediate stack states.
|
|
25
32
|
*/
|
|
26
|
-
function runScript(lockingHex, unlockingHex) {
|
|
27
|
-
console.log(
|
|
28
|
-
console.log(
|
|
29
|
-
console.log(
|
|
33
|
+
function runScript (lockingHex, unlockingHex) {
|
|
34
|
+
console.log('===========================================')
|
|
35
|
+
console.log('🔍 STACK EXAMINATION TOOL')
|
|
36
|
+
console.log('===========================================\n')
|
|
30
37
|
|
|
31
|
-
console.log(
|
|
32
|
-
console.log(
|
|
33
|
-
console.log(
|
|
38
|
+
console.log('🔐 Locking Script:', lockingHex)
|
|
39
|
+
console.log('🔓 Unlocking Script:', unlockingHex)
|
|
40
|
+
console.log('-------------------------------------------')
|
|
34
41
|
|
|
35
42
|
try {
|
|
36
|
-
const lockingScript =
|
|
37
|
-
const unlockingScript =
|
|
43
|
+
const lockingScript = Script.fromHex(lockingHex)
|
|
44
|
+
const unlockingScript = Script.fromHex(unlockingHex)
|
|
38
45
|
|
|
39
|
-
const combined =
|
|
46
|
+
const combined = Script.fromBuffer(
|
|
40
47
|
Buffer.concat([unlockingScript.toBuffer(), lockingScript.toBuffer()])
|
|
41
|
-
)
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
const interpreter = new Interpreter()
|
|
51
|
+
const tx = new Transaction()
|
|
42
52
|
|
|
43
|
-
const interpreter = new bsv.Script.Interpreter();
|
|
44
|
-
const tx = new bsv.Transaction();
|
|
45
|
-
|
|
46
53
|
// Create proper transaction context
|
|
47
|
-
const dummyInput = new
|
|
54
|
+
const dummyInput = new Input({
|
|
48
55
|
prevTxId: '0'.repeat(64),
|
|
49
56
|
outputIndex: 0,
|
|
50
|
-
script:
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
tx.addInput(dummyInput)
|
|
54
|
-
tx.addOutput(new
|
|
55
|
-
satoshis: 100000,
|
|
56
|
-
script: lockingScript
|
|
57
|
-
}))
|
|
58
|
-
|
|
59
|
-
const scriptChunks = combined.chunks
|
|
60
|
-
const sandbox = new
|
|
61
|
-
sandbox.script = combined
|
|
62
|
-
sandbox.tx = tx
|
|
63
|
-
sandbox.nIn = 0
|
|
64
|
-
sandbox.flags =
|
|
57
|
+
script: Script.empty()
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
tx.addInput(dummyInput)
|
|
61
|
+
tx.addOutput(new Output({
|
|
62
|
+
satoshis: 100000,
|
|
63
|
+
script: lockingScript
|
|
64
|
+
}))
|
|
65
|
+
|
|
66
|
+
const scriptChunks = combined.chunks
|
|
67
|
+
const sandbox = new Interpreter()
|
|
68
|
+
sandbox.script = combined
|
|
69
|
+
sandbox.tx = tx
|
|
70
|
+
sandbox.nIn = 0
|
|
71
|
+
sandbox.flags = Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID
|
|
65
72
|
|
|
66
73
|
// Step through each opcode
|
|
67
74
|
for (let i = 0; i < scriptChunks.length; i++) {
|
|
68
|
-
const chunk = scriptChunks[i]
|
|
75
|
+
const chunk = scriptChunks[i]
|
|
69
76
|
try {
|
|
70
77
|
// Check if step method exists (compatibility check)
|
|
71
78
|
if (typeof sandbox.step === 'function') {
|
|
72
|
-
sandbox.step()
|
|
79
|
+
sandbox.step()
|
|
73
80
|
} else {
|
|
74
|
-
console.log(
|
|
75
|
-
break
|
|
81
|
+
console.log('⚠️ Step-by-step execution not supported in this BSV version')
|
|
82
|
+
break
|
|
76
83
|
}
|
|
77
|
-
|
|
78
|
-
console.log(`\n🧩 Step ${i + 1}: ${
|
|
79
|
-
console.log(
|
|
80
|
-
console.log(
|
|
84
|
+
|
|
85
|
+
console.log(`\n🧩 Step ${i + 1}: ${Opcode.reverseMap[chunk.opcodenum] || 'PUSH'}`)
|
|
86
|
+
console.log('Stack:', bufferToHexArray(sandbox.stack))
|
|
87
|
+
console.log('AltStack:', bufferToHexArray(sandbox.altstack))
|
|
81
88
|
} catch (err) {
|
|
82
|
-
console.log(`⚠️ Error executing opcode ${i + 1}:`, err.message)
|
|
83
|
-
break
|
|
89
|
+
console.log(`⚠️ Error executing opcode ${i + 1}:`, err.message)
|
|
90
|
+
break
|
|
84
91
|
}
|
|
85
92
|
}
|
|
86
93
|
|
|
87
94
|
// Final verification with proper satoshis parameter
|
|
88
|
-
const satoshisBN = new
|
|
95
|
+
const satoshisBN = new BN(100000)
|
|
89
96
|
const verified = interpreter.verify(
|
|
90
97
|
unlockingScript,
|
|
91
98
|
lockingScript,
|
|
92
99
|
tx,
|
|
93
100
|
0,
|
|
94
|
-
|
|
101
|
+
Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID,
|
|
95
102
|
satoshisBN
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
console.log(
|
|
99
|
-
console.log(
|
|
100
|
-
console.log(
|
|
101
|
-
console.log(
|
|
102
|
-
console.log(
|
|
103
|
-
|
|
104
|
-
return verified
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
console.log('\n===========================================')
|
|
106
|
+
console.log('✅ Final Result:', verified ? 'TRUE (Success)' : '❌ FALSE (Failure)')
|
|
107
|
+
console.log('Final Stack:', bufferToHexArray(sandbox.stack || []))
|
|
108
|
+
console.log('AltStack:', bufferToHexArray(sandbox.altstack || []))
|
|
109
|
+
console.log('===========================================')
|
|
110
|
+
|
|
111
|
+
return verified
|
|
105
112
|
} catch (err) {
|
|
106
|
-
console.error(
|
|
107
|
-
return false
|
|
113
|
+
console.error('❌ Error in script execution:', err.message)
|
|
114
|
+
return false
|
|
108
115
|
}
|
|
109
116
|
}
|
|
110
117
|
|
|
@@ -113,17 +120,17 @@ function runScript(lockingHex, unlockingHex) {
|
|
|
113
120
|
// ============================================
|
|
114
121
|
if (typeof require !== 'undefined' && require.main === module) {
|
|
115
122
|
if (process.argv.length < 4) {
|
|
116
|
-
console.log(
|
|
117
|
-
process.exit(1)
|
|
123
|
+
console.log('Usage: node stack_examiner.js <locking_script_hex> <unlocking_script_hex>')
|
|
124
|
+
process.exit(1)
|
|
118
125
|
}
|
|
119
126
|
|
|
120
|
-
const locking = process.argv[2]
|
|
121
|
-
const unlocking = process.argv[3]
|
|
122
|
-
runScript(locking, unlocking)
|
|
127
|
+
const locking = process.argv[2]
|
|
128
|
+
const unlocking = process.argv[3]
|
|
129
|
+
runScript(locking, unlocking)
|
|
123
130
|
}
|
|
124
131
|
|
|
125
132
|
// Export for module usage
|
|
126
133
|
module.exports = {
|
|
127
134
|
runScript,
|
|
128
135
|
bufferToHexArray
|
|
129
|
-
}
|
|
136
|
+
}
|
|
@@ -39,13 +39,13 @@
|
|
|
39
39
|
* Requires post-Genesis limits (SmartContract.enableGenesis()).
|
|
40
40
|
*/
|
|
41
41
|
|
|
42
|
-
var
|
|
43
|
-
var P = require('
|
|
44
|
-
var H = require('
|
|
42
|
+
var BN = require('../crypto/bn')
|
|
43
|
+
var P = require('../covenant/pushtx')
|
|
44
|
+
var H = require('../covenant/helpers')
|
|
45
45
|
var A = require('./authorizers')
|
|
46
46
|
|
|
47
|
-
var Script =
|
|
48
|
-
var Opcode =
|
|
47
|
+
var Script = require('../script')
|
|
48
|
+
var Opcode = require('../opcode')
|
|
49
49
|
var n = H.scriptNum
|
|
50
50
|
|
|
51
51
|
function resolveCommit (owner, auth) {
|
|
@@ -285,7 +285,7 @@ function transferOrdinal (signer, newOwnerHash, spend, ordinalSats, lockingScrip
|
|
|
285
285
|
function ser (o) { return o.toBufferWriter().toBuffer() }
|
|
286
286
|
var before = Buffer.concat(outs.slice(0, tokenIndex).map(ser))
|
|
287
287
|
var after = Buffer.concat(outs.slice(tokenIndex + 1).map(ser))
|
|
288
|
-
var tokenValue = new
|
|
288
|
+
var tokenValue = new BN(ordinalSats).toBuffer({ endian: 'little', size: 8 })
|
|
289
289
|
|
|
290
290
|
return unlockTransferMulti(signer, newOwnerHash, spend, ordinalSats, lockingScript, {
|
|
291
291
|
before: before,
|
|
@@ -15,7 +15,13 @@
|
|
|
15
15
|
|
|
16
16
|
'use strict'
|
|
17
17
|
|
|
18
|
-
var
|
|
18
|
+
var sighash = require('../transaction/sighash')
|
|
19
|
+
var Signature = require('../crypto/signature')
|
|
20
|
+
var BN = require('../crypto/bn')
|
|
21
|
+
var Transaction = require('../transaction')
|
|
22
|
+
var PrivateKey = require('../privatekey')
|
|
23
|
+
var Networks = require('../networks')
|
|
24
|
+
var Script = require('../script')
|
|
19
25
|
var crypto = require('crypto')
|
|
20
26
|
|
|
21
27
|
/**
|
|
@@ -28,14 +34,14 @@ function UTXOGenerator(options) {
|
|
|
28
34
|
}
|
|
29
35
|
|
|
30
36
|
this.options = options || {}
|
|
31
|
-
this.network = this.options.network ||
|
|
37
|
+
this.network = this.options.network || Networks.mainnet
|
|
32
38
|
this.keyRing = {} // Store generated keys
|
|
33
39
|
this.utxoPool = [] // Store generated UTXOs
|
|
34
40
|
|
|
35
41
|
// Initialize with SmartUTXO integration via direct require so that
|
|
36
42
|
// touching this internal integration path doesn't surface the
|
|
37
|
-
//
|
|
38
|
-
// consumers who reach for
|
|
43
|
+
// SmartUTXO deprecation warning (the warning is for downstream
|
|
44
|
+
// consumers who reach for SmartUTXO themselves, not for our own
|
|
39
45
|
// internal coupling). Try/catch because smartutxo is Node-only.
|
|
40
46
|
try {
|
|
41
47
|
var SmartUTXO = require('../smartutxo')
|
|
@@ -51,7 +57,7 @@ function UTXOGenerator(options) {
|
|
|
51
57
|
UTXOGenerator.prototype.generateKeypair = function(label) {
|
|
52
58
|
label = label || 'key_' + Date.now()
|
|
53
59
|
|
|
54
|
-
var privateKey =
|
|
60
|
+
var privateKey = PrivateKey.fromRandom(this.network)
|
|
55
61
|
var publicKey = privateKey.toPublicKey()
|
|
56
62
|
var address = privateKey.toAddress(this.network)
|
|
57
63
|
|
|
@@ -119,25 +125,25 @@ UTXOGenerator.prototype._createSingleUTXO = function(config) {
|
|
|
119
125
|
|
|
120
126
|
switch (config.scriptType) {
|
|
121
127
|
case 'P2PKH':
|
|
122
|
-
script =
|
|
128
|
+
script = Script.buildPublicKeyHashOut(config.keypair.address)
|
|
123
129
|
scriptHex = script.toHex()
|
|
124
130
|
break
|
|
125
131
|
|
|
126
132
|
case 'P2SH':
|
|
127
133
|
// Create a simple multisig for P2SH example
|
|
128
|
-
var redeemScript =
|
|
129
|
-
script =
|
|
134
|
+
var redeemScript = Script.buildMultisigOut([config.keypair.publicKey], 1)
|
|
135
|
+
script = Script.buildScriptHashOut(redeemScript)
|
|
130
136
|
scriptHex = script.toHex()
|
|
131
137
|
break
|
|
132
138
|
|
|
133
139
|
case 'CUSTOM':
|
|
134
140
|
// Allow custom script injection
|
|
135
|
-
script = config.customScript ||
|
|
141
|
+
script = config.customScript || Script.buildPublicKeyHashOut(config.keypair.address)
|
|
136
142
|
scriptHex = script.toHex()
|
|
137
143
|
break
|
|
138
144
|
|
|
139
145
|
default:
|
|
140
|
-
script =
|
|
146
|
+
script = Script.buildPublicKeyHashOut(config.keypair.address)
|
|
141
147
|
scriptHex = script.toHex()
|
|
142
148
|
}
|
|
143
149
|
|
|
@@ -174,7 +180,7 @@ UTXOGenerator.prototype.createTestTransaction = function(config) {
|
|
|
174
180
|
}, 0)
|
|
175
181
|
|
|
176
182
|
// Create transaction
|
|
177
|
-
var transaction = new
|
|
183
|
+
var transaction = new Transaction()
|
|
178
184
|
|
|
179
185
|
// Add inputs
|
|
180
186
|
inputUTXOs.forEach(function(utxo) {
|
|
@@ -217,15 +223,15 @@ UTXOGenerator.prototype.createTestTransaction = function(config) {
|
|
|
217
223
|
|
|
218
224
|
// Preimage generation helper
|
|
219
225
|
generatePreimage: function(inputIndex, sighashType) {
|
|
220
|
-
sighashType = sighashType ||
|
|
226
|
+
sighashType = sighashType || Signature.SIGHASH_ALL | Signature.SIGHASH_FORKID
|
|
221
227
|
var utxo = inputUTXOs[inputIndex]
|
|
222
228
|
|
|
223
|
-
return
|
|
229
|
+
return sighash.sighashPreimage(
|
|
224
230
|
transaction,
|
|
225
231
|
sighashType,
|
|
226
232
|
inputIndex,
|
|
227
|
-
|
|
228
|
-
new
|
|
233
|
+
Script.fromHex(utxo.script),
|
|
234
|
+
new BN(utxo.satoshis)
|
|
229
235
|
)
|
|
230
236
|
}
|
|
231
237
|
}
|