@smartledger/bsv 7.9.0 → 7.10.1
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 +103 -0
- 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 +86 -5
- 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 +418 -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/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 -139
- 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/build/bundle_externals.js +116 -0
- package/version.js +1 -1
|
@@ -20,204 +20,211 @@
|
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
// Browser-safe requires
|
|
23
|
-
let readline = null
|
|
23
|
+
let readline = null
|
|
24
24
|
try {
|
|
25
25
|
// Only require readline in Node.js environment
|
|
26
26
|
if (typeof window === 'undefined' && typeof require !== 'undefined') {
|
|
27
|
-
readline = require(
|
|
27
|
+
readline = require('readline')
|
|
28
28
|
}
|
|
29
29
|
} catch (err) {
|
|
30
30
|
// Gracefully handle missing readline in browser
|
|
31
|
-
readline = null
|
|
31
|
+
readline = null
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
const
|
|
34
|
+
const _global = (typeof window !== 'undefined' && window.bsv) ? window.bsv : null
|
|
35
|
+
const Script = _global ? _global.Script : require('../script')
|
|
36
|
+
const Interpreter = _global ? _global.Script.Interpreter : require('../script/interpreter')
|
|
37
|
+
const Opcode = _global ? _global.Opcode : require('../opcode')
|
|
38
|
+
const BN = _global ? _global.crypto.BN : require('../crypto/bn')
|
|
39
|
+
const Transaction = _global ? _global.Transaction : require('../transaction')
|
|
40
|
+
const Input = _global ? _global.Transaction.Input : require('../transaction/input')
|
|
41
|
+
const Output = _global ? _global.Transaction.Output : require('../transaction/output')
|
|
35
42
|
|
|
36
43
|
// Debug: Show Script Interpreter module structure (uncomment to inspect)
|
|
37
|
-
// const ScriptInterpreter =
|
|
44
|
+
// const ScriptInterpreter = Interpreter;
|
|
38
45
|
// console.log("Script Interpreter Module:", ScriptInterpreter);
|
|
39
46
|
/**
|
|
40
47
|
* Parse input as either ASM or HEX.
|
|
41
48
|
*/
|
|
42
|
-
function parseScript(input) {
|
|
43
|
-
if (!input) return new
|
|
44
|
-
const trimmed = input.trim()
|
|
45
|
-
const isHex = /^[0-9a-fA-F]+$/.test(trimmed.replace(/\s+/g,
|
|
49
|
+
function parseScript (input) {
|
|
50
|
+
if (!input) return new Script()
|
|
51
|
+
const trimmed = input.trim()
|
|
52
|
+
const isHex = /^[0-9a-fA-F]+$/.test(trimmed.replace(/\s+/g, ''))
|
|
46
53
|
try {
|
|
47
54
|
return isHex
|
|
48
|
-
?
|
|
49
|
-
:
|
|
55
|
+
? Script.fromHex(trimmed)
|
|
56
|
+
: Script.fromASM(trimmed)
|
|
50
57
|
} catch (err) {
|
|
51
|
-
console.error(
|
|
52
|
-
process.exit(1)
|
|
58
|
+
console.error('❌ Error parsing script:', err.message)
|
|
59
|
+
process.exit(1)
|
|
53
60
|
}
|
|
54
61
|
}
|
|
55
62
|
|
|
56
63
|
/**
|
|
57
64
|
* Display stack contents in readable format.
|
|
58
65
|
*/
|
|
59
|
-
function printStack(stack, altstack = []) {
|
|
60
|
-
const fmt = (b) => (b.length ? b.toString(
|
|
61
|
-
const top = stack.map(fmt)
|
|
62
|
-
console.log(
|
|
63
|
-
if (altstack.length) console.log(
|
|
66
|
+
function printStack (stack, altstack = []) {
|
|
67
|
+
const fmt = (b) => (b.length ? b.toString('hex') : '(empty)')
|
|
68
|
+
const top = stack.map(fmt)
|
|
69
|
+
console.log('Stack:', top.length ? top : ['(empty)'])
|
|
70
|
+
if (altstack.length) console.log('AltStack:', altstack.map(fmt))
|
|
64
71
|
}
|
|
65
72
|
|
|
66
73
|
/**
|
|
67
74
|
* Execute script step-by-step with optional interactivity.
|
|
68
75
|
*/
|
|
69
|
-
async function stepThroughScript(combinedScript, tx, verbose = true) {
|
|
70
|
-
const interpreter = new
|
|
71
|
-
interpreter.script = combinedScript
|
|
72
|
-
interpreter.tx = tx
|
|
73
|
-
interpreter.nIn = 0
|
|
74
|
-
interpreter.flags =
|
|
75
|
-
|
|
76
|
-
const chunks = combinedScript.chunks
|
|
77
|
-
|
|
76
|
+
async function stepThroughScript (combinedScript, tx, verbose = true) {
|
|
77
|
+
const interpreter = new Interpreter()
|
|
78
|
+
interpreter.script = combinedScript
|
|
79
|
+
interpreter.tx = tx
|
|
80
|
+
interpreter.nIn = 0
|
|
81
|
+
interpreter.flags = Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID
|
|
82
|
+
|
|
83
|
+
const chunks = combinedScript.chunks
|
|
84
|
+
|
|
78
85
|
// Browser compatibility check for readline
|
|
79
|
-
let rl = null
|
|
86
|
+
let rl = null
|
|
80
87
|
if (readline && typeof process !== 'undefined' && process.stdin) {
|
|
81
88
|
rl = readline.createInterface({
|
|
82
89
|
input: process.stdin,
|
|
83
|
-
output: process.stdout
|
|
84
|
-
})
|
|
90
|
+
output: process.stdout
|
|
91
|
+
})
|
|
85
92
|
}
|
|
86
93
|
|
|
87
|
-
console.log(
|
|
88
|
-
console.log(
|
|
89
|
-
console.log(
|
|
90
|
-
console.log(
|
|
91
|
-
console.log(
|
|
94
|
+
console.log('===========================================')
|
|
95
|
+
console.log('🔍 SCRIPT INTERPRETER DEBUGGER (STEP MODE)')
|
|
96
|
+
console.log('===========================================\n')
|
|
97
|
+
console.log('Script:', combinedScript.toASM())
|
|
98
|
+
console.log('-------------------------------------------')
|
|
92
99
|
|
|
93
100
|
for (let i = 0; i < chunks.length; i++) {
|
|
94
|
-
const chunk = chunks[i]
|
|
95
|
-
const opname =
|
|
101
|
+
const chunk = chunks[i]
|
|
102
|
+
const opname = Opcode.reverseMap[chunk.opcodenum] || 'PUSH'
|
|
96
103
|
|
|
97
104
|
if (verbose && rl) {
|
|
98
105
|
await new Promise((resolve) =>
|
|
99
106
|
rl.question(`\n[${i + 1}/${chunks.length}] Step (${opname}) — press Enter to execute...`, resolve)
|
|
100
|
-
)
|
|
107
|
+
)
|
|
101
108
|
} else if (verbose) {
|
|
102
|
-
console.log(`\n[${i + 1}/${chunks.length}] Step (${opname})`)
|
|
109
|
+
console.log(`\n[${i + 1}/${chunks.length}] Step (${opname})`)
|
|
103
110
|
}
|
|
104
111
|
|
|
105
112
|
try {
|
|
106
113
|
// Check if step method exists (compatibility check)
|
|
107
114
|
if (typeof interpreter.step === 'function') {
|
|
108
|
-
interpreter.step()
|
|
115
|
+
interpreter.step()
|
|
109
116
|
} else {
|
|
110
|
-
console.log(
|
|
111
|
-
console.log(
|
|
112
|
-
break
|
|
117
|
+
console.log('⚠️ Step-by-step execution not supported in this BSV version')
|
|
118
|
+
console.log('💡 Consider using runFullEvaluation instead')
|
|
119
|
+
break
|
|
113
120
|
}
|
|
114
|
-
|
|
115
|
-
console.log(`🧩 Executed: ${opname}`)
|
|
116
|
-
printStack(interpreter.stack, interpreter.altstack)
|
|
121
|
+
|
|
122
|
+
console.log(`🧩 Executed: ${opname}`)
|
|
123
|
+
printStack(interpreter.stack, interpreter.altstack)
|
|
117
124
|
} catch (err) {
|
|
118
|
-
console.log(`⚠️ Error executing ${opname}: ${err.message}`)
|
|
119
|
-
break
|
|
125
|
+
console.log(`⚠️ Error executing ${opname}: ${err.message}`)
|
|
126
|
+
break
|
|
120
127
|
}
|
|
121
128
|
}
|
|
122
129
|
|
|
123
|
-
if (rl) rl.close()
|
|
124
|
-
console.log(
|
|
125
|
-
console.log(
|
|
126
|
-
printStack(interpreter.stack || [], interpreter.altstack || [])
|
|
127
|
-
console.log(
|
|
130
|
+
if (rl) rl.close()
|
|
131
|
+
console.log('\n===========================================')
|
|
132
|
+
console.log('✅ Final Stack State:')
|
|
133
|
+
printStack(interpreter.stack || [], interpreter.altstack || [])
|
|
134
|
+
console.log('===========================================')
|
|
128
135
|
}
|
|
129
136
|
|
|
130
137
|
/**
|
|
131
138
|
* Run complete truth evaluation (non-interactive)
|
|
132
139
|
*/
|
|
133
|
-
function runFullEvaluation(unlockingScript, lockingScript, tx) {
|
|
134
|
-
console.log(
|
|
135
|
-
console.log(
|
|
136
|
-
console.log(
|
|
140
|
+
function runFullEvaluation (unlockingScript, lockingScript, tx) {
|
|
141
|
+
console.log('===========================================')
|
|
142
|
+
console.log('🔍 SCRIPT INTERPRETER DEBUGGER (FULL RUN)')
|
|
143
|
+
console.log('===========================================\n')
|
|
144
|
+
|
|
145
|
+
const interpreter = new Interpreter()
|
|
137
146
|
|
|
138
|
-
const interpreter = new bsv.Script.Interpreter();
|
|
139
|
-
|
|
140
147
|
// For smartledger-bsv, need to provide satoshisBN parameter
|
|
141
|
-
const satoshisBN = new
|
|
142
|
-
|
|
148
|
+
const satoshisBN = new BN(100000) // 100,000 satoshis
|
|
149
|
+
|
|
143
150
|
const verified = interpreter.verify(
|
|
144
151
|
unlockingScript,
|
|
145
152
|
lockingScript,
|
|
146
153
|
tx,
|
|
147
154
|
0,
|
|
148
|
-
|
|
155
|
+
Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID,
|
|
149
156
|
satoshisBN
|
|
150
|
-
)
|
|
151
|
-
|
|
152
|
-
console.log(
|
|
153
|
-
console.log(
|
|
154
|
-
console.log(
|
|
155
|
-
console.log(
|
|
156
|
-
console.log(
|
|
157
|
-
console.log(
|
|
158
|
-
console.log(
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
console.log('🔐 Locking Script:', lockingScript.toASM())
|
|
160
|
+
console.log('🔓 Unlocking Script:', unlockingScript.toASM())
|
|
161
|
+
console.log('-------------------------------------------')
|
|
162
|
+
console.log('✅ Result:', verified ? 'TRUE (Success)' : '❌ FALSE (Failure)')
|
|
163
|
+
console.log('Final Stack:', interpreter.stack.map((b) => b.toString('hex')))
|
|
164
|
+
console.log('AltStack:', interpreter.altstack.map((b) => b.toString('hex')))
|
|
165
|
+
console.log('===========================================')
|
|
159
166
|
}
|
|
160
167
|
|
|
161
168
|
/**
|
|
162
169
|
* Main entrypoint
|
|
163
170
|
*/
|
|
164
|
-
async function main() {
|
|
171
|
+
async function main () {
|
|
165
172
|
// Browser compatibility check
|
|
166
173
|
if (typeof process === 'undefined' || !process.argv) {
|
|
167
|
-
console.log(
|
|
168
|
-
return
|
|
174
|
+
console.log('⚙️ CLI mode not available in browser environment')
|
|
175
|
+
return
|
|
169
176
|
}
|
|
170
177
|
|
|
171
|
-
const args = process.argv.slice(2)
|
|
178
|
+
const args = process.argv.slice(2)
|
|
172
179
|
const getArg = (name) => {
|
|
173
|
-
const idx = args.indexOf(name)
|
|
174
|
-
return idx !== -1 && args[idx + 1] ? args[idx + 1] : null
|
|
175
|
-
}
|
|
180
|
+
const idx = args.indexOf(name)
|
|
181
|
+
return idx !== -1 && args[idx + 1] ? args[idx + 1] : null
|
|
182
|
+
}
|
|
176
183
|
|
|
177
|
-
const unlockingInput = getArg(
|
|
178
|
-
const lockingInput = getArg(
|
|
179
|
-
const combinedInput = getArg(
|
|
180
|
-
const stepMode = args.includes(
|
|
181
|
-
const truthMode = args.includes(
|
|
184
|
+
const unlockingInput = getArg('--unlocking')
|
|
185
|
+
const lockingInput = getArg('--locking')
|
|
186
|
+
const combinedInput = getArg('--combined')
|
|
187
|
+
const stepMode = args.includes('--step')
|
|
188
|
+
const truthMode = args.includes('--truth')
|
|
182
189
|
|
|
183
190
|
// Build scripts
|
|
184
|
-
let unlockingScript, lockingScript, combinedScript
|
|
191
|
+
let unlockingScript, lockingScript, combinedScript
|
|
185
192
|
if (combinedInput) {
|
|
186
|
-
combinedScript = parseScript(combinedInput)
|
|
193
|
+
combinedScript = parseScript(combinedInput)
|
|
187
194
|
} else {
|
|
188
|
-
unlockingScript = parseScript(unlockingInput)
|
|
189
|
-
lockingScript = parseScript(lockingInput)
|
|
195
|
+
unlockingScript = parseScript(unlockingInput)
|
|
196
|
+
lockingScript = parseScript(lockingInput)
|
|
190
197
|
const combinedBuf = Buffer.concat([
|
|
191
198
|
unlockingScript.toBuffer(),
|
|
192
|
-
lockingScript.toBuffer()
|
|
193
|
-
])
|
|
194
|
-
combinedScript =
|
|
199
|
+
lockingScript.toBuffer()
|
|
200
|
+
])
|
|
201
|
+
combinedScript = Script.fromBuffer(combinedBuf)
|
|
195
202
|
}
|
|
196
203
|
|
|
197
204
|
// Dummy TX context for interpreter
|
|
198
|
-
const tx = new
|
|
199
|
-
|
|
205
|
+
const tx = new Transaction()
|
|
206
|
+
|
|
200
207
|
// Create proper input with UTXO information
|
|
201
|
-
const dummyInput = new
|
|
208
|
+
const dummyInput = new Input({
|
|
202
209
|
prevTxId: '0'.repeat(64),
|
|
203
210
|
outputIndex: 0,
|
|
204
|
-
script:
|
|
211
|
+
script: Script.empty(),
|
|
205
212
|
satoshis: 100000,
|
|
206
|
-
output: new
|
|
213
|
+
output: new Output({
|
|
207
214
|
satoshis: 100000,
|
|
208
|
-
script:
|
|
215
|
+
script: Script.empty()
|
|
209
216
|
})
|
|
210
|
-
})
|
|
211
|
-
|
|
212
|
-
tx.addInput(dummyInput)
|
|
213
|
-
tx.addOutput(new
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
tx.addInput(dummyInput)
|
|
220
|
+
tx.addOutput(new Output({ satoshis: 100000, script: Script.empty() }))
|
|
214
221
|
|
|
215
222
|
if (stepMode) {
|
|
216
|
-
await stepThroughScript(combinedScript, tx, true)
|
|
223
|
+
await stepThroughScript(combinedScript, tx, true)
|
|
217
224
|
} else if (truthMode) {
|
|
218
|
-
runFullEvaluation(unlockingScript ||
|
|
225
|
+
runFullEvaluation(unlockingScript || Script.empty(), lockingScript || Script.empty(), tx)
|
|
219
226
|
} else {
|
|
220
|
-
console.log(
|
|
227
|
+
console.log('⚙️ No mode specified. Use --step or --truth')
|
|
221
228
|
}
|
|
222
229
|
}
|
|
223
230
|
|
|
@@ -228,9 +235,9 @@ module.exports = {
|
|
|
228
235
|
stepThroughScript,
|
|
229
236
|
runFullEvaluation,
|
|
230
237
|
main
|
|
231
|
-
}
|
|
238
|
+
}
|
|
232
239
|
|
|
233
240
|
// CLI execution
|
|
234
241
|
if (typeof require !== 'undefined' && require.main === module) {
|
|
235
|
-
main()
|
|
242
|
+
main()
|
|
236
243
|
}
|
|
@@ -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
|
|