smartledger-bsv 3.3.2 → 3.3.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 +220 -79
- package/README.md +283 -71
- package/bsv-covenant.min.js +26 -3
- package/bsv-gdaf.min.js +11 -9
- package/bsv-ltp.min.js +10 -8
- package/bsv-mnemonic.min.js +4 -4
- package/bsv-script-helper.min.js +2 -2
- package/bsv-security.min.js +3 -24
- package/bsv-shamir.min.js +2 -2
- package/bsv-smartcontract.min.js +10 -8
- package/bsv.bundle.js +9 -9
- package/bsv.min.js +10 -8
- package/build/webpack.bundle.config.js +2 -2
- package/build/webpack.config.js +2 -2
- package/build/webpack.covenant.config.js +2 -2
- package/build/webpack.gdaf.config.js +6 -43
- package/build/webpack.script-helper.config.js +2 -2
- package/build/webpack.security.config.js +2 -2
- package/build/webpack.smartcontract.config.js +2 -2
- package/bundle-entry.js +1 -341
- package/covenant-entry.js +1 -44
- package/demos/README.md +188 -0
- package/{architecture_demo.js → demos/architecture_demo.js} +2 -2
- package/demos/bsv_wallet_demo.js +242 -0
- package/{complete_ltp_demo.js → demos/complete_ltp_demo.js} +1 -1
- package/demos/debug_tools_demo.js +87 -0
- package/demos/demo_features.js +123 -0
- package/demos/easy_interface_demo.js +109 -0
- package/demos/ecies_demo.js +182 -0
- package/demos/gdaf_core_test.js +131 -0
- package/demos/gdaf_demo.js +237 -0
- package/demos/ltp_demo.js +361 -0
- package/demos/ltp_primitives_demo.js +403 -0
- package/demos/message_demo.js +209 -0
- package/demos/preimage_separation_demo.js +383 -0
- package/demos/script_helper_demo.js +289 -0
- package/demos/security_demo.js +287 -0
- package/{shamir_demo.js → demos/shamir_demo.js} +1 -1
- package/{simple_demo.js → demos/simple_demo.js} +1 -1
- package/demos/simple_p2pkh_demo.js +169 -0
- package/demos/simple_utxo_preimage_demo.js +196 -0
- package/demos/smart_contract_demo.html +1347 -0
- package/demos/smart_contract_demo.js +910 -0
- package/demos/utxo_generator_demo.js +244 -0
- package/demos/validation_pipeline_demo.js +155 -0
- package/demos/web3keys.html +740 -0
- package/docs/BUNDLE_UPDATE_SUMMARY.md +40 -0
- package/docs/DOCUMENTATION_REVIEW_REPORT.md +295 -0
- package/docs/FIX_CREATEHMAC_ISSUE.md +91 -0
- package/docs/MODULE_REFERENCE_COMPLETE.md +330 -0
- package/docs/README.md +107 -79
- package/docs/SMARTLEDGER_BSV_USAGE_ANSWERS.md +477 -0
- package/docs/SMARTLEDGER_BSV_USAGE_EXAMPLES.js +372 -0
- package/docs/SMARTLEDGER_BSV_USAGE_GUIDE.md +555 -0
- package/docs/SMART_CONTRACT_DEVELOPMENT_GUIDE.md +1459 -0
- package/docs/advanced/LEGAL_TOKEN_PROTOCOL.md +411 -0
- package/docs/advanced/SMART_CONTRACT_GUIDE.md +1255 -0
- package/docs/advanced/UTXO_MANAGER_GUIDE.md +851 -0
- package/docs/api/LTP.md +334 -0
- package/docs/getting-started/INSTALLATION.md +410 -0
- package/docs/getting-started/QUICK_START.md +180 -0
- package/docs/migration/FROM_BSV_1_5_6.md +260 -0
- package/docs/technical/GDAF_DEVELOPER_INTERFACE.md +187 -0
- package/docs/technical/GDAF_IMPLEMENTATION_COMPLETE.md +190 -0
- package/docs/technical/SHAMIR_INTEGRATION_SUMMARY.md +165 -0
- package/docs/technical/roadmap.md +1250 -0
- package/docs/technical/trust_law.md +142 -0
- package/examples/complete_workflow_demo.js +783 -0
- package/examples/definitive_working_demo.js +261 -0
- package/examples/final_working_contracts.js +338 -0
- package/examples/smart_contract_templates.js +718 -0
- package/examples/working_smart_contracts.js +348 -0
- package/gdaf-entry.js +2 -54
- package/index.js +32 -0
- package/lib/mnemonic/pbkdf2.browser.js +69 -0
- package/lib/mnemonic/pbkdf2.js +2 -68
- package/lib/mnemonic/pbkdf2.node.js +68 -0
- package/ltp-entry.js +2 -92
- package/package.json +21 -8
- package/script-helper-entry.js +1 -49
- package/security-entry.js +1 -70
- package/shamir-entry.js +1 -173
- package/smartcontract-entry.js +1 -133
- package/tests/browser-compatibility/README.md +35 -0
- package/tests/browser-compatibility/test-cdn-vs-local.html +186 -0
- package/tests/browser-compatibility/test-pbkdf2.html +51 -0
- package/tests/test_builtin_verify.js +117 -0
- package/tests/test_debug_integration.js +71 -0
- package/tests/test_ecdsa_little.js +70 -0
- package/tests/test_smartverify_der.js +110 -0
- package/utilities/blockchain-state.js +155 -155
- package/utilities/blockchain-state.json +103293 -5244
- package/utilities/miner-simulator.js +354 -358
- package/utilities/mock-utxo-generator.js +54 -54
- package/utilities/raw-tx-examples.js +120 -122
- package/utilities/success-demo.js +104 -105
- package/utilities/transaction-examples.js +188 -188
- package/utilities/utxo-manager.js +91 -91
- package/utilities/wallet-setup.js +79 -80
- package/utilities/working-signature-demo.js +108 -110
- package/SECURITY.md +0 -75
- package/build/bsv-covenant.min.js +0 -10
- package/build/bsv-script-helper.min.js +0 -10
- package/build/bsv-security.min.js +0 -31
- package/build/bsv-smartcontract.min.js +0 -39
- package/build/bsv.bundle.js +0 -39
- package/build/bsv.min.js +0 -39
- package/validation_test.js +0 -97
- /package/docs/{ADVANCED_COVENANT_DEVELOPMENT.md → advanced/ADVANCED_COVENANT_DEVELOPMENT.md} +0 -0
- /package/docs/{CUSTOM_SCRIPT_DEVELOPMENT.md → advanced/CUSTOM_SCRIPT_DEVELOPMENT.md} +0 -0
- /package/docs/{block.md → api/BLOCKS.md} +0 -0
- /package/docs/{ecies.md → api/ECIES.md} +0 -0
- /package/docs/{networks.md → api/NETWORKS.md} +0 -0
- /package/docs/{script.md → api/SCRIPTS.md} +0 -0
- /package/docs/{transaction.md → api/TRANSACTIONS.md} +0 -0
- /package/docs/{unspentoutput.md → api/UTXO.md} +0 -0
- /package/{test_shamir.js → tests/test_shamir.js} +0 -0
- /package/{test_standalone_shamir.html → tests/test_standalone_shamir.html} +0 -0
|
@@ -0,0 +1,555 @@
|
|
|
1
|
+
# 📖 SmartLedger-BSV v3.3.3 Usage Guide
|
|
2
|
+
|
|
3
|
+
**Comprehensive answers to BIP-143 preimage extraction questions**
|
|
4
|
+
**Date:** October 30, 2025
|
|
5
|
+
**Library:** smartledger-bsv v3.3.3
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 📋 **1. Complete Field Name Documentation**
|
|
10
|
+
|
|
11
|
+
### **✅ Supported Fields for `testFieldExtraction()`**
|
|
12
|
+
|
|
13
|
+
Based on the source code analysis, here are the **exact field names** that work with `testFieldExtraction()`:
|
|
14
|
+
|
|
15
|
+
#### **RIGHT-side Fields (extracted from end of preimage):**
|
|
16
|
+
- **`value`** - 8 bytes, amount in satoshis
|
|
17
|
+
- **`nSequence`** - 4 bytes, sequence number
|
|
18
|
+
- **`hashOutputs`** - 32 bytes, hash of all outputs
|
|
19
|
+
- **`nLocktime`** - 4 bytes, transaction lock time
|
|
20
|
+
- **`sighashType`** - 4 bytes, signature hash type
|
|
21
|
+
|
|
22
|
+
#### **LEFT-side Fields (extracted from beginning):**
|
|
23
|
+
- **`nVersion`** - 4 bytes, transaction version
|
|
24
|
+
- **`hashPrevouts`** - 32 bytes, hash of all previous outputs
|
|
25
|
+
- **`hashSequence`** - 32 bytes, hash of all sequence numbers
|
|
26
|
+
- **`outpoint_txid`** - 32 bytes, referenced transaction ID
|
|
27
|
+
- **`outpoint_vout`** - 4 bytes, referenced output index
|
|
28
|
+
|
|
29
|
+
#### **DYNAMIC Fields (variable-length extraction):**
|
|
30
|
+
- **`scriptCode`** - Variable bytes, the script being executed
|
|
31
|
+
- **`scriptLen`** - CompactSize varint, length of scriptCode
|
|
32
|
+
|
|
33
|
+
### **❌ Non-Working Field Names (and why)**
|
|
34
|
+
|
|
35
|
+
These field names fail with "Unknown field" because they use **different naming conventions**:
|
|
36
|
+
|
|
37
|
+
- **`version`** → Use **`nVersion`** instead
|
|
38
|
+
- **`outpoint`** → Use **`outpoint_txid`** and **`outpoint_vout`** separately
|
|
39
|
+
- **`amount`** → Use **`value`** instead
|
|
40
|
+
- **`sequence`** → Use **`nSequence`** instead
|
|
41
|
+
- **`locktime`** → Use **`nLocktime`** instead
|
|
42
|
+
- **`sighash`** → Use **`sighashType`** instead
|
|
43
|
+
|
|
44
|
+
### **📝 Field Name Mapping Table**
|
|
45
|
+
|
|
46
|
+
| Your Name | SmartLedger Name | BIP-143 Name | Status |
|
|
47
|
+
|-----------|------------------|--------------|---------|
|
|
48
|
+
| `version` | `nVersion` | `nVersion` | ✅ Use nVersion |
|
|
49
|
+
| `hashPrevouts` | `hashPrevouts` | `hashPrevouts` | ✅ Works |
|
|
50
|
+
| `hashSequence` | `hashSequence` | `hashSequence` | ✅ Works |
|
|
51
|
+
| `outpoint` | `outpoint_txid` + `outpoint_vout` | `outpoint` | ⚠️ Split into two |
|
|
52
|
+
| `scriptCode` | `scriptCode` | `scriptCode` | ✅ Works |
|
|
53
|
+
| `amount` | `value` | `value` | ✅ Use value |
|
|
54
|
+
| `sequence` | `nSequence` | `nSequence` | ✅ Use nSequence |
|
|
55
|
+
| `hashOutputs` | `hashOutputs` | `hashOutputs` | ✅ Works |
|
|
56
|
+
| `locktime` | `nLocktime` | `nLockTime` | ✅ Use nLocktime |
|
|
57
|
+
| `sighash` | `sighashType` | `sighashType` | ✅ Use sighashType |
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 🔧 **2. Field Capabilities Matrix**
|
|
62
|
+
|
|
63
|
+
### **ASM Generation vs Extract-Only**
|
|
64
|
+
|
|
65
|
+
**All supported fields can both extract and generate ASM:**
|
|
66
|
+
|
|
67
|
+
```javascript
|
|
68
|
+
// Both of these work for all supported fields:
|
|
69
|
+
const extraction = bsv.SmartContract.testFieldExtraction(preimageHex, 'value');
|
|
70
|
+
const extracted = bsv.SmartContract.extractPreimage(preimageHex);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### **Why some fields appear "extract-only":**
|
|
74
|
+
|
|
75
|
+
The confusion comes from using incorrect field names. When you use `version` instead of `nVersion`, `testFieldExtraction()` fails but `extractPreimage()` works because:
|
|
76
|
+
|
|
77
|
+
1. **`testFieldExtraction()`** - Strict field name validation
|
|
78
|
+
2. **`extractPreimage()`** - Returns all fields with both naming conventions
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## 🚨 **3. Custom Transaction Preimage Generation**
|
|
83
|
+
|
|
84
|
+
### **Why Custom Transactions Fail**
|
|
85
|
+
|
|
86
|
+
The CompactSize errors occur because **custom transactions often have structural differences** from the expected BIP-143 format:
|
|
87
|
+
|
|
88
|
+
#### **Common Issues:**
|
|
89
|
+
1. **Missing or invalid scriptCode** in UTXO
|
|
90
|
+
2. **Incorrect sighash type** (must include FORKID)
|
|
91
|
+
3. **Invalid transaction structure** (missing required fields)
|
|
92
|
+
4. **Wrong input/output encoding**
|
|
93
|
+
|
|
94
|
+
### **✅ Working Custom Transaction Pattern**
|
|
95
|
+
|
|
96
|
+
```javascript
|
|
97
|
+
// ✅ CORRECT: Complete UTXO structure
|
|
98
|
+
function createWorkingCustomTransaction() {
|
|
99
|
+
const privateKey = new bsv.PrivateKey();
|
|
100
|
+
const address = privateKey.toAddress();
|
|
101
|
+
const script = bsv.Script.buildPublicKeyHashOut(address);
|
|
102
|
+
|
|
103
|
+
// CRITICAL: Complete UTXO with proper script
|
|
104
|
+
const utxo = {
|
|
105
|
+
txId: '0'.repeat(64), // Valid 32-byte hex
|
|
106
|
+
outputIndex: 0,
|
|
107
|
+
address: address.toString(),
|
|
108
|
+
script: script.toString(), // ← MUST be valid hex script
|
|
109
|
+
satoshis: 100000
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const tx = new bsv.Transaction()
|
|
113
|
+
.from(utxo)
|
|
114
|
+
.to('1BitcoinEaterAddressDontSendf59kuE', 50000)
|
|
115
|
+
.change(address)
|
|
116
|
+
.sign(privateKey);
|
|
117
|
+
|
|
118
|
+
// CRITICAL: Use FORKID sighash
|
|
119
|
+
const sighashType = bsv.crypto.Signature.SIGHASH_ALL | bsv.crypto.Signature.SIGHASH_FORKID;
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
const preimageBuffer = bsv.Transaction.sighash.sighashPreimage(
|
|
123
|
+
tx, sighashType, 0, script, new bsv.crypto.BN(utxo.satoshis)
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
return preimageBuffer.toString('hex');
|
|
127
|
+
} catch (error) {
|
|
128
|
+
console.error('Custom transaction preimage failed:', error.message);
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### **❌ Common Mistakes That Cause CompactSize Errors**
|
|
135
|
+
|
|
136
|
+
```javascript
|
|
137
|
+
// ❌ WRONG: Invalid script
|
|
138
|
+
const badUTXO = {
|
|
139
|
+
script: 'invalid_hex', // Causes CompactSize error
|
|
140
|
+
// ... other fields
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// ❌ WRONG: Missing FORKID
|
|
144
|
+
const badSighash = bsv.crypto.Signature.SIGHASH_ALL; // No FORKID
|
|
145
|
+
|
|
146
|
+
// ❌ WRONG: Invalid UTXO structure
|
|
147
|
+
const badUTXO2 = {
|
|
148
|
+
txId: 'short', // Must be 64 chars (32 bytes)
|
|
149
|
+
satoshis: 0 // Must be > 546 (dust limit)
|
|
150
|
+
};
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## 📚 **4. extractPreimage() vs testFieldExtraction()**
|
|
156
|
+
|
|
157
|
+
### **When to Use Each Method**
|
|
158
|
+
|
|
159
|
+
#### **Use `extractPreimage()` for:**
|
|
160
|
+
- **General field access** - Get all fields at once
|
|
161
|
+
- **Data analysis** - Examining preimage structure
|
|
162
|
+
- **Production apps** - Reliable field extraction
|
|
163
|
+
|
|
164
|
+
```javascript
|
|
165
|
+
// ✅ General purpose extraction
|
|
166
|
+
const extracted = bsv.SmartContract.extractPreimage(preimageHex);
|
|
167
|
+
console.log('Version:', extracted.version.toString('hex'));
|
|
168
|
+
console.log('Value:', extracted.amount.toString('hex')); // Note: 'amount', not 'value'
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
#### **Use `testFieldExtraction()` for:**
|
|
172
|
+
- **ASM generation** - Building Bitcoin Scripts
|
|
173
|
+
- **Covenant development** - Creating smart contracts
|
|
174
|
+
- **Script testing** - Validating field extraction logic
|
|
175
|
+
|
|
176
|
+
```javascript
|
|
177
|
+
// ✅ ASM generation for covenants
|
|
178
|
+
const result = bsv.SmartContract.testFieldExtraction(preimageHex, 'value');
|
|
179
|
+
console.log('Generated ASM:', result.fieldExtraction.asmGenerated);
|
|
180
|
+
console.log('Extracted value:', result.fieldExtraction.value);
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### **Key Differences:**
|
|
184
|
+
|
|
185
|
+
| Feature | `extractPreimage()` | `testFieldExtraction()` |
|
|
186
|
+
|---------|---------------------|-------------------------|
|
|
187
|
+
| **Purpose** | Data extraction | Script generation |
|
|
188
|
+
| **Field Names** | BIP-143 standard (`amount`, `version`) | SmartLedger format (`value`, `nVersion`) |
|
|
189
|
+
| **Returns** | Field objects | ASM + execution results |
|
|
190
|
+
| **Use Case** | Analysis, debugging | Covenant development |
|
|
191
|
+
| **Error Handling** | Graceful fallbacks | Strict validation |
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## 🔒 **5. BIP-143 Compliance**
|
|
196
|
+
|
|
197
|
+
### **✅ SmartLedger-BSV IS BIP-143 Compliant**
|
|
198
|
+
|
|
199
|
+
The library correctly implements the BIP-143 specification:
|
|
200
|
+
|
|
201
|
+
#### **Correct Field Order:**
|
|
202
|
+
1. `nVersion` (4 bytes)
|
|
203
|
+
2. `hashPrevouts` (32 bytes)
|
|
204
|
+
3. `hashSequence` (32 bytes)
|
|
205
|
+
4. `outpoint` (36 bytes: 32 + 4)
|
|
206
|
+
5. `scriptCode` (variable with CompactSize prefix)
|
|
207
|
+
6. `value` (8 bytes)
|
|
208
|
+
7. `nSequence` (4 bytes)
|
|
209
|
+
8. `hashOutputs` (32 bytes)
|
|
210
|
+
9. `nLockTime` (4 bytes)
|
|
211
|
+
10. `sighashType` (4 bytes)
|
|
212
|
+
|
|
213
|
+
#### **Naming Convention Differences**
|
|
214
|
+
|
|
215
|
+
The library uses **two naming conventions** for backward compatibility:
|
|
216
|
+
|
|
217
|
+
- **BIP-143 Standard:** `version`, `amount`, `sequence`, `locktime`, `sighash`
|
|
218
|
+
- **SmartLedger Format:** `nVersion`, `value`, `nSequence`, `nLocktime`, `sighashType`
|
|
219
|
+
|
|
220
|
+
Both are correct - just use the right one for each function!
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## 🛠️ **6. Recommended Error Handling**
|
|
225
|
+
|
|
226
|
+
### **✅ Production-Ready Error Handling Pattern**
|
|
227
|
+
|
|
228
|
+
```javascript
|
|
229
|
+
function robustPreimageExtraction(preimageHex, fieldName) {
|
|
230
|
+
const results = {
|
|
231
|
+
success: false,
|
|
232
|
+
value: null,
|
|
233
|
+
asm: null,
|
|
234
|
+
strategy: null,
|
|
235
|
+
errors: []
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
try {
|
|
239
|
+
// Step 1: Try testFieldExtraction first (for ASM generation)
|
|
240
|
+
const testResult = bsv.SmartContract.testFieldExtraction(preimageHex, fieldName);
|
|
241
|
+
|
|
242
|
+
if (testResult.success) {
|
|
243
|
+
results.success = true;
|
|
244
|
+
results.value = testResult.fieldExtraction.value;
|
|
245
|
+
results.asm = testResult.fieldExtraction.asmGenerated;
|
|
246
|
+
results.strategy = testResult.fieldExtraction.strategy;
|
|
247
|
+
return results;
|
|
248
|
+
} else {
|
|
249
|
+
results.errors.push(`testFieldExtraction failed: ${testResult.error}`);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
} catch (error) {
|
|
253
|
+
results.errors.push(`testFieldExtraction error: ${error.message}`);
|
|
254
|
+
|
|
255
|
+
// Step 2: Try field name mapping
|
|
256
|
+
const fieldMapping = {
|
|
257
|
+
'version': 'nVersion',
|
|
258
|
+
'amount': 'value',
|
|
259
|
+
'sequence': 'nSequence',
|
|
260
|
+
'locktime': 'nLocktime',
|
|
261
|
+
'sighash': 'sighashType'
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
const mappedField = fieldMapping[fieldName];
|
|
265
|
+
if (mappedField) {
|
|
266
|
+
try {
|
|
267
|
+
const mappedResult = bsv.SmartContract.testFieldExtraction(preimageHex, mappedField);
|
|
268
|
+
if (mappedResult.success) {
|
|
269
|
+
results.success = true;
|
|
270
|
+
results.value = mappedResult.fieldExtraction.value;
|
|
271
|
+
results.asm = mappedResult.fieldExtraction.asmGenerated;
|
|
272
|
+
results.strategy = mappedResult.fieldExtraction.strategy;
|
|
273
|
+
results.usedMapping = `${fieldName} → ${mappedField}`;
|
|
274
|
+
return results;
|
|
275
|
+
}
|
|
276
|
+
} catch (mappingError) {
|
|
277
|
+
results.errors.push(`Mapping attempt failed: ${mappingError.message}`);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Step 3: Fallback to extractPreimage
|
|
282
|
+
try {
|
|
283
|
+
const extracted = bsv.SmartContract.extractPreimage(preimageHex);
|
|
284
|
+
const fallbackValue = extracted[fieldName] || extracted[mappedField];
|
|
285
|
+
|
|
286
|
+
if (fallbackValue) {
|
|
287
|
+
results.success = true;
|
|
288
|
+
results.value = fallbackValue.toString('hex');
|
|
289
|
+
results.strategy = 'FALLBACK_EXTRACT';
|
|
290
|
+
results.warning = 'No ASM generated - used extractPreimage fallback';
|
|
291
|
+
return results;
|
|
292
|
+
}
|
|
293
|
+
} catch (fallbackError) {
|
|
294
|
+
results.errors.push(`Fallback extraction failed: ${fallbackError.message}`);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return results;
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### **🚨 Common Error Types and Solutions**
|
|
303
|
+
|
|
304
|
+
| Error | Cause | Solution |
|
|
305
|
+
|-------|-------|----------|
|
|
306
|
+
| `Unknown field: version` | Wrong field name | Use `nVersion` |
|
|
307
|
+
| `Invalid 8-byte CompactSize` | Bad transaction structure | Fix UTXO script/sighash |
|
|
308
|
+
| `toString() radix argument` | Numeric conversion issue | Use `.toString('hex')` |
|
|
309
|
+
| `Field not found in LEFT fields` | Typo in field name | Check spelling |
|
|
310
|
+
| `Failed to extract with any strategy` | Corrupted preimage | Validate preimage hex |
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## 🎯 **7. Production Usage Recommendations**
|
|
315
|
+
|
|
316
|
+
### **✅ Recommended Production Pattern**
|
|
317
|
+
|
|
318
|
+
```javascript
|
|
319
|
+
class ProductionPreimageHandler {
|
|
320
|
+
constructor(options = {}) {
|
|
321
|
+
this.options = {
|
|
322
|
+
validatePreimage: true,
|
|
323
|
+
enableFallbacks: true,
|
|
324
|
+
logErrors: false,
|
|
325
|
+
...options
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
async extractField(preimageHex, fieldName) {
|
|
330
|
+
// Step 1: Input validation
|
|
331
|
+
if (!preimageHex || typeof preimageHex !== 'string') {
|
|
332
|
+
throw new Error('Invalid preimage hex');
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (preimageHex.length < 208) { // Minimum BIP-143 preimage: 104 bytes = 208 hex chars
|
|
336
|
+
throw new Error('Preimage too short');
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Step 2: Normalize field name
|
|
340
|
+
const normalizedField = this.normalizeFieldName(fieldName);
|
|
341
|
+
|
|
342
|
+
// Step 3: Extract with error handling
|
|
343
|
+
try {
|
|
344
|
+
const result = bsv.SmartContract.testFieldExtraction(preimageHex, normalizedField);
|
|
345
|
+
|
|
346
|
+
if (result.success) {
|
|
347
|
+
return {
|
|
348
|
+
success: true,
|
|
349
|
+
field: normalizedField,
|
|
350
|
+
value: result.fieldExtraction.value,
|
|
351
|
+
asm: result.fieldExtraction.asmGenerated,
|
|
352
|
+
interpretation: result.fieldExtraction.interpretation
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
} catch (error) {
|
|
356
|
+
if (this.options.logErrors) {
|
|
357
|
+
console.warn(`Field extraction failed for ${fieldName}:`, error.message);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// Step 4: Fallback if enabled
|
|
362
|
+
if (this.options.enableFallbacks) {
|
|
363
|
+
return this.fallbackExtraction(preimageHex, fieldName);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
throw new Error(`Failed to extract field: ${fieldName}`);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
normalizeFieldName(fieldName) {
|
|
370
|
+
const mapping = {
|
|
371
|
+
'version': 'nVersion',
|
|
372
|
+
'amount': 'value',
|
|
373
|
+
'sequence': 'nSequence',
|
|
374
|
+
'locktime': 'nLocktime',
|
|
375
|
+
'sighash': 'sighashType',
|
|
376
|
+
'outpoint': 'outpoint_txid' // Note: only returns txid part
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
return mapping[fieldName] || fieldName;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
fallbackExtraction(preimageHex, fieldName) {
|
|
383
|
+
const extracted = bsv.SmartContract.extractPreimage(preimageHex);
|
|
384
|
+
const value = extracted[fieldName];
|
|
385
|
+
|
|
386
|
+
if (value) {
|
|
387
|
+
return {
|
|
388
|
+
success: true,
|
|
389
|
+
field: fieldName,
|
|
390
|
+
value: value.toString('hex'),
|
|
391
|
+
asm: null, // No ASM in fallback
|
|
392
|
+
interpretation: null,
|
|
393
|
+
warning: 'Used fallback extraction - no ASM generated'
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
return { success: false, error: 'Field not found in fallback extraction' };
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Usage
|
|
402
|
+
const handler = new ProductionPreimageHandler({ enableFallbacks: true });
|
|
403
|
+
const result = await handler.extractField(preimageHex, 'amount');
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
## ⚡ **8. Performance Considerations**
|
|
409
|
+
|
|
410
|
+
### **Performance Guidelines**
|
|
411
|
+
|
|
412
|
+
1. **Cache preimage objects** - Don't re-parse the same preimage
|
|
413
|
+
2. **Use `extractPreimage()` for multiple fields** - More efficient than multiple `testFieldExtraction()` calls
|
|
414
|
+
3. **Validate preimage length first** - Quick check before expensive operations
|
|
415
|
+
4. **Use appropriate extraction strategy** - `LEFT` for early fields, `RIGHT` for late fields
|
|
416
|
+
|
|
417
|
+
```javascript
|
|
418
|
+
// ✅ Efficient multiple field extraction
|
|
419
|
+
const extracted = bsv.SmartContract.extractPreimage(preimageHex);
|
|
420
|
+
const fields = {
|
|
421
|
+
version: extracted.version,
|
|
422
|
+
amount: extracted.amount,
|
|
423
|
+
sighashType: extracted.sighash
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
// ❌ Inefficient - multiple parsing
|
|
427
|
+
const version = bsv.SmartContract.testFieldExtraction(preimageHex, 'nVersion');
|
|
428
|
+
const amount = bsv.SmartContract.testFieldExtraction(preimageHex, 'value');
|
|
429
|
+
const sighash = bsv.SmartContract.testFieldExtraction(preimageHex, 'sighashType');
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
---
|
|
433
|
+
|
|
434
|
+
## 🔮 **9. Working Example: Complete Field Extraction**
|
|
435
|
+
|
|
436
|
+
### **Complete Working Example**
|
|
437
|
+
|
|
438
|
+
```javascript
|
|
439
|
+
function completeFieldExtractionDemo() {
|
|
440
|
+
console.log('🚀 Complete SmartLedger-BSV Field Extraction Demo\n');
|
|
441
|
+
|
|
442
|
+
// Step 1: Create working preimage
|
|
443
|
+
const privateKey = new bsv.PrivateKey();
|
|
444
|
+
const address = privateKey.toAddress();
|
|
445
|
+
const script = bsv.Script.buildPublicKeyHashOut(address);
|
|
446
|
+
|
|
447
|
+
const utxo = {
|
|
448
|
+
txId: '1'.repeat(64),
|
|
449
|
+
outputIndex: 0,
|
|
450
|
+
address: address.toString(),
|
|
451
|
+
script: script.toString(),
|
|
452
|
+
satoshis: 100000
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
const tx = new bsv.Transaction()
|
|
456
|
+
.from(utxo)
|
|
457
|
+
.to('1BitcoinEaterAddressDontSendf59kuE', 50000)
|
|
458
|
+
.change(address)
|
|
459
|
+
.sign(privateKey);
|
|
460
|
+
|
|
461
|
+
const sighashType = bsv.crypto.Signature.SIGHASH_ALL | bsv.crypto.Signature.SIGHASH_FORKID;
|
|
462
|
+
const preimageBuffer = bsv.Transaction.sighash.sighashPreimage(
|
|
463
|
+
tx, sighashType, 0, script, new bsv.crypto.BN(utxo.satoshis)
|
|
464
|
+
);
|
|
465
|
+
|
|
466
|
+
const preimageHex = preimageBuffer.toString('hex');
|
|
467
|
+
console.log(`📊 Generated preimage: ${preimageBuffer.length} bytes\n`);
|
|
468
|
+
|
|
469
|
+
// Step 2: Test all supported fields
|
|
470
|
+
const supportedFields = [
|
|
471
|
+
'nVersion', 'hashPrevouts', 'hashSequence', 'outpoint_txid', 'outpoint_vout',
|
|
472
|
+
'scriptCode', 'scriptLen', 'value', 'nSequence', 'hashOutputs', 'nLocktime', 'sighashType'
|
|
473
|
+
];
|
|
474
|
+
|
|
475
|
+
console.log('🧪 Testing all supported fields:\n');
|
|
476
|
+
|
|
477
|
+
supportedFields.forEach(fieldName => {
|
|
478
|
+
try {
|
|
479
|
+
const result = bsv.SmartContract.testFieldExtraction(preimageHex, fieldName);
|
|
480
|
+
|
|
481
|
+
if (result.success) {
|
|
482
|
+
const field = result.fieldExtraction;
|
|
483
|
+
console.log(`✅ ${fieldName.padEnd(15)}: ${field.value.substring(0, 20)}... (${field.strategy})`);
|
|
484
|
+
|
|
485
|
+
// Show interpretation if available
|
|
486
|
+
if (field.interpretation && field.interpretation.description) {
|
|
487
|
+
console.log(` └─ ${field.interpretation.description}`);
|
|
488
|
+
}
|
|
489
|
+
} else {
|
|
490
|
+
console.log(`❌ ${fieldName.padEnd(15)}: ${result.error}`);
|
|
491
|
+
}
|
|
492
|
+
} catch (error) {
|
|
493
|
+
console.log(`❌ ${fieldName.padEnd(15)}: ${error.message}`);
|
|
494
|
+
}
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
// Step 3: Compare with extractPreimage
|
|
498
|
+
console.log('\n🔍 Comparing with extractPreimage():\n');
|
|
499
|
+
|
|
500
|
+
const extracted = bsv.SmartContract.extractPreimage(preimageHex);
|
|
501
|
+
|
|
502
|
+
console.log('Available fields in extracted object:');
|
|
503
|
+
Object.keys(extracted).forEach(key => {
|
|
504
|
+
if (extracted[key] && extracted[key].toString) {
|
|
505
|
+
const value = extracted[key].toString('hex');
|
|
506
|
+
console.log(` ${key.padEnd(15)}: ${value.substring(0, 20)}...`);
|
|
507
|
+
}
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
return {
|
|
511
|
+
preimageHex: preimageHex,
|
|
512
|
+
supportedFields: supportedFields,
|
|
513
|
+
extracted: extracted
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// Run the demo
|
|
518
|
+
const demo = completeFieldExtractionDemo();
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
---
|
|
522
|
+
|
|
523
|
+
## 📝 **10. Summary & Best Practices**
|
|
524
|
+
|
|
525
|
+
### **✅ Key Takeaways**
|
|
526
|
+
|
|
527
|
+
1. **Use correct field names:** `nVersion`, `value`, `nSequence`, `nLocktime`, `sighashType`
|
|
528
|
+
2. **For ASM generation:** Use `testFieldExtraction()` with SmartLedger field names
|
|
529
|
+
3. **For data extraction:** Use `extractPreimage()` with BIP-143 standard names
|
|
530
|
+
4. **Custom transactions:** Ensure proper UTXO structure and FORKID sighash
|
|
531
|
+
5. **Error handling:** Implement fallbacks and field name mapping
|
|
532
|
+
6. **Performance:** Cache preimage objects, validate input early
|
|
533
|
+
|
|
534
|
+
### **🎯 Production Checklist**
|
|
535
|
+
|
|
536
|
+
- [ ] Use normalized field names consistently
|
|
537
|
+
- [ ] Implement proper error handling with fallbacks
|
|
538
|
+
- [ ] Validate preimage structure before extraction
|
|
539
|
+
- [ ] Cache preimage objects for multiple field access
|
|
540
|
+
- [ ] Log errors for debugging but handle gracefully
|
|
541
|
+
- [ ] Test with both `createExample()` and custom transactions
|
|
542
|
+
- [ ] Document which extraction method you're using and why
|
|
543
|
+
|
|
544
|
+
### **🔗 Related Documentation**
|
|
545
|
+
|
|
546
|
+
- [Smart Contract Guide](./SMART_CONTRACT_GUIDE.md) - Advanced covenant development
|
|
547
|
+
- [API Reference](../lib/smart_contract/API_REFERENCE.md) - Complete function documentation
|
|
548
|
+
- [Examples](../examples/) - Working code samples
|
|
549
|
+
- [GitHub Repository](https://github.com/codenlighten/smartledger-bsv) - Source code
|
|
550
|
+
|
|
551
|
+
---
|
|
552
|
+
|
|
553
|
+
**Created by:** SmartLedger-BSV Development Team
|
|
554
|
+
**Version:** v3.3.3
|
|
555
|
+
**Last Updated:** October 30, 2025
|