@smartledger/bsv 3.4.3 โ†’ 3.4.4

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.
Files changed (87) hide show
  1. package/CHANGELOG.md +321 -0
  2. package/README.md +72 -72
  3. package/SECURITY.md +88 -0
  4. package/bin/cli.js +13 -8
  5. package/bsv-covenant.min.js +4 -4
  6. package/bsv-gdaf.min.js +5 -5
  7. package/bsv-ltp.min.js +7 -7
  8. package/bsv-smartcontract.min.js +5 -5
  9. package/bsv.bundle.js +5 -5
  10. package/bsv.d.ts +486 -9
  11. package/bsv.min.js +5 -5
  12. package/docs/COVENANT_DEVELOPMENT_RESOLVED.md +2 -2
  13. package/docs/MODULE_REFERENCE_COMPLETE.md +60 -57
  14. package/docs/advanced/UTXO_MANAGER_GUIDE.md +1 -1
  15. package/docs/getting-started/INSTALLATION.md +30 -30
  16. package/docs/getting-started/QUICK_START.md +14 -14
  17. package/docs/migration/FROM_BSV_1_5_6.md +5 -5
  18. package/gdaf-entry.js +1 -2
  19. package/index.js +20 -7
  20. package/lib/smart_contract/covenant.js +10 -1
  21. package/lib/smartutxo.js +20 -12
  22. package/lib/transaction/transaction.js +7 -0
  23. package/ltp-entry.js +1 -2
  24. package/package.json +3 -3
  25. package/utilities/blockchain-state.js +32 -23
  26. package/demos/README.md +0 -188
  27. package/demos/architecture_demo.js +0 -247
  28. package/demos/browser-test.html +0 -1208
  29. package/demos/bsv_wallet_demo.js +0 -242
  30. package/demos/complete_ltp_demo.js +0 -511
  31. package/demos/debug_tools_demo.js +0 -87
  32. package/demos/demo_features.js +0 -123
  33. package/demos/easy_interface_demo.js +0 -109
  34. package/demos/ecies_demo.js +0 -182
  35. package/demos/gdaf_demo.js +0 -237
  36. package/demos/ltp_demo.js +0 -361
  37. package/demos/ltp_primitives_demo.js +0 -403
  38. package/demos/message_demo.js +0 -209
  39. package/demos/preimage_separation_demo.js +0 -383
  40. package/demos/script_helper_demo.js +0 -289
  41. package/demos/security_demo.js +0 -287
  42. package/demos/shamir_demo.js +0 -121
  43. package/demos/simple_demo.js +0 -204
  44. package/demos/simple_p2pkh_demo.js +0 -169
  45. package/demos/simple_utxo_preimage_demo.js +0 -196
  46. package/demos/smart_contract_demo.html +0 -1347
  47. package/demos/smart_contract_demo.js +0 -910
  48. package/demos/utxo_generator_demo.js +0 -244
  49. package/demos/validation_pipeline_demo.js +0 -155
  50. package/demos/web3keys.html +0 -740
  51. package/examples/README.md +0 -200
  52. package/examples/basic/transaction-creation.js +0 -534
  53. package/examples/basic/transaction_signature_api_gap.js +0 -178
  54. package/examples/complete_workflow_demo.js +0 -783
  55. package/examples/covenants/advanced_covenant_demo.js +0 -219
  56. package/examples/covenants/covenant_interface_demo.js +0 -270
  57. package/examples/covenants/covenant_manual_signature_resolved.js +0 -212
  58. package/examples/covenants/covenant_signature_template.js +0 -117
  59. package/examples/covenants2/covenant_bidirectional_example.js +0 -262
  60. package/examples/covenants2/covenant_utils_demo.js +0 -120
  61. package/examples/covenants2/preimage_covenant_utils.js +0 -287
  62. package/examples/covenants2/production_integration.js +0 -256
  63. package/examples/data/covenant_utxos.json +0 -28
  64. package/examples/data/utxos.json +0 -26
  65. package/examples/definitive_working_demo.js +0 -261
  66. package/examples/final_working_contracts.js +0 -338
  67. package/examples/legacy/README.md +0 -11
  68. package/examples/legacy/smart_contract_test_integration.js +0 -269
  69. package/examples/legacy/test_builtin_verify.js +0 -117
  70. package/examples/legacy/test_debug_integration.js +0 -71
  71. package/examples/legacy/test_ecdsa_little.js +0 -70
  72. package/examples/legacy/test_shamir.js +0 -221
  73. package/examples/legacy/test_smartverify_der.js +0 -110
  74. package/examples/preimage/README.md +0 -178
  75. package/examples/preimage/extract_preimage_bidirectional.js +0 -421
  76. package/examples/preimage/generate_sample_preimage.js +0 -208
  77. package/examples/preimage/generate_sighash_examples.js +0 -152
  78. package/examples/preimage/parse_preimage.js +0 -117
  79. package/examples/preimage/test_preimage_extractor.js +0 -53
  80. package/examples/preimage/test_varint_extraction.js +0 -95
  81. package/examples/scripts/custom_script_helper_example.js +0 -273
  82. package/examples/scripts/script_interpreter.js +0 -193
  83. package/examples/smart_contract/complete_workflow_demo.js +0 -343
  84. package/examples/smart_contract/covenant_builder_demo.js +0 -176
  85. package/examples/smart_contract/script_testing_integration.js +0 -198
  86. package/examples/smart_contract_templates.js +0 -718
  87. package/examples/working_smart_contracts.js +0 -348
