smartledger-bsv 3.4.0 ā 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.
- package/CHANGELOG.md +400 -0
- package/README.md +112 -84
- package/SECURITY.md +88 -0
- package/bin/cli.js +13 -8
- package/bsv-anchor.min.js +12 -0
- package/bsv-covenant.min.js +8 -8
- package/bsv-didweb.min.js +12 -0
- package/bsv-gdaf.min.js +9 -9
- package/bsv-ltp.min.js +9 -9
- package/bsv-mnemonic.min.js +2 -2
- package/bsv-shamir.min.js +3 -3
- package/bsv-smartcontract.min.js +5 -5
- package/bsv-statuslist.min.js +18 -0
- package/bsv-vcjwt.min.js +12 -0
- package/bsv.bundle.js +9 -9
- package/bsv.d.ts +486 -9
- package/bsv.min.js +5 -5
- package/build/webpack.anchor.config.js +9 -13
- package/build/webpack.didweb.config.js +10 -14
- package/build/webpack.statuslist.config.js +9 -14
- package/build/webpack.vcjwt.config.js +9 -13
- package/docs/COVENANT_DEVELOPMENT_RESOLVED.md +2 -2
- package/docs/MODULE_REFERENCE_COMPLETE.md +61 -58
- package/docs/advanced/LEGAL_TOKEN_PROTOCOL.md +3 -3
- package/docs/advanced/UTXO_MANAGER_GUIDE.md +1 -1
- package/docs/getting-started/INSTALLATION.md +30 -30
- package/docs/getting-started/QUICK_START.md +18 -18
- package/docs/migration/FROM_BSV_1_5_6.md +16 -10
- package/gdaf-entry.js +1 -2
- package/index.js +44 -13
- package/lib/browser-utxo-manager-es5.js +11 -4
- package/lib/browser-utxo-manager.js +15 -8
- package/lib/ltp/claim.js +1 -0
- package/lib/ltp/obligation.js +1 -0
- package/lib/ltp/registry.js +2 -0
- package/lib/ltp/right.js +1 -0
- package/lib/smart_contract/covenant.js +10 -1
- package/lib/smartutxo.js +20 -12
- package/lib/transaction/transaction.js +8 -1
- package/lib/util/_.js +7 -1
- package/ltp-entry.js +1 -2
- package/package.json +11 -13
- package/utilities/blockchain-state.js +32 -23
- package/demos/README.md +0 -188
- package/demos/architecture_demo.js +0 -247
- package/demos/browser-test.html +0 -1208
- package/demos/bsv_wallet_demo.js +0 -242
- package/demos/complete_ltp_demo.js +0 -511
- package/demos/debug_tools_demo.js +0 -87
- package/demos/demo_features.js +0 -123
- package/demos/easy_interface_demo.js +0 -109
- package/demos/ecies_demo.js +0 -182
- package/demos/gdaf_core_test.js +0 -131
- package/demos/gdaf_demo.js +0 -237
- package/demos/ltp_demo.js +0 -361
- package/demos/ltp_primitives_demo.js +0 -403
- package/demos/message_demo.js +0 -209
- package/demos/preimage_separation_demo.js +0 -383
- package/demos/script_helper_demo.js +0 -289
- package/demos/security_demo.js +0 -287
- package/demos/shamir_demo.js +0 -121
- package/demos/simple_demo.js +0 -204
- package/demos/simple_p2pkh_demo.js +0 -169
- package/demos/simple_utxo_preimage_demo.js +0 -196
- package/demos/smart_contract_demo.html +0 -1347
- package/demos/smart_contract_demo.js +0 -910
- package/demos/utxo_generator_demo.js +0 -244
- package/demos/validation_pipeline_demo.js +0 -155
- package/demos/web3keys.html +0 -740
- package/examples/README.md +0 -200
- package/examples/basic/transaction-creation.js +0 -534
- package/examples/basic/transaction_signature_api_gap.js +0 -178
- package/examples/complete_workflow_demo.js +0 -783
- package/examples/covenants/advanced_covenant_demo.js +0 -219
- package/examples/covenants/covenant_interface_demo.js +0 -270
- package/examples/covenants/covenant_manual_signature_resolved.js +0 -212
- package/examples/covenants/covenant_signature_template.js +0 -117
- package/examples/covenants2/covenant_bidirectional_example.js +0 -262
- package/examples/covenants2/covenant_utils_demo.js +0 -120
- package/examples/covenants2/preimage_covenant_utils.js +0 -287
- package/examples/covenants2/production_integration.js +0 -256
- package/examples/data/covenant_utxos.json +0 -28
- package/examples/data/utxos.json +0 -26
- package/examples/definitive_working_demo.js +0 -261
- package/examples/final_working_contracts.js +0 -338
- package/examples/preimage/README.md +0 -178
- package/examples/preimage/extract_preimage_bidirectional.js +0 -421
- package/examples/preimage/generate_sample_preimage.js +0 -208
- package/examples/preimage/generate_sighash_examples.js +0 -152
- package/examples/preimage/parse_preimage.js +0 -117
- package/examples/preimage/test_preimage_extractor.js +0 -53
- package/examples/preimage/test_varint_extraction.js +0 -95
- package/examples/scripts/custom_script_helper_example.js +0 -273
- package/examples/scripts/custom_script_signature_test.js +0 -344
- package/examples/scripts/script_interpreter.js +0 -193
- package/examples/smart_contract/complete_workflow_demo.js +0 -343
- package/examples/smart_contract/covenant_builder_demo.js +0 -176
- package/examples/smart_contract/script_testing_integration.js +0 -198
- package/examples/smart_contract_templates.js +0 -718
- package/examples/working_smart_contracts.js +0 -348
- package/lib/smart_contract/test_integration.js +0 -269
- package/tests/browser-compatibility/README.md +0 -35
- package/tests/browser-compatibility/test-cdn-vs-local.html +0 -186
- package/tests/browser-compatibility/test-pbkdf2.html +0 -51
- package/tests/bundle-completeness-test.html +0 -131
- package/tests/bundle-demo.html +0 -476
- package/tests/smartcontract-test.html +0 -239
- package/tests/standalone-modules-test.html +0 -260
- package/tests/test.html +0 -612
- package/tests/test_builtin_verify.js +0 -117
- package/tests/test_debug_integration.js +0 -71
- package/tests/test_ecdsa_little.js +0 -70
- package/tests/test_shamir.js +0 -221
- package/tests/test_smartverify_der.js +0 -110
- package/tests/test_standalone_shamir.html +0 -83
- package/tests/unpkg-demo.html +0 -194
- package/utilities/blockchain-state.json +0 -118565
|
@@ -1,383 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* UTXO Generator and Preimage Separation Demonstration
|
|
5
|
-
*
|
|
6
|
-
* This example shows how to:
|
|
7
|
-
* 1. Generate authentic UTXOs using the UTXOGenerator
|
|
8
|
-
* 2. Create transactions and extract BIP-143 preimages
|
|
9
|
-
* 3. Separate preimage into individual fields with detailed analysis
|
|
10
|
-
* 4. Display each component with hex values and interpretations
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
// Workaround for Node.js environment with minified BSV
|
|
14
|
-
global.window = global.window || {};
|
|
15
|
-
global.window.crypto = global.window.crypto || require('crypto').webcrypto || require('crypto');
|
|
16
|
-
|
|
17
|
-
const bsv = require('../bsv.min.js');
|
|
18
|
-
const SmartContract = bsv.SmartContract;
|
|
19
|
-
|
|
20
|
-
console.log('š§ UTXO Generator and Preimage Separation Demo');
|
|
21
|
-
console.log('=' .repeat(60));
|
|
22
|
-
|
|
23
|
-
async function demonstrateUTXOAndPreimage() {
|
|
24
|
-
try {
|
|
25
|
-
// Step 1: Generate authentic UTXOs
|
|
26
|
-
console.log('\nš¦ Step 1: Generating Authentic UTXOs');
|
|
27
|
-
console.log('-'.repeat(40));
|
|
28
|
-
|
|
29
|
-
// Create simple mock UTXOs for preimage demonstration
|
|
30
|
-
const demoPrivateKey = new bsv.PrivateKey();
|
|
31
|
-
const demoAddress = demoPrivateKey.toAddress();
|
|
32
|
-
|
|
33
|
-
const utxos = [
|
|
34
|
-
{
|
|
35
|
-
txid: '1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
|
|
36
|
-
vout: 0,
|
|
37
|
-
scriptPubKey: bsv.Script.buildPublicKeyHashOut(demoAddress).toHex(),
|
|
38
|
-
satoshis: 150000
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
txid: 'abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890',
|
|
42
|
-
vout: 1,
|
|
43
|
-
scriptPubKey: bsv.Script.buildPublicKeyHashOut(demoAddress).toHex(),
|
|
44
|
-
satoshis: 150000
|
|
45
|
-
}
|
|
46
|
-
];
|
|
47
|
-
|
|
48
|
-
console.log('ā
Mock UTXOs Created for Demo:');
|
|
49
|
-
console.log(` Count: ${utxos.length}`);
|
|
50
|
-
console.log(` Address: ${demoAddress.toString()}`);
|
|
51
|
-
console.log(` Private Key (WIF): ${demoPrivateKey.toWIF()}`);
|
|
52
|
-
|
|
53
|
-
utxos.forEach((utxo, index) => {
|
|
54
|
-
console.log(`\n UTXO ${index + 1}:`);
|
|
55
|
-
console.log(` TXID: ${utxo.txid}`);
|
|
56
|
-
console.log(` VOUT: ${utxo.vout}`);
|
|
57
|
-
console.log(` Satoshis: ${utxo.satoshis.toLocaleString()}`);
|
|
58
|
-
console.log(` Script: ${utxo.script}`);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
// Step 2: Create a transaction using the UTXOs
|
|
62
|
-
console.log('\n\nšØ Step 2: Creating Transaction from UTXOs');
|
|
63
|
-
console.log('-'.repeat(40));
|
|
64
|
-
|
|
65
|
-
const privateKey = demoPrivateKey;
|
|
66
|
-
const address = demoAddress;
|
|
67
|
-
|
|
68
|
-
// Create transaction spending first UTXO
|
|
69
|
-
const tx = new bsv.Transaction()
|
|
70
|
-
.from({
|
|
71
|
-
txId: utxos[0].txid,
|
|
72
|
-
outputIndex: utxos[0].vout,
|
|
73
|
-
scriptPubKey: utxos[0].scriptPubKey,
|
|
74
|
-
satoshis: utxos[0].satoshis
|
|
75
|
-
})
|
|
76
|
-
.to(address, 140000) // Send to same address with fee
|
|
77
|
-
.change(address) // Change back to same address
|
|
78
|
-
.sign(privateKey);
|
|
79
|
-
|
|
80
|
-
console.log('ā
Transaction Created:');
|
|
81
|
-
console.log(` Transaction ID: ${tx.id}`);
|
|
82
|
-
console.log(` Inputs: ${tx.inputs.length}`);
|
|
83
|
-
console.log(` Outputs: ${tx.outputs.length}`);
|
|
84
|
-
console.log(` Fee: ${tx.getFee()} satoshis`);
|
|
85
|
-
|
|
86
|
-
// Display transaction details
|
|
87
|
-
tx.inputs.forEach((input, index) => {
|
|
88
|
-
console.log(`\n Input ${index + 1}:`);
|
|
89
|
-
console.log(` Previous TXID: ${input.prevTxId.toString('hex')}`);
|
|
90
|
-
console.log(` Output Index: ${input.outputIndex}`);
|
|
91
|
-
console.log(` Script: ${input.script ? input.script.toString() : 'None'}`);
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
tx.outputs.forEach((output, index) => {
|
|
95
|
-
console.log(`\n Output ${index + 1}:`);
|
|
96
|
-
console.log(` Satoshis: ${output.satoshis.toLocaleString()}`);
|
|
97
|
-
console.log(` Script: ${output.script.toString()}`);
|
|
98
|
-
console.log(` Address: ${output.script.toAddress().toString()}`);
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
// Step 3: Generate BIP-143 Preimage
|
|
102
|
-
console.log('\n\nš Step 3: Generating BIP-143 Preimage');
|
|
103
|
-
console.log('-'.repeat(40));
|
|
104
|
-
|
|
105
|
-
const inputIndex = 0;
|
|
106
|
-
const sighashType = bsv.crypto.Signature.SIGHASH_ALL | bsv.crypto.Signature.SIGHASH_FORKID;
|
|
107
|
-
const subscript = bsv.Script.buildPublicKeyHashOut(address);
|
|
108
|
-
const satoshis = new bsv.crypto.BN(utxos[0].satoshis);
|
|
109
|
-
|
|
110
|
-
const preimageBuffer = bsv.Transaction.sighash.sighashPreimage(
|
|
111
|
-
tx,
|
|
112
|
-
sighashType,
|
|
113
|
-
inputIndex,
|
|
114
|
-
subscript,
|
|
115
|
-
satoshis
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
console.log('ā
Preimage Generated:');
|
|
119
|
-
console.log(` Length: ${preimageBuffer.length} bytes`);
|
|
120
|
-
console.log(` Hex: ${preimageBuffer.toString('hex')}`);
|
|
121
|
-
console.log(` SIGHASH Type: 0x${sighashType.toString(16)}`);
|
|
122
|
-
|
|
123
|
-
// Step 4: Separate Preimage into Individual Fields
|
|
124
|
-
console.log('\n\nš¬ Step 4: Preimage Field Separation Analysis');
|
|
125
|
-
console.log('='.repeat(60));
|
|
126
|
-
|
|
127
|
-
// Create preimage analyzer
|
|
128
|
-
const preimage = new SmartContract.Preimage(preimageBuffer.toString('hex'));
|
|
129
|
-
|
|
130
|
-
// Extract all fields using different strategies
|
|
131
|
-
console.log('\nš Field Extraction Strategy Comparison:');
|
|
132
|
-
console.log('-'.repeat(50));
|
|
133
|
-
|
|
134
|
-
try {
|
|
135
|
-
const leftExtraction = preimage.extract('LEFT');
|
|
136
|
-
console.log('ā
LEFT extraction successful:', Object.keys(leftExtraction).length, 'fields');
|
|
137
|
-
} catch (error) {
|
|
138
|
-
console.log('ā LEFT extraction failed:', error.message);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
try {
|
|
142
|
-
const rightExtraction = preimage.extract('RIGHT');
|
|
143
|
-
console.log('ā
RIGHT extraction successful:', Object.keys(rightExtraction).length, 'fields');
|
|
144
|
-
} catch (error) {
|
|
145
|
-
console.log('ā RIGHT extraction failed:', error.message);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
try {
|
|
149
|
-
const dynamicExtraction = preimage.extract('DYNAMIC');
|
|
150
|
-
console.log('ā
DYNAMIC extraction successful:', Object.keys(dynamicExtraction).length, 'fields');
|
|
151
|
-
} catch (error) {
|
|
152
|
-
console.log('ā DYNAMIC extraction failed:', error.message);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Manual field-by-field extraction with detailed analysis
|
|
156
|
-
console.log('\n\nš Detailed Field-by-Field Analysis:');
|
|
157
|
-
console.log('='.repeat(60));
|
|
158
|
-
|
|
159
|
-
const fields = [
|
|
160
|
-
'version',
|
|
161
|
-
'hashPrevouts',
|
|
162
|
-
'hashSequence',
|
|
163
|
-
'outpoint',
|
|
164
|
-
'scriptCode',
|
|
165
|
-
'amount',
|
|
166
|
-
'sequence',
|
|
167
|
-
'hashOutputs',
|
|
168
|
-
'locktime',
|
|
169
|
-
'sighash'
|
|
170
|
-
];
|
|
171
|
-
|
|
172
|
-
let offset = 0;
|
|
173
|
-
const fieldDetails = {};
|
|
174
|
-
|
|
175
|
-
fields.forEach((fieldName, index) => {
|
|
176
|
-
console.log(`\n${index + 1}. ${fieldName.toUpperCase()}:`);
|
|
177
|
-
console.log('-'.repeat(20));
|
|
178
|
-
|
|
179
|
-
try {
|
|
180
|
-
const fieldBuffer = preimage.getField(fieldName);
|
|
181
|
-
fieldDetails[fieldName] = {
|
|
182
|
-
buffer: fieldBuffer,
|
|
183
|
-
hex: fieldBuffer.toString('hex'),
|
|
184
|
-
length: fieldBuffer.length,
|
|
185
|
-
offset: offset
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
console.log(` Hex Value: ${fieldBuffer.toString('hex')}`);
|
|
189
|
-
console.log(` Length: ${fieldBuffer.length} bytes`);
|
|
190
|
-
console.log(` Offset: ${offset}-${offset + fieldBuffer.length - 1}`);
|
|
191
|
-
|
|
192
|
-
// Interpret field values where possible
|
|
193
|
-
switch (fieldName) {
|
|
194
|
-
case 'version':
|
|
195
|
-
const version = fieldBuffer.readUInt32LE(0);
|
|
196
|
-
console.log(` Interpreted: Version ${version}`);
|
|
197
|
-
break;
|
|
198
|
-
|
|
199
|
-
case 'amount':
|
|
200
|
-
const amount = fieldBuffer.readBigUInt64LE(0);
|
|
201
|
-
console.log(` Interpreted: ${amount.toString()} satoshis (${(Number(amount) / 100000000).toFixed(8)} BSV)`);
|
|
202
|
-
break;
|
|
203
|
-
|
|
204
|
-
case 'sequence':
|
|
205
|
-
const sequence = fieldBuffer.readUInt32LE(0);
|
|
206
|
-
console.log(` Interpreted: Sequence ${sequence} (0x${sequence.toString(16)})`);
|
|
207
|
-
break;
|
|
208
|
-
|
|
209
|
-
case 'locktime':
|
|
210
|
-
const locktime = fieldBuffer.readUInt32LE(0);
|
|
211
|
-
if (locktime < 500000000) {
|
|
212
|
-
console.log(` Interpreted: Block height ${locktime}`);
|
|
213
|
-
} else {
|
|
214
|
-
console.log(` Interpreted: Unix timestamp ${locktime} (${new Date(locktime * 1000).toISOString()})`);
|
|
215
|
-
}
|
|
216
|
-
break;
|
|
217
|
-
|
|
218
|
-
case 'sighash':
|
|
219
|
-
const sighashValue = fieldBuffer.readUInt32LE(0);
|
|
220
|
-
console.log(` Interpreted: SIGHASH 0x${sighashValue.toString(16)}`);
|
|
221
|
-
|
|
222
|
-
// Decode SIGHASH flags
|
|
223
|
-
const flags = [];
|
|
224
|
-
if (sighashValue & 0x01) flags.push('SIGHASH_ALL');
|
|
225
|
-
if (sighashValue & 0x02) flags.push('SIGHASH_NONE');
|
|
226
|
-
if (sighashValue & 0x03) flags.push('SIGHASH_SINGLE');
|
|
227
|
-
if (sighashValue & 0x80) flags.push('SIGHASH_ANYONECANPAY');
|
|
228
|
-
if (sighashValue & 0x40) flags.push('SIGHASH_FORKID');
|
|
229
|
-
|
|
230
|
-
console.log(` Flags: ${flags.join(' | ')}`);
|
|
231
|
-
break;
|
|
232
|
-
|
|
233
|
-
case 'outpoint':
|
|
234
|
-
const txid = fieldBuffer.slice(0, 32).reverse().toString('hex');
|
|
235
|
-
const vout = fieldBuffer.slice(32, 36).readUInt32LE(0);
|
|
236
|
-
console.log(` Interpreted: ${txid}:${vout}`);
|
|
237
|
-
break;
|
|
238
|
-
|
|
239
|
-
case 'scriptCode':
|
|
240
|
-
try {
|
|
241
|
-
const script = new bsv.Script(fieldBuffer);
|
|
242
|
-
console.log(` Interpreted: ${script.toString()}`);
|
|
243
|
-
} catch (error) {
|
|
244
|
-
console.log(` Interpreted: Raw script data (${fieldBuffer.length} bytes)`);
|
|
245
|
-
}
|
|
246
|
-
break;
|
|
247
|
-
|
|
248
|
-
default:
|
|
249
|
-
if (fieldBuffer.length === 32) {
|
|
250
|
-
console.log(` Interpreted: 32-byte hash (likely SHA256)`);
|
|
251
|
-
} else {
|
|
252
|
-
console.log(` Interpreted: Raw binary data`);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
offset += fieldBuffer.length;
|
|
257
|
-
|
|
258
|
-
} catch (error) {
|
|
259
|
-
console.log(` ā Error extracting field: ${error.message}`);
|
|
260
|
-
fieldDetails[fieldName] = { error: error.message };
|
|
261
|
-
}
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
// Step 5: Preimage Validation and Analysis
|
|
265
|
-
console.log('\n\nš Step 5: Preimage Validation and Analysis');
|
|
266
|
-
console.log('='.repeat(60));
|
|
267
|
-
|
|
268
|
-
// Get SIGHASH analysis
|
|
269
|
-
try {
|
|
270
|
-
const sighashInfo = preimage.getSighashInfo();
|
|
271
|
-
console.log('\nš SIGHASH Analysis:');
|
|
272
|
-
console.log(` Has zero hashes: ${sighashInfo.hasZeroHashes ? 'ā ļø YES' : 'ā
NO'}`);
|
|
273
|
-
console.log(` SIGHASH type detected: ${sighashInfo.type || 'Unknown'}`);
|
|
274
|
-
console.log(` Is standard: ${sighashInfo.isStandard ? 'ā
YES' : 'ā NO'}`);
|
|
275
|
-
|
|
276
|
-
if (sighashInfo.warnings && sighashInfo.warnings.length > 0) {
|
|
277
|
-
console.log('\nā ļø Warnings:');
|
|
278
|
-
sighashInfo.warnings.forEach(warning => {
|
|
279
|
-
console.log(` - ${warning}`);
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
} catch (error) {
|
|
283
|
-
console.log('ā SIGHASH analysis failed:', error.message);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
// Verify preimage reconstruction
|
|
287
|
-
console.log('\nš§ Preimage Reconstruction Verification:');
|
|
288
|
-
console.log('-'.repeat(40));
|
|
289
|
-
|
|
290
|
-
let reconstructed = Buffer.alloc(0);
|
|
291
|
-
let reconstructionErrors = 0;
|
|
292
|
-
|
|
293
|
-
fields.forEach(fieldName => {
|
|
294
|
-
if (fieldDetails[fieldName] && fieldDetails[fieldName].buffer) {
|
|
295
|
-
reconstructed = Buffer.concat([reconstructed, fieldDetails[fieldName].buffer]);
|
|
296
|
-
} else {
|
|
297
|
-
reconstructionErrors++;
|
|
298
|
-
console.log(` ā Missing field: ${fieldName}`);
|
|
299
|
-
}
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
const originalHex = preimageBuffer.toString('hex');
|
|
303
|
-
const reconstructedHex = reconstructed.toString('hex');
|
|
304
|
-
const matches = originalHex === reconstructedHex;
|
|
305
|
-
|
|
306
|
-
console.log(` Original length: ${preimageBuffer.length} bytes`);
|
|
307
|
-
console.log(` Reconstructed length: ${reconstructed.length} bytes`);
|
|
308
|
-
console.log(` Reconstruction errors: ${reconstructionErrors}`);
|
|
309
|
-
console.log(` Fields match: ${matches ? 'ā
YES' : 'ā NO'}`);
|
|
310
|
-
|
|
311
|
-
if (!matches && reconstructionErrors === 0) {
|
|
312
|
-
console.log('\nš Hex Comparison (first 200 chars):');
|
|
313
|
-
console.log(` Original: ${originalHex.substring(0, 200)}${originalHex.length > 200 ? '...' : ''}`);
|
|
314
|
-
console.log(` Reconstructed: ${reconstructedHex.substring(0, 200)}${reconstructedHex.length > 200 ? '...' : ''}`);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// Step 6: Summary and Statistics
|
|
318
|
-
console.log('\n\nš Step 6: Summary and Statistics');
|
|
319
|
-
console.log('='.repeat(60));
|
|
320
|
-
|
|
321
|
-
const totalFields = fields.length;
|
|
322
|
-
const successfulFields = Object.keys(fieldDetails).filter(k => fieldDetails[k].buffer).length;
|
|
323
|
-
const totalBytes = Object.values(fieldDetails)
|
|
324
|
-
.filter(f => f.buffer)
|
|
325
|
-
.reduce((sum, f) => sum + f.buffer.length, 0);
|
|
326
|
-
|
|
327
|
-
console.log('\nš Extraction Statistics:');
|
|
328
|
-
console.log(` Total fields: ${totalFields}`);
|
|
329
|
-
console.log(` Successfully extracted: ${successfulFields}`);
|
|
330
|
-
console.log(` Success rate: ${((successfulFields / totalFields) * 100).toFixed(1)}%`);
|
|
331
|
-
console.log(` Total bytes processed: ${totalBytes}`);
|
|
332
|
-
console.log(` Average field size: ${(totalBytes / successfulFields).toFixed(1)} bytes`);
|
|
333
|
-
|
|
334
|
-
console.log('\nš Field Size Distribution:');
|
|
335
|
-
Object.entries(fieldDetails)
|
|
336
|
-
.filter(([name, data]) => data.buffer)
|
|
337
|
-
.sort((a, b) => b[1].buffer.length - a[1].buffer.length)
|
|
338
|
-
.forEach(([name, data]) => {
|
|
339
|
-
const percentage = ((data.buffer.length / totalBytes) * 100).toFixed(1);
|
|
340
|
-
console.log(` ${name.padEnd(15)}: ${data.buffer.length.toString().padStart(2)} bytes (${percentage.padStart(4)}%)`);
|
|
341
|
-
});
|
|
342
|
-
|
|
343
|
-
// Final validation
|
|
344
|
-
console.log('\nā
Demonstration Complete!');
|
|
345
|
-
console.log(` UTXOs generated: ${utxos.length}`);
|
|
346
|
-
console.log(` Transaction created: ${tx.id}`);
|
|
347
|
-
console.log(` Preimage extracted: ${preimageBuffer.length} bytes`);
|
|
348
|
-
console.log(` Fields separated: ${successfulFields}/${totalFields}`);
|
|
349
|
-
console.log(` Reconstruction: ${matches ? 'Success' : 'Partial'}`);
|
|
350
|
-
|
|
351
|
-
return {
|
|
352
|
-
utxos,
|
|
353
|
-
transaction: tx,
|
|
354
|
-
preimage: preimageBuffer,
|
|
355
|
-
fields: fieldDetails,
|
|
356
|
-
statistics: {
|
|
357
|
-
totalFields,
|
|
358
|
-
successfulFields,
|
|
359
|
-
totalBytes,
|
|
360
|
-
reconstructionMatches: matches
|
|
361
|
-
}
|
|
362
|
-
};
|
|
363
|
-
|
|
364
|
-
} catch (error) {
|
|
365
|
-
console.error('\nā Demonstration failed:', error.message);
|
|
366
|
-
console.error('Stack trace:', error.stack);
|
|
367
|
-
throw error;
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
// Run the demonstration
|
|
372
|
-
if (require.main === module) {
|
|
373
|
-
demonstrateUTXOAndPreimage()
|
|
374
|
-
.then(result => {
|
|
375
|
-
console.log('\nš All operations completed successfully!');
|
|
376
|
-
})
|
|
377
|
-
.catch(error => {
|
|
378
|
-
console.error('\nš„ Demonstration failed:', error.message);
|
|
379
|
-
process.exit(1);
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
module.exports = { demonstrateUTXOAndPreimage };
|
|
@@ -1,289 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Script Helper Utilities Demo
|
|
5
|
-
* ============================
|
|
6
|
-
*
|
|
7
|
-
* Demonstrates the SmartLedger-BSV Script Helper utilities for
|
|
8
|
-
* Bitcoin Script development and analysis.
|
|
9
|
-
*
|
|
10
|
-
* Features demonstrated:
|
|
11
|
-
* - Script building and construction
|
|
12
|
-
* - ASM parsing and generation
|
|
13
|
-
* - Script analysis and optimization
|
|
14
|
-
* - Opcode utilities and mapping
|
|
15
|
-
* - Script debugging tools
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
const bsv = require('../index.js');
|
|
19
|
-
|
|
20
|
-
console.log('š ļø SmartLedger-BSV Script Helper Demo');
|
|
21
|
-
console.log('======================================\n');
|
|
22
|
-
|
|
23
|
-
async function demonstrateScriptHelper() {
|
|
24
|
-
try {
|
|
25
|
-
// Check if custom script helper is available
|
|
26
|
-
let ScriptHelper;
|
|
27
|
-
try {
|
|
28
|
-
ScriptHelper = require('../lib/custom-script-helper.js');
|
|
29
|
-
console.log('ā
Custom Script Helper loaded');
|
|
30
|
-
} catch (e) {
|
|
31
|
-
console.log('ā¹ļø Using built-in BSV Script utilities');
|
|
32
|
-
ScriptHelper = null;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Test 1: Basic Script Construction
|
|
36
|
-
console.log('šļø Test 1: Basic Script Construction');
|
|
37
|
-
console.log('------------------------------------');
|
|
38
|
-
|
|
39
|
-
// P2PKH script
|
|
40
|
-
const privateKey = bsv.PrivateKey.fromRandom();
|
|
41
|
-
const address = privateKey.toAddress();
|
|
42
|
-
const p2pkhScript = bsv.Script.buildPublicKeyHashOut(address);
|
|
43
|
-
|
|
44
|
-
console.log('š Generated Address:', address.toString());
|
|
45
|
-
console.log('š P2PKH Script ASM:', p2pkhScript.toString());
|
|
46
|
-
console.log('š¢ P2PKH Script Hex:', p2pkhScript.toHex());
|
|
47
|
-
console.log('š Script Size:', p2pkhScript.toBuffer().length, 'bytes');
|
|
48
|
-
console.log('');
|
|
49
|
-
|
|
50
|
-
// P2SH script
|
|
51
|
-
const redeemScript = bsv.Script.buildMultisigOut([privateKey.publicKey], 1);
|
|
52
|
-
const p2shScript = bsv.Script.buildScriptHashOut(redeemScript);
|
|
53
|
-
|
|
54
|
-
console.log('š Redeem Script ASM:', redeemScript.toString());
|
|
55
|
-
console.log('š¦ P2SH Script ASM:', p2shScript.toString());
|
|
56
|
-
console.log('š¢ P2SH Script Hex:', p2shScript.toHex());
|
|
57
|
-
console.log('');
|
|
58
|
-
|
|
59
|
-
// Test 2: Script Analysis
|
|
60
|
-
console.log('š Test 2: Script Analysis');
|
|
61
|
-
console.log('-------------------------');
|
|
62
|
-
|
|
63
|
-
const scripts = [
|
|
64
|
-
{ name: 'P2PKH', script: p2pkhScript },
|
|
65
|
-
{ name: 'P2SH', script: p2shScript },
|
|
66
|
-
{ name: 'Multisig', script: redeemScript }
|
|
67
|
-
];
|
|
68
|
-
|
|
69
|
-
scripts.forEach(({ name, script }) => {
|
|
70
|
-
console.log(`š ${name} Analysis:`);
|
|
71
|
-
console.log(` š Size: ${script.toBuffer().length} bytes`);
|
|
72
|
-
console.log(` š§© Chunks: ${script.chunks.length}`);
|
|
73
|
-
console.log(` š Push-only: ${script.isPushOnly()}`);
|
|
74
|
-
console.log(` š Has multisig: ${script.toString().includes('CHECKMULTISIG')}`);
|
|
75
|
-
console.log(` ā° Has timelock: ${script.toString().includes('CHECKLOCKTIMEVERIFY')}`);
|
|
76
|
-
console.log('');
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
// Test 3: Custom Script Building
|
|
80
|
-
console.log('āļø Test 3: Custom Script Building');
|
|
81
|
-
console.log('---------------------------------');
|
|
82
|
-
|
|
83
|
-
// Build a custom script with various operations
|
|
84
|
-
const customScript = new bsv.Script()
|
|
85
|
-
.add(bsv.Opcode.OP_DUP)
|
|
86
|
-
.add(bsv.Opcode.OP_HASH160)
|
|
87
|
-
.add(address.hashBuffer)
|
|
88
|
-
.add(bsv.Opcode.OP_EQUALVERIFY)
|
|
89
|
-
.add(bsv.Opcode.OP_CHECKSIG);
|
|
90
|
-
|
|
91
|
-
console.log('š ļø Custom Script ASM:', customScript.toString());
|
|
92
|
-
console.log('š¢ Custom Script Hex:', customScript.toHex());
|
|
93
|
-
|
|
94
|
-
// Verify it matches P2PKH
|
|
95
|
-
const isEquivalent = customScript.toString() === p2pkhScript.toString();
|
|
96
|
-
console.log('šÆ Equivalent to P2PKH:', isEquivalent ? 'ā
' : 'ā');
|
|
97
|
-
console.log('');
|
|
98
|
-
|
|
99
|
-
// Test 4: Script Parsing and Conversion
|
|
100
|
-
console.log('š Test 4: Script Parsing and Conversion');
|
|
101
|
-
console.log('---------------------------------------');
|
|
102
|
-
|
|
103
|
-
const testASM = 'OP_DUP OP_HASH160 OP_PUSHDATA1 0x14 0x' + address.hashBuffer.toString('hex') + ' OP_EQUALVERIFY OP_CHECKSIG';
|
|
104
|
-
console.log('š Input ASM:', testASM);
|
|
105
|
-
|
|
106
|
-
try {
|
|
107
|
-
const parsedScript = bsv.Script.fromASM(testASM);
|
|
108
|
-
console.log('ā
Successfully parsed ASM');
|
|
109
|
-
console.log('š Parsed Script:', parsedScript.toString());
|
|
110
|
-
console.log('š¢ Script Hex:', parsedScript.toHex());
|
|
111
|
-
|
|
112
|
-
// Convert back to ASM
|
|
113
|
-
const backToASM = parsedScript.toString();
|
|
114
|
-
console.log('š Back to ASM:', backToASM);
|
|
115
|
-
console.log('šÆ Round-trip success:', testASM.includes('OP_DUP') && backToASM.includes('OP_DUP') ? 'ā
' : 'ā');
|
|
116
|
-
|
|
117
|
-
} catch (error) {
|
|
118
|
-
console.log('ā ASM parsing error:', error.message);
|
|
119
|
-
}
|
|
120
|
-
console.log('');
|
|
121
|
-
|
|
122
|
-
// Test 5: Opcode Analysis
|
|
123
|
-
console.log('š¤ Test 5: Opcode Analysis');
|
|
124
|
-
console.log('-------------------------');
|
|
125
|
-
|
|
126
|
-
const opcodes = [
|
|
127
|
-
bsv.Opcode.OP_0,
|
|
128
|
-
bsv.Opcode.OP_1,
|
|
129
|
-
bsv.Opcode.OP_DUP,
|
|
130
|
-
bsv.Opcode.OP_HASH160,
|
|
131
|
-
bsv.Opcode.OP_EQUAL,
|
|
132
|
-
bsv.Opcode.OP_CHECKSIG,
|
|
133
|
-
bsv.Opcode.OP_CHECKMULTISIG,
|
|
134
|
-
bsv.Opcode.OP_CHECKLOCKTIMEVERIFY
|
|
135
|
-
];
|
|
136
|
-
|
|
137
|
-
console.log('š Common Opcodes:');
|
|
138
|
-
opcodes.forEach(opcode => {
|
|
139
|
-
const name = bsv.Opcode.reverseMap[opcode] || `OP_${opcode}`;
|
|
140
|
-
console.log(` ${opcode.toString().padStart(3)} = ${name}`);
|
|
141
|
-
});
|
|
142
|
-
console.log('');
|
|
143
|
-
|
|
144
|
-
// Test 6: Script Complexity Analysis
|
|
145
|
-
console.log('š Test 6: Script Complexity Analysis');
|
|
146
|
-
console.log('------------------------------------');
|
|
147
|
-
|
|
148
|
-
const complexScripts = [
|
|
149
|
-
{
|
|
150
|
-
name: 'Simple P2PKH',
|
|
151
|
-
script: p2pkhScript,
|
|
152
|
-
expectedOps: 5
|
|
153
|
-
},
|
|
154
|
-
{
|
|
155
|
-
name: 'Multisig 1-of-1',
|
|
156
|
-
script: redeemScript,
|
|
157
|
-
expectedOps: 4
|
|
158
|
-
},
|
|
159
|
-
{
|
|
160
|
-
name: 'Time Lock',
|
|
161
|
-
script: new bsv.Script()
|
|
162
|
-
.add(144) // ~24 hours in blocks
|
|
163
|
-
.add(bsv.Opcode.OP_CHECKLOCKTIMEVERIFY)
|
|
164
|
-
.add(bsv.Opcode.OP_DROP)
|
|
165
|
-
.add(bsv.Opcode.OP_DUP)
|
|
166
|
-
.add(bsv.Opcode.OP_HASH160)
|
|
167
|
-
.add(address.hashBuffer)
|
|
168
|
-
.add(bsv.Opcode.OP_EQUALVERIFY)
|
|
169
|
-
.add(bsv.Opcode.OP_CHECKSIG),
|
|
170
|
-
expectedOps: 8
|
|
171
|
-
}
|
|
172
|
-
];
|
|
173
|
-
|
|
174
|
-
complexScripts.forEach(({ name, script, expectedOps }) => {
|
|
175
|
-
const chunks = script.chunks.length;
|
|
176
|
-
const size = script.toBuffer().length;
|
|
177
|
-
const complexity = chunks > 10 ? 'High' : chunks > 5 ? 'Medium' : 'Low';
|
|
178
|
-
|
|
179
|
-
console.log(`š ${name}:`);
|
|
180
|
-
console.log(` š Chunks: ${chunks} (expected ~${expectedOps})`);
|
|
181
|
-
console.log(` š Size: ${size} bytes`);
|
|
182
|
-
console.log(` ā” Complexity: ${complexity}`);
|
|
183
|
-
console.log(` š° Est. fee (1 sat/byte): ${size} satoshis`);
|
|
184
|
-
console.log('');
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
// Test 7: Script Validation
|
|
188
|
-
console.log('ā
Test 7: Script Validation');
|
|
189
|
-
console.log('---------------------------');
|
|
190
|
-
|
|
191
|
-
const validationTests = [
|
|
192
|
-
{
|
|
193
|
-
name: 'Valid P2PKH',
|
|
194
|
-
script: p2pkhScript,
|
|
195
|
-
shouldPass: true
|
|
196
|
-
},
|
|
197
|
-
{
|
|
198
|
-
name: 'Valid Multisig',
|
|
199
|
-
script: redeemScript,
|
|
200
|
-
shouldPass: true
|
|
201
|
-
},
|
|
202
|
-
{
|
|
203
|
-
name: 'Empty Script',
|
|
204
|
-
script: new bsv.Script(),
|
|
205
|
-
shouldPass: true
|
|
206
|
-
},
|
|
207
|
-
{
|
|
208
|
-
name: 'Invalid Opcode Script',
|
|
209
|
-
script: (() => {
|
|
210
|
-
try {
|
|
211
|
-
return new bsv.Script().add(255); // Invalid opcode
|
|
212
|
-
} catch (e) {
|
|
213
|
-
return null;
|
|
214
|
-
}
|
|
215
|
-
})(),
|
|
216
|
-
shouldPass: false
|
|
217
|
-
}
|
|
218
|
-
];
|
|
219
|
-
|
|
220
|
-
validationTests.forEach(({ name, script, shouldPass }) => {
|
|
221
|
-
if (!script) {
|
|
222
|
-
console.log(`ā ļø ${name}: Could not create (expected for invalid tests)`);
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
try {
|
|
227
|
-
const isValid = script.toBuffer().length >= 0; // Basic validation
|
|
228
|
-
console.log(`${isValid === shouldPass ? 'ā
' : 'ā'} ${name}: ${isValid ? 'Valid' : 'Invalid'}`);
|
|
229
|
-
} catch (error) {
|
|
230
|
-
const failed = !shouldPass;
|
|
231
|
-
console.log(`${failed ? 'ā
' : 'ā'} ${name}: Failed validation (${error.message.substring(0, 30)}...)`);
|
|
232
|
-
}
|
|
233
|
-
});
|
|
234
|
-
console.log('');
|
|
235
|
-
|
|
236
|
-
// Test 8: Performance Metrics
|
|
237
|
-
console.log('š Test 8: Performance Metrics');
|
|
238
|
-
console.log('-----------------------------');
|
|
239
|
-
|
|
240
|
-
const iterations = 1000;
|
|
241
|
-
|
|
242
|
-
// Script creation performance
|
|
243
|
-
const createStart = Date.now();
|
|
244
|
-
for (let i = 0; i < iterations; i++) {
|
|
245
|
-
const tempKey = bsv.PrivateKey.fromRandom();
|
|
246
|
-
const tempAddr = tempKey.toAddress();
|
|
247
|
-
bsv.Script.buildPublicKeyHashOut(tempAddr);
|
|
248
|
-
}
|
|
249
|
-
const createEnd = Date.now();
|
|
250
|
-
const createTime = createEnd - createStart;
|
|
251
|
-
|
|
252
|
-
// Script parsing performance
|
|
253
|
-
const parseStart = Date.now();
|
|
254
|
-
const testScript = p2pkhScript.toString();
|
|
255
|
-
for (let i = 0; i < iterations; i++) {
|
|
256
|
-
bsv.Script.fromASM(testScript);
|
|
257
|
-
}
|
|
258
|
-
const parseEnd = Date.now();
|
|
259
|
-
const parseTime = parseEnd - parseStart;
|
|
260
|
-
|
|
261
|
-
console.log(`ā±ļø Script Creation: ${createTime}ms for ${iterations} scripts`);
|
|
262
|
-
console.log(`š Creation Rate: ${(iterations * 1000 / createTime).toFixed(0)} scripts/second`);
|
|
263
|
-
console.log(`ā±ļø Script Parsing: ${parseTime}ms for ${iterations} parses`);
|
|
264
|
-
console.log(`š Parsing Rate: ${(iterations * 1000 / parseTime).toFixed(0)} parses/second`);
|
|
265
|
-
|
|
266
|
-
} catch (error) {
|
|
267
|
-
console.error('ā Demo error:', error.message);
|
|
268
|
-
console.error('š Stack:', error.stack);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// Run the demo
|
|
273
|
-
demonstrateScriptHelper().then(() => {
|
|
274
|
-
console.log('\nš Script Helper Demo completed!');
|
|
275
|
-
console.log('');
|
|
276
|
-
console.log('š” Use Cases:');
|
|
277
|
-
console.log(' ⢠Custom script development and testing');
|
|
278
|
-
console.log(' ⢠Script analysis and optimization');
|
|
279
|
-
console.log(' ⢠Educational Bitcoin Script learning');
|
|
280
|
-
console.log(' ⢠Smart contract script generation');
|
|
281
|
-
console.log(' ⢠Transaction script debugging');
|
|
282
|
-
console.log(' ⢠Fee estimation for complex scripts');
|
|
283
|
-
console.log('');
|
|
284
|
-
console.log('š§ Integration Tips:');
|
|
285
|
-
console.log(' ⢠Use with SmartContract framework for covenants');
|
|
286
|
-
console.log(' ⢠Combine with UTXOGenerator for complete testing');
|
|
287
|
-
console.log(' ⢠Store optimized scripts for production use');
|
|
288
|
-
console.log(' ⢠Validate scripts before blockchain deployment');
|
|
289
|
-
});
|