@smartledger/bsv 3.4.3 โ†’ 3.4.5

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 (89) hide show
  1. package/CHANGELOG.md +367 -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/script/script.js +19 -0
  21. package/lib/smart_contract/covenant.js +10 -1
  22. package/lib/smartutxo.js +20 -12
  23. package/lib/transaction/input/publickeyhash.js +6 -1
  24. package/lib/transaction/transaction.js +12 -1
  25. package/ltp-entry.js +1 -2
  26. package/package.json +3 -3
  27. package/utilities/blockchain-state.js +32 -23
  28. package/demos/README.md +0 -188
  29. package/demos/architecture_demo.js +0 -247
  30. package/demos/browser-test.html +0 -1208
  31. package/demos/bsv_wallet_demo.js +0 -242
  32. package/demos/complete_ltp_demo.js +0 -511
  33. package/demos/debug_tools_demo.js +0 -87
  34. package/demos/demo_features.js +0 -123
  35. package/demos/easy_interface_demo.js +0 -109
  36. package/demos/ecies_demo.js +0 -182
  37. package/demos/gdaf_demo.js +0 -237
  38. package/demos/ltp_demo.js +0 -361
  39. package/demos/ltp_primitives_demo.js +0 -403
  40. package/demos/message_demo.js +0 -209
  41. package/demos/preimage_separation_demo.js +0 -383
  42. package/demos/script_helper_demo.js +0 -289
  43. package/demos/security_demo.js +0 -287
  44. package/demos/shamir_demo.js +0 -121
  45. package/demos/simple_demo.js +0 -204
  46. package/demos/simple_p2pkh_demo.js +0 -169
  47. package/demos/simple_utxo_preimage_demo.js +0 -196
  48. package/demos/smart_contract_demo.html +0 -1347
  49. package/demos/smart_contract_demo.js +0 -910
  50. package/demos/utxo_generator_demo.js +0 -244
  51. package/demos/validation_pipeline_demo.js +0 -155
  52. package/demos/web3keys.html +0 -740
  53. package/examples/README.md +0 -200
  54. package/examples/basic/transaction-creation.js +0 -534
  55. package/examples/basic/transaction_signature_api_gap.js +0 -178
  56. package/examples/complete_workflow_demo.js +0 -783
  57. package/examples/covenants/advanced_covenant_demo.js +0 -219
  58. package/examples/covenants/covenant_interface_demo.js +0 -270
  59. package/examples/covenants/covenant_manual_signature_resolved.js +0 -212
  60. package/examples/covenants/covenant_signature_template.js +0 -117
  61. package/examples/covenants2/covenant_bidirectional_example.js +0 -262
  62. package/examples/covenants2/covenant_utils_demo.js +0 -120
  63. package/examples/covenants2/preimage_covenant_utils.js +0 -287
  64. package/examples/covenants2/production_integration.js +0 -256
  65. package/examples/data/covenant_utxos.json +0 -28
  66. package/examples/data/utxos.json +0 -26
  67. package/examples/definitive_working_demo.js +0 -261
  68. package/examples/final_working_contracts.js +0 -338
  69. package/examples/legacy/README.md +0 -11
  70. package/examples/legacy/smart_contract_test_integration.js +0 -269
  71. package/examples/legacy/test_builtin_verify.js +0 -117
  72. package/examples/legacy/test_debug_integration.js +0 -71
  73. package/examples/legacy/test_ecdsa_little.js +0 -70
  74. package/examples/legacy/test_shamir.js +0 -221
  75. package/examples/legacy/test_smartverify_der.js +0 -110
  76. package/examples/preimage/README.md +0 -178
  77. package/examples/preimage/extract_preimage_bidirectional.js +0 -421
  78. package/examples/preimage/generate_sample_preimage.js +0 -208
  79. package/examples/preimage/generate_sighash_examples.js +0 -152
  80. package/examples/preimage/parse_preimage.js +0 -117
  81. package/examples/preimage/test_preimage_extractor.js +0 -53
  82. package/examples/preimage/test_varint_extraction.js +0 -95
  83. package/examples/scripts/custom_script_helper_example.js +0 -273
  84. package/examples/scripts/script_interpreter.js +0 -193
  85. package/examples/smart_contract/complete_workflow_demo.js +0 -343
  86. package/examples/smart_contract/covenant_builder_demo.js +0 -176
  87. package/examples/smart_contract/script_testing_integration.js +0 -198
  88. package/examples/smart_contract_templates.js +0 -718
  89. 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
- };