@@ -1,421 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * extract_preimage_bidirectional.js
4
- * ---------------------------------------------------------------------
5
- * Extract any part of the transaction preimage intelligently by slicing
6
- * from either LEFT or RIGHT based on what is known.
7
- * Handles variable scriptCode length via dynamic slicing.
8
- *
9
- * Part of the Preimage Covenant Tools - implements bidirectional slicing
10
- * strategy for optimal preimage field extraction in Bitcoin Script.
11
- *
12
- * Usage:
13
- * node extract_preimage_bidirectional.js <raw_preimage_hex> <field_name>
14
- *
15
- * Example:
16
- * node extract_preimage_bidirectional.js 01000000ab12... scriptCode
17
- */
18
-
19
- const { Buffer } = require("buffer");
20
-
21
- // Fixed field definitions - LEFT side (known offsets from start)
22
- const LEFT_FIXED_FIELDS = [
23
- { name: "nVersion", len: 4 },
24
- { name: "hashPrevouts", len: 32 },
25
- { name: "hashSequence", len: 32 },
26
- { name: "outpoint_txid", len: 32 },
27
- { name: "outpoint_vout", len: 4 },
28
- // Note: scriptLen is VARIABLE (1-3 bytes CompactSize varint) - handled separately
29
- ];
30
-
31
- // Fixed field definitions - RIGHT side (known offsets from end)
32
- const RIGHT_FIXED_FIELDS = [
33
- { name: "value", len: 8 },
34
- { name: "nSequence", len: 4 },
35
- { name: "hashOutputs", len: 32 },
36
- { name: "nLocktime", len: 4 },
37
- { name: "sighashType", len: 4 },
38
- ];
39
-
40
- // Calculate total bytes on each side
41
- const LEFT_FIXED_TOTAL = LEFT_FIXED_FIELDS.reduce((a, f) => a + f.len, 0); // 104 bytes (without scriptLen varint)
42
- const RIGHT_TOTAL = RIGHT_FIXED_FIELDS.reduce((a, f) => a + f.len, 0); // 52 bytes
43
-
44
- // CompactSize varint decoder for scriptLen
45
- function decodeCompactSize(buf, offset) {
46
- if (offset >= buf.length) return { value: 0, size: 1 };
47
-
48
- const firstByte = buf[offset];
49
-
50
- if (firstByte < 0xfd) {
51
- // 1-byte encoding: 0-252
52
- return { value: firstByte, size: 1 };
53
- } else if (firstByte === 0xfd) {
54
- // 3-byte encoding: 0xfd + 2 bytes little-endian
55
- if (offset + 2 >= buf.length) return { value: 0, size: 1 };
56
- const value = buf.readUInt16LE(offset + 1);
57
- return { value, size: 3 };
58
- } else if (firstByte === 0xfe) {
59
- // 5-byte encoding: 0xfe + 4 bytes little-endian
60
- if (offset + 4 >= buf.length) return { value: 0, size: 1 };
61
- const value = buf.readUInt32LE(offset + 1);
62
- return { value, size: 5 };
63
- } else {
64
- // 0xff = 9-byte encoding (not used for script lengths)
65
- throw new Error('Invalid CompactSize varint: 8-byte integers not supported for scriptLen');
66
- }
67
- }
68
-
69
- // Helper functions
70
- function safeSlice(buf, start, end) {
71
- if (start >= buf.length) return Buffer.alloc(0);
72
- if (end > buf.length) end = buf.length;
73
- return buf.slice(start, end);
74
- }
75
-
76
- function parsePreimage(hex) {
77
- const buf = Buffer.from(hex, "hex");
78
- let offset = 0;
79
- const parsed = {};
80
-
81
- // Parse LEFT fixed fields (104 bytes)
82
- for (const f of LEFT_FIXED_FIELDS) {
83
- const part = safeSlice(buf, offset, offset + f.len);
84
- parsed[f.name] = part.toString("hex");
85
- offset += f.len;
86
- }
87
-
88
- // Parse CompactSize varint for scriptLen
89
- const scriptLenInfo = decodeCompactSize(buf, offset);
90
- parsed.scriptLen = scriptLenInfo.value;
91
- parsed.scriptLenSize = scriptLenInfo.size; // Track varint encoding size
92
- parsed.scriptLenRaw = safeSlice(buf, offset, offset + scriptLenInfo.size).toString("hex");
93
- offset += scriptLenInfo.size;
94
-
95
- // Parse variable scriptCode using decoded scriptLen
96
- const scriptCode = safeSlice(buf, offset, offset + parsed.scriptLen);
97
- parsed.scriptCode = scriptCode.toString("hex");
98
- offset += parsed.scriptLen;
99
-
100
- // Parse RIGHT fields
101
- for (const f of RIGHT_FIXED_FIELDS) {
102
- const part = safeSlice(buf, offset, offset + f.len);
103
- parsed[f.name] = part.toString("hex");
104
- offset += f.len;
105
- }
106
-
107
- // Add structure info for analysis
108
- parsed._structure = {
109
- leftFixed: LEFT_FIXED_TOTAL,
110
- scriptLenVarint: scriptLenInfo.size,
111
- scriptCode: parsed.scriptLen,
112
- rightFixed: RIGHT_TOTAL,
113
- totalCalculated: LEFT_FIXED_TOTAL + scriptLenInfo.size + parsed.scriptLen + RIGHT_TOTAL,
114
- totalActual: buf.length
115
- };
116
-
117
- return parsed;
118
- }
119
-
120
- function generateBidirectionalASM(field, preimageLength, parsed) {
121
- console.log(`\n๐Ÿง  Bidirectional Analysis for "${field}"`);
122
- console.log('='.repeat(60));
123
-
124
- // Determine extraction strategy
125
- const rightFields = RIGHT_FIXED_FIELDS.map(f => f.name);
126
- const leftFields = LEFT_FIXED_FIELDS.map(f => f.name);
127
-
128
- const isRightField = rightFields.includes(field);
129
- const isLeftField = leftFields.includes(field);
130
- const isDynamic = field === 'scriptCode';
131
- const isScriptLen = field === 'scriptLen';
132
-
133
- if (isRightField) {
134
- return generateRightExtractionASM(field, preimageLength);
135
- } else if (isLeftField) {
136
- return generateLeftExtractionASM(field);
137
- } else if (isDynamic) {
138
- return generateDynamicExtractionASM(field, parsed);
139
- } else if (isScriptLen) {
140
- return generateScriptLenExtractionASM(parsed);
141
- } else {
142
- throw new Error(`Unknown field: ${field}`);
143
- }
144
- }
145
-
146
- function generateRightExtractionASM(field, preimageLength) {
147
- // Calculate offset from end
148
- let offsetFromEnd = 0;
149
- let targetLen = 0;
150
-
151
- for (const f of RIGHT_FIXED_FIELDS) {
152
- if (f.name === field) {
153
- targetLen = f.len;
154
- break;
155
- }
156
- offsetFromEnd += f.len;
157
- }
158
-
159
- console.log(`๐Ÿ“ Strategy: Extract from RIGHT side`);
160
- console.log(` - Total preimage: ${preimageLength} bytes`);
161
- console.log(` - Right zone: ${RIGHT_TOTAL} bytes`);
162
- console.log(` - Offset from end: ${offsetFromEnd} bytes`);
163
- console.log(` - Field length: ${targetLen} bytes`);
164
-
165
- const asm = [
166
- `# ๐Ÿ”„ Extract ${field} from RIGHT side (bidirectional strategy)`,
167
- `OP_SIZE # Push preimage size: [preimage, size]`,
168
- `${RIGHT_TOTAL - offsetFromEnd} OP_SUB # Calculate split point: [preimage, split_point]`,
169
- `OP_SPLIT # Split: [left_part, right_part]`,
170
- `OP_DROP # Drop left: [right_part]`,
171
- `${targetLen} OP_SPLIT # Extract field: [remaining, ${field}]`,
172
- `OP_DROP # Clean up: [${field}]`,
173
- `# โœ… Result: ${field} is now on top of stack`
174
- ].join('\n');
175
-
176
- return asm;
177
- }
178
-
179
- function generateLeftExtractionASM(field) {
180
- // Calculate offset from start
181
- let offsetFromStart = 0;
182
- let targetLen = 0;
183
-
184
- for (const f of LEFT_FIXED_FIELDS) {
185
- if (f.name === field) {
186
- targetLen = f.len;
187
- break;
188
- }
189
- offsetFromStart += f.len;
190
- }
191
-
192
- console.log(`๐Ÿ“ Strategy: Extract from LEFT side`);
193
- console.log(` - Left fixed zone: ${LEFT_FIXED_TOTAL} bytes`);
194
- console.log(` - Offset from start: ${offsetFromStart} bytes`);
195
- console.log(` - Field length: ${targetLen} bytes`);
196
-
197
- const asm = [
198
- `# ๐Ÿ”„ Extract ${field} from LEFT side (bidirectional strategy)`,
199
- `${offsetFromStart} OP_SPLIT # Skip to field: [prefix, remainder]`,
200
- `OP_DROP # Drop prefix: [remainder]`,
201
- `${targetLen} OP_SPLIT # Extract field: [${field}, suffix]`,
202
- `OP_DROP # Clean up: [${field}]`,
203
- `# โœ… Result: ${field} is now on top of stack`
204
- ].join('\n');
205
-
206
- return asm;
207
- }
208
-
209
- function generateDynamicExtractionASM(field, parsed) {
210
- const leftZone = LEFT_FIXED_TOTAL + parsed.scriptLenSize;
211
-
212
- console.log(`๐Ÿ“ Strategy: Extract DYNAMIC field (uses CompactSize varint)`);
213
- console.log(` - Left fixed zone: ${LEFT_FIXED_TOTAL} bytes`);
214
- console.log(` - ScriptLen varint: ${parsed.scriptLenSize} bytes (${parsed.scriptLenRaw})`);
215
- console.log(` - Script length: ${parsed.scriptLen} bytes`);
216
- console.log(` - Skip zone total: ${leftZone} bytes`);
217
-
218
- const asm = [
219
- `# ๐ŸŽฏ Extract ${field} DYNAMICALLY with CompactSize varint support`,
220
- `${leftZone} OP_SPLIT # Skip left zone + scriptLen varint: [left_zone, remainder]`,
221
- `OP_DROP # Drop left: [remainder]`,
222
- `${parsed.scriptLen} OP_SPLIT # Extract scriptCode: [scriptCode, right_zone]`,
223
- `OP_DROP # Clean up: [scriptCode]`,
224
- `# โœ… Result: scriptCode extracted with ${parsed.scriptLenSize}-byte varint awareness`
225
- ].join('\n');
226
-
227
- return asm;
228
- }
229
-
230
- function generateScriptLenExtractionASM(parsed) {
231
- console.log(`๐Ÿ“ Strategy: Extract CompactSize scriptLen varint`);
232
- console.log(` - Left fixed zone: ${LEFT_FIXED_TOTAL} bytes`);
233
- console.log(` - Varint encoding: ${parsed.scriptLenSize} bytes`);
234
- console.log(` - Raw varint: ${parsed.scriptLenRaw}`);
235
- console.log(` - Decoded value: ${parsed.scriptLen}`);
236
-
237
- const asm = [
238
- `# ๐ŸŽฏ Extract scriptLen CompactSize varint (${parsed.scriptLenSize} bytes)`,
239
- `${LEFT_FIXED_TOTAL} OP_SPLIT # Skip left fixed fields: [left_zone, remainder]`,
240
- `OP_DROP # Drop left: [remainder]`,
241
- `${parsed.scriptLenSize} OP_SPLIT # Extract varint: [scriptLen_varint, suffix]`,
242
- `OP_DROP # Clean up: [scriptLen_varint]`,
243
- `# โœ… Result: CompactSize varint (decode off-chain to get ${parsed.scriptLen})`
244
- ].join('\n');
245
-
246
- return asm;
247
- }
248
-
249
- function simulateExtraction(buf, field) {
250
- console.log(`\n๐ŸŽฌ Simulating stack execution for "${field}"`);
251
- console.log('='.repeat(60));
252
-
253
- const parsed = parsePreimage(buf.toString('hex'));
254
-
255
- if (parsed[field] !== undefined) {
256
- const value = parsed[field];
257
- console.log(`๐Ÿ“ฆ Extracted value: ${value}`);
258
-
259
- // Add interpretations with CompactSize awareness
260
- if (field === 'nVersion') {
261
- const version = Buffer.from(value, 'hex').readUInt32LE(0);
262
- console.log(` ๐Ÿ“ Interpreted: Version ${version}`);
263
- } else if (field === 'value') {
264
- if (value.length === 16) { // 8 bytes = 16 hex chars
265
- const satoshis = Buffer.from(value, 'hex').readBigUInt64LE(0);
266
- console.log(` ๐Ÿ“ Interpreted: ${satoshis} satoshis`);
267
- }
268
- } else if (field === 'sighashType') {
269
- const sighashInt = Buffer.from(value, 'hex').readUInt32LE(0);
270
- const types = {
271
- 1: 'SIGHASH_ALL',
272
- 65: 'SIGHASH_ALL | FORKID',
273
- 2: 'SIGHASH_NONE',
274
- 66: 'SIGHASH_NONE | FORKID',
275
- 3: 'SIGHASH_SINGLE',
276
- 67: 'SIGHASH_SINGLE | FORKID',
277
- 129: 'SIGHASH_ALL | ANYONECANPAY',
278
- 193: 'SIGHASH_ALL | ANYONECANPAY | FORKID'
279
- };
280
- console.log(` ๐Ÿ“ Interpreted: ${types[sighashInt] || `Custom (${sighashInt})`}`);
281
- } else if (field === 'outpoint_vout') {
282
- const vout = Buffer.from(value, 'hex').readUInt32LE(0);
283
- console.log(` ๐Ÿ“ Interpreted: Output index ${vout}`);
284
- } else if (field === 'scriptLen') {
285
- console.log(` ๐Ÿ“ Interpreted: CompactSize varint (${parsed.scriptLenSize} bytes)`);
286
- console.log(` ๐Ÿ“ Raw varint: ${parsed.scriptLenRaw}`);
287
- console.log(` ๐Ÿ“ Decoded value: ${parsed.scriptLen} bytes`);
288
-
289
- if (parsed.scriptLenSize === 1) {
290
- console.log(` ๐Ÿ’ก Standard encoding: value < 253 (0xFD)`);
291
- } else if (parsed.scriptLenSize === 3) {
292
- console.log(` ๐Ÿ’ก Extended encoding: 0xFD + 2-byte little-endian`);
293
- } else if (parsed.scriptLenSize === 5) {
294
- console.log(` ๐Ÿ’ก Long encoding: 0xFE + 4-byte little-endian`);
295
- }
296
- } else if (field === 'scriptCode') {
297
- const scriptBuf = Buffer.from(value, 'hex');
298
- if (scriptBuf.length === 25 && scriptBuf[0] === 0x76 && scriptBuf[1] === 0xa9) {
299
- console.log(` ๐Ÿ“ Interpreted: Standard P2PKH script (25 bytes)`);
300
- } else if (scriptBuf.length > 70 && scriptBuf[0] >= 0x51 && scriptBuf[0] <= 0x60) {
301
- console.log(` ๐Ÿ“ Interpreted: Multisig script (${scriptBuf.length} bytes)`);
302
- } else if (scriptBuf.length > 0 && scriptBuf[0] === 0x6a) {
303
- console.log(` ๐Ÿ“ Interpreted: OP_RETURN data script (${scriptBuf.length} bytes)`);
304
- } else {
305
- console.log(` ๐Ÿ“ Interpreted: Custom script (${scriptBuf.length} bytes)`);
306
- }
307
- } else if (['hashPrevouts', 'hashSequence', 'hashOutputs'].includes(field)) {
308
- if (value === '00'.repeat(32)) {
309
- console.log(` โš ๏ธ Zero hash detected - check SIGHASH flags (ANYONECANPAY, NONE, SINGLE)`);
310
- } else {
311
- console.log(` ๐Ÿ“ Interpreted: 32-byte hash (${value.substring(0, 16)}...)`);
312
- }
313
- }
314
- } else {
315
- console.log(`โŒ Field "${field}" not found in parsed preimage`);
316
- }
317
- }
318
-
319
- // CLI Interface
320
- if (process.argv.length < 4) {
321
- console.log("๐Ÿง  Bidirectional Preimage Field Extractor v2.0");
322
- console.log("=============================================");
323
- console.log("โœจ Now with CompactSize varint support for multi-input transactions!");
324
- console.log("");
325
- console.log("Usage: node extract_preimage_bidirectional.js <preimage_hex> <field_name>");
326
- console.log("");
327
- console.log("๐Ÿ”„ LEFT Fields (fixed offsets from start):");
328
- LEFT_FIXED_FIELDS.forEach(f => {
329
- console.log(` - ${f.name.padEnd(16)} (${f.len} bytes)`);
330
- });
331
- console.log(" - scriptLen (1-3 bytes CompactSize varint)");
332
- console.log("");
333
- console.log("๐ŸŽฏ DYNAMIC Field (uses CompactSize scriptLen):");
334
- console.log(` - scriptCode (variable, decoded from scriptLen varint)`);
335
- console.log("");
336
- console.log("๐Ÿ”„ RIGHT Fields (fixed offsets from end):");
337
- RIGHT_FIXED_FIELDS.forEach(f => {
338
- console.log(` - ${f.name.padEnd(16)} (${f.len} bytes)`);
339
- });
340
- console.log("");
341
- console.log("๐Ÿ“– CompactSize Encoding:");
342
- console.log(" < 253 (0xFD) โ†’ 1 byte");
343
- console.log(" 253-65535 โ†’ 3 bytes (0xFD + 2-byte LE)");
344
- console.log(" 65536-4294967295 โ†’ 5 bytes (0xFE + 4-byte LE)");
345
- console.log("");
346
- console.log("Examples:");
347
- console.log(" node extract_preimage_bidirectional.js 01000000ab12cd... scriptCode");
348
- console.log(" node extract_preimage_bidirectional.js 01000000ab12cd... scriptLen");
349
- console.log(" node extract_preimage_bidirectional.js 01000000ab12cd... value");
350
- process.exit(1);
351
- }
352
-
353
- const hex = process.argv[2];
354
- const field = process.argv[3];
355
-
356
- // Validate input
357
- if (!/^[0-9a-fA-F]+$/.test(hex)) {
358
- console.error("โŒ Invalid hex string. Please provide a valid hexadecimal preimage.");
359
- process.exit(1);
360
- }
361
-
362
- if (hex.length < 200) {
363
- console.error("โŒ Preimage too short. Expected at least 100+ bytes for valid BIP-143 preimage.");
364
- process.exit(1);
365
- }
366
-
367
- try {
368
- const buf = Buffer.from(hex, "hex");
369
- const parsed = parsePreimage(hex);
370
-
371
- console.log(`\n๐Ÿ” Bidirectional Preimage Analysis`);
372
- console.log('='.repeat(60));
373
- console.log(`๐Ÿ“Š Total preimage: ${buf.length} bytes (${hex.length} hex chars)`);
374
- console.log(`๐Ÿ“‹ Structure: LEFT(${parsed._structure.leftFixed}) + scriptLen(${parsed._structure.scriptLenVarint}) + scriptCode(${parsed._structure.scriptCode}) + RIGHT(${parsed._structure.rightFixed}) = ${parsed._structure.totalCalculated} bytes`);
375
-
376
- // Validate structure with CompactSize awareness
377
- if (buf.length !== parsed._structure.totalCalculated) {
378
- console.log(`โš ๏ธ Size mismatch: expected ${parsed._structure.totalCalculated}, got ${buf.length}`);
379
- console.log(`๐Ÿ’ก Check: CompactSize varint encoding, script serialization, SIGHASH flags`);
380
- } else {
381
- console.log(`โœ… Structure validated: Perfect BIP-143 compliance`);
382
- }
383
-
384
- // Show CompactSize details
385
- if (parsed.scriptLenSize > 1) {
386
- console.log(`๐Ÿ” CompactSize Details: ${parsed.scriptLen} bytes encoded as ${parsed.scriptLenSize}-byte varint (${parsed.scriptLenRaw})`);
387
- }
388
-
389
- // Generate and display ASM
390
- const asm = generateBidirectionalASM(field, buf.length, parsed);
391
- console.log(`\n๐Ÿ“œ Generated ASM:`);
392
- console.log(asm);
393
-
394
- // Simulate extraction
395
- simulateExtraction(buf, field);
396
-
397
- } catch (error) {
398
- console.error("โŒ Error:", error.message);
399
- if (error.message.includes('Invalid hex')) {
400
- console.error("๐Ÿ’ก Tip: Make sure your preimage is valid hexadecimal");
401
- } else if (error.message.includes('Unknown field')) {
402
- console.error("๐Ÿ’ก Tip: Check available fields with --help");
403
- }
404
- process.exit(1);
405
- }
406
-
407
- // Add helpful footer
408
- console.log("\n" + "=".repeat(60));
409
- console.log("๐ŸŽฏ Enhanced Bidirectional Strategy Benefits:");
410
- console.log(" โœ… Optimal extraction direction for each field");
411
- console.log(" โœ… CompactSize varint scriptLen support (1-3 bytes)");
412
- console.log(" โœ… Handles multi-input transaction preimages");
413
- console.log(" โœ… SIGHASH flag awareness (zero hash detection)");
414
- console.log(" โœ… Self-contained (no external context needed)");
415
- console.log(" โœ… Generates minimal ASM operations");
416
- console.log("");
417
- console.log("๐Ÿ”— Integration with Covenant Tools:");
418
- console.log(" - Use generated ASM in covenant locking scripts");
419
- console.log(" - Verify preimage components with dynamic extraction");
420
- console.log(" - Build advanced covenant patterns with field isolation");
421
- console.log("๐Ÿ“– See DOCUMENTATION.md for complete covenant implementation");
@@ -1,208 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * generate_sample_preimage.js
4
- * Advanced BIP-143 preimage generator with multiple realistic scenarios
5
- *
6
- * Generates various types of preimages for testing bidirectional extraction:
7
- * - Standard P2PKH transactions
8
- * - Multi-signature scenarios
9
- * - Custom script patterns
10
- * - Different value ranges
11
- */
12
-
13
- function createSamplePreimage(type = 'standard') {
14
- const { Buffer } = require("buffer");
15
-
16
- // Base fields (same for all types)
17
- const baseFields = {
18
- nVersion: Buffer.from([0x01, 0x00, 0x00, 0x00]), // Version 1
19
- hashPrevouts: Buffer.alloc(32, 0xab), // Mock hash
20
- hashSequence: Buffer.alloc(32, 0xcd), // Mock hash
21
- outpoint_txid: Buffer.alloc(32, 0x12), // Mock TXID
22
- outpoint_vout: Buffer.from([0x00, 0x00, 0x00, 0x00]), // Output 0
23
- nSequence: Buffer.from([0xff, 0xff, 0xff, 0xff]), // Max sequence
24
- hashOutputs: Buffer.alloc(32, 0xef), // Mock hash
25
- nLocktime: Buffer.from([0x00, 0x00, 0x00, 0x00]), // No locktime
26
- sighashType: Buffer.from([0x41, 0x00, 0x00, 0x00]) // SIGHASH_ALL | FORKID
27
- };
28
-
29
- let scriptVariant;
30
-
31
- switch (type) {
32
- case 'standard':
33
- // Standard P2PKH (25 bytes)
34
- scriptVariant = {
35
- scriptLen: Buffer.from([0x19]), // 25 bytes
36
- scriptCode: Buffer.from([
37
- 0x76, 0xa9, 0x14, // OP_DUP OP_HASH160 OP_PUSHDATA(20)
38
- ...Buffer.alloc(20, 0x88), // 20-byte pubkey hash
39
- 0x88, 0xac // OP_EQUALVERIFY OP_CHECKSIG
40
- ]),
41
- value: Buffer.from([0x00, 0xe1, 0xf5, 0x05, 0x00, 0x00, 0x00, 0x00]) // 100000000 satoshis (1 BSV)
42
- };
43
- break;
44
-
45
- case 'multisig':
46
- // 2-of-3 multisig (71 bytes)
47
- scriptVariant = {
48
- scriptLen: Buffer.from([0x47]), // 71 bytes
49
- scriptCode: Buffer.concat([
50
- Buffer.from([0x52]), // OP_2 (required signatures)
51
- Buffer.from([0x21]), Buffer.alloc(33, 0xaa), // First pubkey (33 bytes)
52
- Buffer.from([0x21]), Buffer.alloc(33, 0xbb), // Second pubkey (33 bytes)
53
- Buffer.from([0x21]), Buffer.alloc(33, 0xcc), // Third pubkey (33 bytes)
54
- Buffer.from([0x53]), // OP_3 (total pubkeys)
55
- Buffer.from([0xae]) // OP_CHECKMULTISIG
56
- ]),
57
- value: Buffer.from([0x00, 0x40, 0x42, 0x0f, 0x00, 0x00, 0x00, 0x00]) // 2.56 BSV
58
- };
59
- break;
60
-
61
- case 'custom':
62
- // Custom script with OP_RETURN data (34 bytes)
63
- scriptVariant = {
64
- scriptLen: Buffer.from([0x22]), // 34 bytes
65
- scriptCode: Buffer.concat([
66
- Buffer.from([0x6a]), // OP_RETURN
67
- Buffer.from([0x20]), // Push 32 bytes
68
- Buffer.from('Hello Bitcoin SV - Custom Script Test', 'utf8').slice(0, 32)
69
- ]),
70
- value: Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) // 0 satoshis (OP_RETURN output)
71
- };
72
- break;
73
-
74
- case 'large':
75
- // Large script (300 bytes) to test CompactSize 3-byte varint (0xFD)
76
- const scriptSize = 300;
77
- scriptVariant = {
78
- scriptLen: Buffer.from([0xfd, scriptSize & 0xff, (scriptSize >> 8) & 0xff]), // 3-byte varint: 0xFD + 2-byte LE
79
- scriptCode: Buffer.concat([
80
- Buffer.from([0x76, 0xa9, 0x14]), // OP_DUP OP_HASH160 OP_PUSHDATA(20)
81
- Buffer.alloc(20, 0x99), // 20-byte pubkey hash
82
- Buffer.from([0x88, 0xac]), // OP_EQUALVERIFY OP_CHECKSIG
83
- Buffer.alloc(275, 0x6a) // Padding with OP_RETURN opcodes to reach 300 bytes
84
- ]),
85
- value: Buffer.from([0x00, 0x10, 0xa5, 0xd4, 0xe8, 0x00, 0x00, 0x00]) // 10 BSV
86
- };
87
- break;
88
-
89
- case 'huge':
90
- // Huge script (70000 bytes) to test CompactSize 5-byte varint (0xFE)
91
- const hugeSize = 70000;
92
- scriptVariant = {
93
- scriptLen: Buffer.from([
94
- 0xfe,
95
- hugeSize & 0xff,
96
- (hugeSize >> 8) & 0xff,
97
- (hugeSize >> 16) & 0xff,
98
- (hugeSize >> 24) & 0xff
99
- ]), // 5-byte varint: 0xFE + 4-byte LE
100
- scriptCode: Buffer.concat([
101
- Buffer.from([0x6a]), // OP_RETURN
102
- Buffer.from([0x4c, 0xff, 0xff]), // OP_PUSHDATA2 + 65535 bytes
103
- Buffer.alloc(65535, 0xaa), // Large data block
104
- Buffer.alloc(hugeSize - 65539, 0xbb) // Remaining padding
105
- ]),
106
- value: Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) // 0 satoshis (data output)
107
- };
108
- break;
109
-
110
- default:
111
- throw new Error(`Unknown preimage type: ${type}`);
112
- }
113
-
114
- const fields = { ...baseFields, ...scriptVariant };
115
-
116
- // Concatenate all fields
117
- const preimage = Buffer.concat([
118
- fields.nVersion,
119
- fields.hashPrevouts,
120
- fields.hashSequence,
121
- fields.outpoint_txid,
122
- fields.outpoint_vout,
123
- fields.scriptLen,
124
- fields.scriptCode,
125
- fields.value,
126
- fields.nSequence,
127
- fields.hashOutputs,
128
- fields.nLocktime,
129
- fields.sighashType
130
- ]);
131
-
132
- return preimage.toString('hex');
133
- }
134
-
135
- // CLI Interface
136
- if (require.main === module) {
137
- const type = process.argv[2] || 'standard';
138
-
139
- if (type === '--help' || type === '-h') {
140
- console.log("๐ŸŽฏ Advanced BIP-143 Preimage Generator");
141
- console.log("=====================================");
142
- console.log("Usage: node generate_sample_preimage.js [type]");
143
- console.log("");
144
- console.log("Available types:");
145
- console.log(" standard - Standard P2PKH script (25 bytes, 1-byte varint) - DEFAULT");
146
- console.log(" multisig - 2-of-3 multisig script (71 bytes, 1-byte varint)");
147
- console.log(" custom - Custom OP_RETURN script (34 bytes, 1-byte varint)");
148
- console.log(" large - Large script (300 bytes, 3-byte varint 0xFD)");
149
- console.log(" huge - Huge script (70000 bytes, 5-byte varint 0xFE)");
150
- console.log("");
151
- console.log("Examples:");
152
- console.log(" node generate_sample_preimage.js");
153
- console.log(" node generate_sample_preimage.js multisig");
154
- console.log(" node generate_sample_preimage.js large # Test 3-byte varint");
155
- console.log(" node generate_sample_preimage.js huge # Test 5-byte varint");
156
- process.exit(0);
157
- }
158
-
159
- try {
160
- console.log("๐ŸŽฏ Advanced BIP-143 Preimage Generator");
161
- console.log("=====================================");
162
- console.log(`๐Ÿ“‹ Type: ${type}`);
163
-
164
- const sampleHex = createSamplePreimage(type);
165
- const scriptLen = parseInt(sampleHex.substring(208, 210), 16); // Extract scriptLen byte
166
-
167
- console.log(`๐Ÿ“Š Generated: ${sampleHex.length / 2} bytes total`);
168
- console.log(`๐Ÿ“ Structure: LEFT(105) + scriptCode(${scriptLen}) + RIGHT(52) bytes`);
169
- console.log(`๐Ÿ“ฆ Preimage: ${sampleHex}`);
170
-
171
- console.log("\n๐Ÿงช Test Commands:");
172
- console.log(` node extract_preimage_bidirectional.js ${sampleHex} scriptCode`);
173
- console.log(` node extract_preimage_bidirectional.js ${sampleHex} value`);
174
- console.log(` npm run preimage:extract ${sampleHex} nVersion`);
175
-
176
- console.log("\n๐Ÿ” Field Analysis:");
177
- console.log(` LEFT extraction: nVersion, hashPrevouts, hashSequence, outpoint_*, scriptLen`);
178
- console.log(` DYNAMIC extraction: scriptCode (${scriptLen} bytes)`);
179
- console.log(` RIGHT extraction: value, nSequence, hashOutputs, nLocktime, sighashType`);
180
-
181
- } catch (error) {
182
- console.error("โŒ Error:", error.message);
183
- console.log("๐Ÿ’ก Use --help to see available types");
184
- process.exit(1);
185
- }
186
- }
187
-
188
- // Export functions for programmatic use
189
- function generateAllTypes() {
190
- return {
191
- standard: createSamplePreimage('standard'),
192
- multisig: createSamplePreimage('multisig'),
193
- custom: createSamplePreimage('custom'),
194
- large: createSamplePreimage('large')
195
- };
196
- }
197
-
198
- module.exports = {
199
- createSamplePreimage,
200
- generateAllTypes,
201
-
202
- // Convenience functions
203
- getStandardPreimage: () => createSamplePreimage('standard'),
204
- getMultisigPreimage: () => createSamplePreimage('multisig'),
205
- getCustomPreimage: () => createSamplePreimage('custom'),
206
- getLargePreimage: () => createSamplePreimage('large'),
207
- getHugePreimage: () => createSamplePreimage('huge')
208
- };