@smartledger/bsv 3.1.1 → 3.2.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 +123 -1
- package/README.md +233 -277
- package/bsv.bundle.js +39 -0
- package/bsv.min.js +8 -8
- package/docs/ADVANCED_COVENANT_DEVELOPMENT.md +533 -0
- package/docs/COVENANT_DEVELOPMENT_RESOLVED.md +169 -0
- package/docs/CUSTOM_SCRIPT_DEVELOPMENT.md +320 -0
- package/docs/README.md +201 -0
- package/docs/block.md +46 -0
- package/docs/ecies.md +102 -0
- package/docs/index.md +104 -0
- package/docs/nchain.md +958 -0
- package/docs/networks.md +55 -0
- package/docs/preimage.md +126 -0
- package/docs/script.md +139 -0
- package/docs/transaction.md +174 -0
- package/docs/unspentoutput.md +32 -0
- package/examples/README.md +200 -0
- package/examples/basic/transaction-creation.js +534 -0
- package/examples/basic/transaction_signature_api_gap.js +178 -0
- package/examples/covenants/advanced_covenant_demo.js +219 -0
- package/examples/covenants/covenant_interface_demo.js +270 -0
- package/examples/covenants/covenant_manual_signature_resolved.js +212 -0
- package/examples/covenants/covenant_signature_template.js +117 -0
- package/examples/covenants2/covenant_bidirectional_example.js +262 -0
- package/examples/covenants2/covenant_utils_demo.js +120 -0
- package/examples/covenants2/preimage_covenant_utils.js +287 -0
- package/examples/covenants2/production_integration.js +256 -0
- package/examples/data/covenant_utxos.json +28 -0
- package/examples/data/utxos.json +26 -0
- package/examples/preimage/README.md +178 -0
- package/examples/preimage/extract_preimage_bidirectional.js +421 -0
- package/examples/preimage/generate_sample_preimage.js +208 -0
- package/examples/preimage/generate_sighash_examples.js +152 -0
- package/examples/preimage/parse_preimage.js +117 -0
- package/examples/preimage/test_preimage_extractor.js +53 -0
- package/examples/preimage/test_varint_extraction.js +95 -0
- package/examples/scripts/custom_script_helper_example.js +273 -0
- package/examples/scripts/custom_script_signature_test.js +344 -0
- package/examples/scripts/script_interpreter.js +193 -0
- package/examples/smart_contract/complete_workflow_demo.js +343 -0
- package/examples/smart_contract/covenant_builder_demo.js +176 -0
- package/examples/smart_contract/script_testing_integration.js +198 -0
- package/index.js +3 -0
- package/lib/covenant-interface.js +713 -0
- package/lib/opcode.js +14 -7
- package/lib/smart_contract/API_REFERENCE.md +862 -0
- package/lib/smart_contract/DOCUMENTATION_SUMMARY.md +201 -0
- package/lib/smart_contract/EXAMPLES.md +751 -0
- package/lib/smart_contract/QUICK_START.md +549 -0
- package/lib/smart_contract/README.md +395 -0
- package/lib/smart_contract/builder.js +452 -0
- package/lib/smart_contract/covenant.js +336 -0
- package/lib/smart_contract/covenant_builder.js +512 -0
- package/lib/smart_contract/index.js +350 -0
- package/lib/smart_contract/opcode_list.js +30 -0
- package/lib/smart_contract/opcode_map.js +1174 -0
- package/lib/smart_contract/opcodes.md +1173 -0
- package/lib/smart_contract/preimage.js +903 -0
- package/lib/smart_contract/script_interpreter.js +236 -0
- package/lib/smart_contract/script_tester.js +487 -0
- package/lib/smart_contract/script_utils.js +621 -0
- package/lib/smart_contract/sighash.js +310 -0
- package/lib/smart_contract/smartledger-opcode_review.md +70 -0
- package/lib/smart_contract/stack_examiner.js +129 -0
- package/lib/smart_contract/test_integration.js +269 -0
- package/lib/smart_contract/utxo_generator.js +367 -0
- package/package.json +43 -10
- package/utilities/blockchain-state.json +20478 -3
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* script_interpreter_debugger.js
|
|
3
|
+
* ---------------------------------------------------------------
|
|
4
|
+
* Universal Bitcoin Script Interpreter Debugger for BSV
|
|
5
|
+
* Browser + Node.js compatible
|
|
6
|
+
* ---------------------------------------------------------------
|
|
7
|
+
* Usage:
|
|
8
|
+
* node script_interpreter_debugger.js [options]
|
|
9
|
+
*
|
|
10
|
+
* Options:
|
|
11
|
+
* --unlocking <hex|asm> Unlocking script (input scriptSig)
|
|
12
|
+
* --locking <hex|asm> Locking script (output scriptPubKey)
|
|
13
|
+
* --combined <hex|asm> Combined script (unlocking + locking)
|
|
14
|
+
* --step Step through opcode-by-opcode
|
|
15
|
+
* --truth Run full verification (TRUE/FALSE)
|
|
16
|
+
*
|
|
17
|
+
* Examples:
|
|
18
|
+
* node script_interpreter_debugger.js --locking "76a91489abcdefabbaabbaabbaabbaabbaabbaabbaabba88ac" --unlocking "4104abcd1234...ac" --truth
|
|
19
|
+
* node script_interpreter_debugger.js --combined "OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG" --step
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
// Browser-safe requires
|
|
23
|
+
let readline = null;
|
|
24
|
+
try {
|
|
25
|
+
// Only require readline in Node.js environment
|
|
26
|
+
if (typeof window === 'undefined' && typeof require !== 'undefined') {
|
|
27
|
+
readline = require("readline");
|
|
28
|
+
}
|
|
29
|
+
} catch (err) {
|
|
30
|
+
// Gracefully handle missing readline in browser
|
|
31
|
+
readline = null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const bsv = (typeof window !== 'undefined' && window.bsv) ? window.bsv : require("../../index.js");
|
|
35
|
+
|
|
36
|
+
// Debug: Show Script Interpreter module structure (uncomment to inspect)
|
|
37
|
+
// const ScriptInterpreter = bsv.Script.Interpreter;
|
|
38
|
+
// console.log("Script Interpreter Module:", ScriptInterpreter);
|
|
39
|
+
/**
|
|
40
|
+
* Parse input as either ASM or HEX.
|
|
41
|
+
*/
|
|
42
|
+
function parseScript(input) {
|
|
43
|
+
if (!input) return new bsv.Script();
|
|
44
|
+
const trimmed = input.trim();
|
|
45
|
+
const isHex = /^[0-9a-fA-F]+$/.test(trimmed.replace(/\s+/g, ""));
|
|
46
|
+
try {
|
|
47
|
+
return isHex
|
|
48
|
+
? bsv.Script.fromHex(trimmed)
|
|
49
|
+
: bsv.Script.fromASM(trimmed);
|
|
50
|
+
} catch (err) {
|
|
51
|
+
console.error("❌ Error parsing script:", err.message);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Display stack contents in readable format.
|
|
58
|
+
*/
|
|
59
|
+
function printStack(stack, altstack = []) {
|
|
60
|
+
const fmt = (b) => (b.length ? b.toString("hex") : "(empty)");
|
|
61
|
+
const top = stack.map(fmt);
|
|
62
|
+
console.log("Stack:", top.length ? top : ["(empty)"]);
|
|
63
|
+
if (altstack.length) console.log("AltStack:", altstack.map(fmt));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Execute script step-by-step with optional interactivity.
|
|
68
|
+
*/
|
|
69
|
+
async function stepThroughScript(combinedScript, tx, verbose = true) {
|
|
70
|
+
const interpreter = new bsv.Script.Interpreter();
|
|
71
|
+
interpreter.script = combinedScript;
|
|
72
|
+
interpreter.tx = tx;
|
|
73
|
+
interpreter.nIn = 0;
|
|
74
|
+
interpreter.flags = bsv.Script.Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID;
|
|
75
|
+
|
|
76
|
+
const chunks = combinedScript.chunks;
|
|
77
|
+
|
|
78
|
+
// Browser compatibility check for readline
|
|
79
|
+
let rl = null;
|
|
80
|
+
if (readline && typeof process !== 'undefined' && process.stdin) {
|
|
81
|
+
rl = readline.createInterface({
|
|
82
|
+
input: process.stdin,
|
|
83
|
+
output: process.stdout,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.log("===========================================");
|
|
88
|
+
console.log("🔍 SCRIPT INTERPRETER DEBUGGER (STEP MODE)");
|
|
89
|
+
console.log("===========================================\n");
|
|
90
|
+
console.log("Script:", combinedScript.toASM());
|
|
91
|
+
console.log("-------------------------------------------");
|
|
92
|
+
|
|
93
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
94
|
+
const chunk = chunks[i];
|
|
95
|
+
const opname = bsv.Opcode.reverseMap[chunk.opcodenum] || "PUSH";
|
|
96
|
+
|
|
97
|
+
if (verbose && rl) {
|
|
98
|
+
await new Promise((resolve) =>
|
|
99
|
+
rl.question(`\n[${i + 1}/${chunks.length}] Step (${opname}) — press Enter to execute...`, resolve)
|
|
100
|
+
);
|
|
101
|
+
} else if (verbose) {
|
|
102
|
+
console.log(`\n[${i + 1}/${chunks.length}] Step (${opname})`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
// Check if step method exists (compatibility check)
|
|
107
|
+
if (typeof interpreter.step === 'function') {
|
|
108
|
+
interpreter.step();
|
|
109
|
+
} else {
|
|
110
|
+
console.log("⚠️ Step-by-step execution not supported in this BSV version");
|
|
111
|
+
console.log("💡 Consider using runFullEvaluation instead");
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
console.log(`🧩 Executed: ${opname}`);
|
|
116
|
+
printStack(interpreter.stack, interpreter.altstack);
|
|
117
|
+
} catch (err) {
|
|
118
|
+
console.log(`⚠️ Error executing ${opname}: ${err.message}`);
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (rl) rl.close();
|
|
124
|
+
console.log("\n===========================================");
|
|
125
|
+
console.log("✅ Final Stack State:");
|
|
126
|
+
printStack(interpreter.stack || [], interpreter.altstack || []);
|
|
127
|
+
console.log("===========================================");
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Run complete truth evaluation (non-interactive)
|
|
132
|
+
*/
|
|
133
|
+
function runFullEvaluation(unlockingScript, lockingScript, tx) {
|
|
134
|
+
console.log("===========================================");
|
|
135
|
+
console.log("🔍 SCRIPT INTERPRETER DEBUGGER (FULL RUN)");
|
|
136
|
+
console.log("===========================================\n");
|
|
137
|
+
|
|
138
|
+
const interpreter = new bsv.Script.Interpreter();
|
|
139
|
+
|
|
140
|
+
// For smartledger-bsv, need to provide satoshisBN parameter
|
|
141
|
+
const satoshisBN = new bsv.crypto.BN(100000); // 100,000 satoshis
|
|
142
|
+
|
|
143
|
+
const verified = interpreter.verify(
|
|
144
|
+
unlockingScript,
|
|
145
|
+
lockingScript,
|
|
146
|
+
tx,
|
|
147
|
+
0,
|
|
148
|
+
bsv.Script.Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID,
|
|
149
|
+
satoshisBN
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
console.log("🔐 Locking Script:", lockingScript.toASM());
|
|
153
|
+
console.log("🔓 Unlocking Script:", unlockingScript.toASM());
|
|
154
|
+
console.log("-------------------------------------------");
|
|
155
|
+
console.log("✅ Result:", verified ? "TRUE (Success)" : "❌ FALSE (Failure)");
|
|
156
|
+
console.log("Final Stack:", interpreter.stack.map((b) => b.toString("hex")));
|
|
157
|
+
console.log("AltStack:", interpreter.altstack.map((b) => b.toString("hex")));
|
|
158
|
+
console.log("===========================================");
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Main entrypoint
|
|
163
|
+
*/
|
|
164
|
+
async function main() {
|
|
165
|
+
// Browser compatibility check
|
|
166
|
+
if (typeof process === 'undefined' || !process.argv) {
|
|
167
|
+
console.log("⚙️ CLI mode not available in browser environment");
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const args = process.argv.slice(2);
|
|
172
|
+
const getArg = (name) => {
|
|
173
|
+
const idx = args.indexOf(name);
|
|
174
|
+
return idx !== -1 && args[idx + 1] ? args[idx + 1] : null;
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const unlockingInput = getArg("--unlocking");
|
|
178
|
+
const lockingInput = getArg("--locking");
|
|
179
|
+
const combinedInput = getArg("--combined");
|
|
180
|
+
const stepMode = args.includes("--step");
|
|
181
|
+
const truthMode = args.includes("--truth");
|
|
182
|
+
|
|
183
|
+
// Build scripts
|
|
184
|
+
let unlockingScript, lockingScript, combinedScript;
|
|
185
|
+
if (combinedInput) {
|
|
186
|
+
combinedScript = parseScript(combinedInput);
|
|
187
|
+
} else {
|
|
188
|
+
unlockingScript = parseScript(unlockingInput);
|
|
189
|
+
lockingScript = parseScript(lockingInput);
|
|
190
|
+
const combinedBuf = Buffer.concat([
|
|
191
|
+
unlockingScript.toBuffer(),
|
|
192
|
+
lockingScript.toBuffer(),
|
|
193
|
+
]);
|
|
194
|
+
combinedScript = bsv.Script.fromBuffer(combinedBuf);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Dummy TX context for interpreter
|
|
198
|
+
const tx = new bsv.Transaction();
|
|
199
|
+
|
|
200
|
+
// Create proper input with UTXO information
|
|
201
|
+
const dummyInput = new bsv.Transaction.Input({
|
|
202
|
+
prevTxId: '0'.repeat(64),
|
|
203
|
+
outputIndex: 0,
|
|
204
|
+
script: bsv.Script.empty(),
|
|
205
|
+
satoshis: 100000,
|
|
206
|
+
output: new bsv.Transaction.Output({
|
|
207
|
+
satoshis: 100000,
|
|
208
|
+
script: bsv.Script.empty()
|
|
209
|
+
})
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
tx.addInput(dummyInput);
|
|
213
|
+
tx.addOutput(new bsv.Transaction.Output({ satoshis: 100000, script: bsv.Script.empty() }));
|
|
214
|
+
|
|
215
|
+
if (stepMode) {
|
|
216
|
+
await stepThroughScript(combinedScript, tx, true);
|
|
217
|
+
} else if (truthMode) {
|
|
218
|
+
runFullEvaluation(unlockingScript || bsv.Script.empty(), lockingScript || bsv.Script.empty(), tx);
|
|
219
|
+
} else {
|
|
220
|
+
console.log("⚙️ No mode specified. Use --step or --truth");
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Export functions for module usage
|
|
225
|
+
module.exports = {
|
|
226
|
+
parseScript,
|
|
227
|
+
printStack,
|
|
228
|
+
stepThroughScript,
|
|
229
|
+
runFullEvaluation,
|
|
230
|
+
main
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
// CLI execution
|
|
234
|
+
if (typeof require !== 'undefined' && require.main === module) {
|
|
235
|
+
main();
|
|
236
|
+
}
|