@smartledger/bsv 3.4.3 → 3.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +321 -0
- package/README.md +72 -72
- package/SECURITY.md +88 -0
- package/bin/cli.js +13 -8
- package/bsv-covenant.min.js +4 -4
- package/bsv-gdaf.min.js +5 -5
- package/bsv-ltp.min.js +7 -7
- package/bsv-smartcontract.min.js +5 -5
- package/bsv.bundle.js +5 -5
- package/bsv.d.ts +486 -9
- package/bsv.min.js +5 -5
- package/docs/COVENANT_DEVELOPMENT_RESOLVED.md +2 -2
- package/docs/MODULE_REFERENCE_COMPLETE.md +60 -57
- package/docs/advanced/UTXO_MANAGER_GUIDE.md +1 -1
- package/docs/getting-started/INSTALLATION.md +30 -30
- package/docs/getting-started/QUICK_START.md +14 -14
- package/docs/migration/FROM_BSV_1_5_6.md +5 -5
- package/gdaf-entry.js +1 -2
- package/index.js +20 -7
- package/lib/smart_contract/covenant.js +10 -1
- package/lib/smartutxo.js +20 -12
- package/lib/transaction/transaction.js +7 -0
- package/ltp-entry.js +1 -2
- package/package.json +3 -3
- 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_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/legacy/README.md +0 -11
- package/examples/legacy/smart_contract_test_integration.js +0 -269
- package/examples/legacy/test_builtin_verify.js +0 -117
- package/examples/legacy/test_debug_integration.js +0 -71
- package/examples/legacy/test_ecdsa_little.js +0 -70
- package/examples/legacy/test_shamir.js +0 -221
- package/examples/legacy/test_smartverify_der.js +0 -110
- 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/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
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* BSV Shamir Secret Sharing Test
|
|
5
|
-
* Comprehensive test of the Shamir Secret Sharing implementation
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
'use strict'
|
|
9
|
-
|
|
10
|
-
console.log('=== BSV Shamir Secret Sharing Test ===\n')
|
|
11
|
-
|
|
12
|
-
// Load the BSV library with Shamir support
|
|
13
|
-
var bsv
|
|
14
|
-
try {
|
|
15
|
-
bsv = require('./index.js')
|
|
16
|
-
console.log('✓ Loaded BSV library with Shamir support')
|
|
17
|
-
} catch (e) {
|
|
18
|
-
console.error('✗ Failed to load BSV library:', e.message)
|
|
19
|
-
process.exit(1)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Test 1: Basic functionality test
|
|
23
|
-
console.log('\n--- Test 1: Basic Secret Sharing ---')
|
|
24
|
-
try {
|
|
25
|
-
var secret = 'Hello, Bitcoin SV!'
|
|
26
|
-
var threshold = 3
|
|
27
|
-
var shares = 5
|
|
28
|
-
|
|
29
|
-
console.log('Original secret:', secret)
|
|
30
|
-
console.log('Threshold:', threshold, '/ Total shares:', shares)
|
|
31
|
-
|
|
32
|
-
// Split the secret
|
|
33
|
-
var splitShares = bsv.Shamir.split(secret, threshold, shares)
|
|
34
|
-
console.log('✓ Successfully split secret into', splitShares.length, 'shares')
|
|
35
|
-
|
|
36
|
-
// Reconstruct with minimum shares
|
|
37
|
-
var reconstructed = bsv.Shamir.combine(splitShares.slice(0, threshold))
|
|
38
|
-
var reconstructedSecret = reconstructed.toString('utf8')
|
|
39
|
-
|
|
40
|
-
console.log('Reconstructed:', reconstructedSecret)
|
|
41
|
-
|
|
42
|
-
if (reconstructedSecret === secret) {
|
|
43
|
-
console.log('✓ Test 1 PASSED: Secret correctly reconstructed')
|
|
44
|
-
} else {
|
|
45
|
-
console.log('✗ Test 1 FAILED: Secret reconstruction failed')
|
|
46
|
-
}
|
|
47
|
-
} catch (e) {
|
|
48
|
-
console.log('✗ Test 1 ERROR:', e.message)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Test 2: Larger secret test
|
|
52
|
-
console.log('\n--- Test 2: Large Secret Test ---')
|
|
53
|
-
try {
|
|
54
|
-
var largeSecret = 'This is a much longer secret that will test the chunking functionality of the Shamir Secret Sharing implementation. It should handle secrets of arbitrary length by breaking them into manageable chunks and processing each chunk separately.'
|
|
55
|
-
var threshold2 = 4
|
|
56
|
-
var shares2 = 7
|
|
57
|
-
|
|
58
|
-
console.log('Large secret length:', largeSecret.length, 'characters')
|
|
59
|
-
|
|
60
|
-
var splitShares2 = bsv.Shamir.split(largeSecret, threshold2, shares2)
|
|
61
|
-
console.log('✓ Successfully split large secret')
|
|
62
|
-
|
|
63
|
-
var reconstructed2 = bsv.Shamir.combine(splitShares2.slice(0, threshold2))
|
|
64
|
-
var reconstructedSecret2 = reconstructed2.toString('utf8')
|
|
65
|
-
|
|
66
|
-
if (reconstructedSecret2 === largeSecret) {
|
|
67
|
-
console.log('✓ Test 2 PASSED: Large secret correctly reconstructed')
|
|
68
|
-
} else {
|
|
69
|
-
console.log('✗ Test 2 FAILED: Large secret reconstruction failed')
|
|
70
|
-
console.log('Expected length:', largeSecret.length)
|
|
71
|
-
console.log('Actual length:', reconstructedSecret2.length)
|
|
72
|
-
console.log('First 50 chars expected:', largeSecret.substring(0, 50))
|
|
73
|
-
console.log('First 50 chars actual :', reconstructedSecret2.substring(0, 50))
|
|
74
|
-
console.log('Match:', largeSecret === reconstructedSecret2)
|
|
75
|
-
}
|
|
76
|
-
} catch (e) {
|
|
77
|
-
console.log('✗ Test 2 ERROR:', e.message)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Test 3: Different share combinations
|
|
81
|
-
console.log('\n--- Test 3: Share Combination Test ---')
|
|
82
|
-
try {
|
|
83
|
-
var secret3 = 'Testing different combinations'
|
|
84
|
-
var splitShares3 = bsv.Shamir.split(secret3, 3, 6)
|
|
85
|
-
|
|
86
|
-
// Test different combinations of 3 shares
|
|
87
|
-
var combinations = [
|
|
88
|
-
[0, 1, 2], // First three
|
|
89
|
-
[1, 3, 5], // Every other
|
|
90
|
-
[2, 4, 5] // Last three + one
|
|
91
|
-
]
|
|
92
|
-
|
|
93
|
-
var allPassed = true
|
|
94
|
-
for (var i = 0; i < combinations.length; i++) {
|
|
95
|
-
var combo = combinations[i]
|
|
96
|
-
var testShares = combo.map(function(idx) { return splitShares3[idx] })
|
|
97
|
-
var reconstructed3 = bsv.Shamir.combine(testShares)
|
|
98
|
-
var result = reconstructed3.toString('utf8')
|
|
99
|
-
|
|
100
|
-
if (result === secret3) {
|
|
101
|
-
console.log('✓ Combination', combo, 'successful')
|
|
102
|
-
} else {
|
|
103
|
-
console.log('✗ Combination', combo, 'failed')
|
|
104
|
-
allPassed = false
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
if (allPassed) {
|
|
109
|
-
console.log('✓ Test 3 PASSED: All share combinations work')
|
|
110
|
-
} else {
|
|
111
|
-
console.log('✗ Test 3 FAILED: Some combinations failed')
|
|
112
|
-
}
|
|
113
|
-
} catch (e) {
|
|
114
|
-
console.log('✗ Test 3 ERROR:', e.message)
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Test 4: Share verification
|
|
118
|
-
console.log('\n--- Test 4: Share Verification Test ---')
|
|
119
|
-
try {
|
|
120
|
-
var secret4 = 'Verification test'
|
|
121
|
-
var splitShares4 = bsv.Shamir.split(secret4, 2, 4)
|
|
122
|
-
|
|
123
|
-
var validCount = 0
|
|
124
|
-
for (var j = 0; j < splitShares4.length; j++) {
|
|
125
|
-
if (bsv.Shamir.verifyShare(splitShares4[j])) {
|
|
126
|
-
validCount++
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (validCount === splitShares4.length) {
|
|
131
|
-
console.log('✓ Test 4 PASSED: All shares verified as valid')
|
|
132
|
-
} else {
|
|
133
|
-
console.log('✗ Test 4 FAILED: Only', validCount, 'of', splitShares4.length, 'shares valid')
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Test invalid share
|
|
137
|
-
var invalidShare = { invalid: 'data' }
|
|
138
|
-
if (!bsv.Shamir.verifyShare(invalidShare)) {
|
|
139
|
-
console.log('✓ Invalid share correctly rejected')
|
|
140
|
-
} else {
|
|
141
|
-
console.log('✗ Invalid share incorrectly accepted')
|
|
142
|
-
}
|
|
143
|
-
} catch (e) {
|
|
144
|
-
console.log('✗ Test 4 ERROR:', e.message)
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Test 5: Error handling
|
|
148
|
-
console.log('\n--- Test 5: Error Handling Test ---')
|
|
149
|
-
try {
|
|
150
|
-
var errorTests = [
|
|
151
|
-
function() { bsv.Shamir.split('', 2, 3) }, // Empty secret
|
|
152
|
-
function() { bsv.Shamir.split('secret', 1, 3) }, // Threshold too low
|
|
153
|
-
function() { bsv.Shamir.split('secret', 3, 2) }, // More threshold than shares
|
|
154
|
-
function() { bsv.Shamir.combine([]) }, // Empty shares array
|
|
155
|
-
function() { bsv.Shamir.combine([{id: 1, threshold: 2, shares: 3, length: 1, bytes: []}]) } // Insufficient shares
|
|
156
|
-
]
|
|
157
|
-
|
|
158
|
-
var errorsPassed = 0
|
|
159
|
-
for (var k = 0; k < errorTests.length; k++) {
|
|
160
|
-
try {
|
|
161
|
-
errorTests[k]()
|
|
162
|
-
console.log('✗ Error test', k + 1, 'should have thrown an error')
|
|
163
|
-
} catch (e) {
|
|
164
|
-
console.log('✓ Error test', k + 1, 'correctly threw:', e.message)
|
|
165
|
-
errorsPassed++
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
if (errorsPassed === errorTests.length) {
|
|
170
|
-
console.log('✓ Test 5 PASSED: All error conditions handled correctly')
|
|
171
|
-
} else {
|
|
172
|
-
console.log('✗ Test 5 FAILED: Some error conditions not handled')
|
|
173
|
-
}
|
|
174
|
-
} catch (e) {
|
|
175
|
-
console.log('✗ Test 5 ERROR:', e.message)
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// Test 6: Binary data test
|
|
179
|
-
console.log('\n--- Test 6: Binary Data Test ---')
|
|
180
|
-
try {
|
|
181
|
-
var binaryData = Buffer.from([0x00, 0x01, 0x02, 0xFF, 0xFE, 0xFD, 0x80, 0x7F])
|
|
182
|
-
var splitBinary = bsv.Shamir.split(binaryData, 2, 3)
|
|
183
|
-
var reconstructedBinary = bsv.Shamir.combine(splitBinary.slice(0, 2))
|
|
184
|
-
|
|
185
|
-
if (Buffer.compare(binaryData, reconstructedBinary) === 0) {
|
|
186
|
-
console.log('✓ Test 6 PASSED: Binary data correctly handled')
|
|
187
|
-
} else {
|
|
188
|
-
console.log('✗ Test 6 FAILED: Binary data reconstruction failed')
|
|
189
|
-
console.log('Original:', Array.from(binaryData))
|
|
190
|
-
console.log('Reconstructed:', Array.from(reconstructedBinary))
|
|
191
|
-
}
|
|
192
|
-
} catch (e) {
|
|
193
|
-
console.log('✗ Test 6 ERROR:', e.message)
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// Test 7: Generate test vectors
|
|
197
|
-
console.log('\n--- Test 7: Test Vectors Generation ---')
|
|
198
|
-
try {
|
|
199
|
-
var testVectors = bsv.Shamir.generateTestVectors()
|
|
200
|
-
|
|
201
|
-
console.log('Test vectors generated:')
|
|
202
|
-
console.log('- Secret:', testVectors.secret)
|
|
203
|
-
console.log('- Threshold:', testVectors.threshold)
|
|
204
|
-
console.log('- Total shares:', testVectors.totalShares)
|
|
205
|
-
console.log('- Shares generated:', testVectors.shares.length)
|
|
206
|
-
console.log('- Reconstruction successful:', testVectors.valid)
|
|
207
|
-
|
|
208
|
-
if (testVectors.valid) {
|
|
209
|
-
console.log('✓ Test 7 PASSED: Test vectors generated and validated')
|
|
210
|
-
} else {
|
|
211
|
-
console.log('✗ Test 7 FAILED: Test vectors validation failed')
|
|
212
|
-
}
|
|
213
|
-
} catch (e) {
|
|
214
|
-
console.log('✗ Test 7 ERROR:', e.message)
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
console.log('\n=== Shamir Secret Sharing Tests Complete ===')
|
|
218
|
-
console.log('💡 Integration successful! Shamir Secret Sharing is now available in:')
|
|
219
|
-
console.log(' • Main library: bsv.Shamir or bsv.crypto.Shamir')
|
|
220
|
-
console.log(' • Standalone: bsv-shamir.min.js (after build)')
|
|
221
|
-
console.log(' • CDN ready: Use npm run build-shamir to generate minified version')
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Test SmartVerify DER Buffer Handling
|
|
5
|
-
*
|
|
6
|
-
* Tests SmartVerify with different input types to isolate the DER parsing issue
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const bsv = require('./index.js');
|
|
10
|
-
|
|
11
|
-
console.log('🔍 Test SmartVerify DER Buffer Handling');
|
|
12
|
-
console.log('=======================================\n');
|
|
13
|
-
|
|
14
|
-
// Simple signature test like minimal reproduction
|
|
15
|
-
const privateKey = new bsv.PrivateKey('L1aW4aubDFB7yfras2S1mN3bqg9nwySY8nkoLmJebSLD5BWv3ENZ');
|
|
16
|
-
const publicKey = privateKey.publicKey;
|
|
17
|
-
const message = Buffer.from('hello world', 'utf8');
|
|
18
|
-
const hash = bsv.crypto.Hash.sha256(message);
|
|
19
|
-
|
|
20
|
-
console.log('Creating signature...');
|
|
21
|
-
const signature = bsv.crypto.ECDSA.sign(hash, privateKey);
|
|
22
|
-
const derSig = signature.toDER();
|
|
23
|
-
|
|
24
|
-
console.log(`Original signature r: ${signature.r.toString('hex')}`);
|
|
25
|
-
console.log(`Original signature s: ${signature.s.toString('hex')}`);
|
|
26
|
-
console.log(`DER buffer: ${derSig.toString('hex')}`);
|
|
27
|
-
console.log(`DER length: ${derSig.length}`);
|
|
28
|
-
|
|
29
|
-
console.log('\n🧪 SmartVerify Test Matrix:');
|
|
30
|
-
console.log('===========================');
|
|
31
|
-
|
|
32
|
-
// Test 1: Signature object
|
|
33
|
-
const smartVerifyObj = bsv.SmartVerify.smartVerify(hash, signature, publicKey);
|
|
34
|
-
console.log(`SmartVerify(hash, sigObject, pubkey): ${smartVerifyObj ? '✅ VALID' : '❌ INVALID'}`);
|
|
35
|
-
|
|
36
|
-
// Test 2: DER buffer
|
|
37
|
-
const smartVerifyBuffer = bsv.SmartVerify.smartVerify(hash, derSig, publicKey);
|
|
38
|
-
console.log(`SmartVerify(hash, derBuffer, pubkey): ${smartVerifyBuffer ? '✅ VALID' : '❌ INVALID'}`);
|
|
39
|
-
|
|
40
|
-
// Test 3: Manually parsed DER
|
|
41
|
-
try {
|
|
42
|
-
const parsedFromDER = bsv.crypto.Signature.fromDER(derSig);
|
|
43
|
-
console.log(`Parsed from DER r: ${parsedFromDER.r.toString('hex')}`);
|
|
44
|
-
console.log(`Parsed from DER s: ${parsedFromDER.s.toString('hex')}`);
|
|
45
|
-
|
|
46
|
-
const smartVerifyParsed = bsv.SmartVerify.smartVerify(hash, parsedFromDER, publicKey);
|
|
47
|
-
console.log(`SmartVerify(hash, parsedSig, pubkey): ${smartVerifyParsed ? '✅ VALID' : '❌ INVALID'}`);
|
|
48
|
-
|
|
49
|
-
console.log('\n🔍 Compare r,s values:');
|
|
50
|
-
console.log('======================');
|
|
51
|
-
console.log(`Original r: ${signature.r.toString('hex')}`);
|
|
52
|
-
console.log(`Parsed r : ${parsedFromDER.r.toString('hex')}`);
|
|
53
|
-
console.log(`r matches : ${signature.r.eq(parsedFromDER.r) ? '✅ YES' : '❌ NO'}`);
|
|
54
|
-
|
|
55
|
-
console.log(`Original s: ${signature.s.toString('hex')}`);
|
|
56
|
-
console.log(`Parsed s : ${parsedFromDER.s.toString('hex')}`);
|
|
57
|
-
console.log(`s matches : ${signature.s.eq(parsedFromDER.s) ? '✅ YES' : '❌ NO'}`);
|
|
58
|
-
|
|
59
|
-
} catch (error) {
|
|
60
|
-
console.log(`❌ DER parsing failed: ${error.message}`);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
console.log('\n🔧 Debug SmartVerify DER Parsing:');
|
|
64
|
-
console.log('==================================');
|
|
65
|
-
|
|
66
|
-
// Let's manually step through what SmartVerify does with DER buffers
|
|
67
|
-
try {
|
|
68
|
-
console.log('Step 1: Input validation...');
|
|
69
|
-
console.log(` Hash is Buffer: ${Buffer.isBuffer(hash)}`);
|
|
70
|
-
console.log(` Hash length: ${hash.length}`);
|
|
71
|
-
console.log(` DER is Buffer: ${Buffer.isBuffer(derSig)}`);
|
|
72
|
-
|
|
73
|
-
console.log('Step 2: DER parsing in SmartVerify...');
|
|
74
|
-
|
|
75
|
-
// This replicates what SmartVerify does internally
|
|
76
|
-
const Signature = bsv.crypto.Signature;
|
|
77
|
-
const testParsed = Signature.fromDER(derSig);
|
|
78
|
-
console.log(` Parsed successfully: ✅`);
|
|
79
|
-
console.log(` Parsed r: ${testParsed.r.toString('hex')}`);
|
|
80
|
-
console.log(` Parsed s: ${testParsed.s.toString('hex')}`);
|
|
81
|
-
|
|
82
|
-
const BN = bsv.crypto.BN;
|
|
83
|
-
const r = BN.isBN(testParsed.r) ? testParsed.r : new BN(testParsed.r);
|
|
84
|
-
const s = BN.isBN(testParsed.s) ? testParsed.s : new BN(testParsed.s);
|
|
85
|
-
console.log(` r as BN: ${r.toString('hex')}`);
|
|
86
|
-
console.log(` s as BN: ${s.toString('hex')}`);
|
|
87
|
-
|
|
88
|
-
// Check canonicalization
|
|
89
|
-
const Point = bsv.crypto.Point;
|
|
90
|
-
const n = Point.getN();
|
|
91
|
-
const nh = n.shrn(1);
|
|
92
|
-
console.log(` s > n/2: ${s.gt(nh)}`);
|
|
93
|
-
|
|
94
|
-
const canonicalS = s.gt(nh) ? n.sub(s) : s;
|
|
95
|
-
console.log(` canonical s: ${canonicalS.toString('hex')}`);
|
|
96
|
-
|
|
97
|
-
// Test final ECDSA call
|
|
98
|
-
const canonicalSig = new Signature({
|
|
99
|
-
r: r,
|
|
100
|
-
s: canonicalS
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
const ECDSA = bsv.crypto.ECDSA;
|
|
104
|
-
const finalResult = ECDSA.verify(hash, canonicalSig, publicKey, 'little');
|
|
105
|
-
console.log(` Final ECDSA result: ${finalResult ? '✅ VALID' : '❌ INVALID'}`);
|
|
106
|
-
|
|
107
|
-
} catch (error) {
|
|
108
|
-
console.log(`❌ Debug failed: ${error.message}`);
|
|
109
|
-
console.log(`Stack: ${error.stack}`);
|
|
110
|
-
}
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
# BIP-143 Preimage Tools
|
|
2
|
-
|
|
3
|
-
This directory contains tools and examples for working with Bitcoin BIP-143 transaction preimages.
|
|
4
|
-
|
|
5
|
-
## Files
|
|
6
|
-
|
|
7
|
-
### `extract_preimage_bidirectional.js`
|
|
8
|
-
**Advanced bidirectional preimage field extractor with optimal ASM generation**
|
|
9
|
-
|
|
10
|
-
Intelligently extracts any BIP-143 preimage field using the most efficient strategy:
|
|
11
|
-
- **LEFT extraction** for early fields (nVersion, hashPrevouts, etc.)
|
|
12
|
-
- **RIGHT extraction** for late fields (value, nLocktime, sighashType, etc.)
|
|
13
|
-
- **DYNAMIC extraction** for variable-length scriptCode
|
|
14
|
-
|
|
15
|
-
#### Features
|
|
16
|
-
- ✅ Complete BIP-143 specification compliance
|
|
17
|
-
- ✅ Optimal operation count for each field
|
|
18
|
-
- ✅ Generates production-ready Bitcoin Script ASM
|
|
19
|
-
- ✅ Handles variable scriptCode dynamically
|
|
20
|
-
- ✅ Robust error handling and validation
|
|
21
|
-
- ✅ Field interpretation (satoshis, version numbers, etc.)
|
|
22
|
-
|
|
23
|
-
#### Usage
|
|
24
|
-
```bash
|
|
25
|
-
# Extract any preimage field
|
|
26
|
-
node extract_preimage_bidirectional.js <preimage_hex> <field_name>
|
|
27
|
-
|
|
28
|
-
# Examples
|
|
29
|
-
node extract_preimage_bidirectional.js 01000000ab12cd... scriptCode
|
|
30
|
-
node extract_preimage_bidirectional.js 01000000ab12cd... value
|
|
31
|
-
node extract_preimage_bidirectional.js 01000000ab12cd... sighashType
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
#### Available Fields
|
|
35
|
-
|
|
36
|
-
**LEFT Fields (fixed offsets from start):**
|
|
37
|
-
- `nVersion` (4 bytes) - Transaction version
|
|
38
|
-
- `hashPrevouts` (32 bytes) - Hash of all input outpoints
|
|
39
|
-
- `hashSequence` (32 bytes) - Hash of all input sequences
|
|
40
|
-
- `outpoint_txid` (32 bytes) - Current input's previous transaction ID
|
|
41
|
-
- `outpoint_vout` (4 bytes) - Current input's previous output index
|
|
42
|
-
- `scriptLen` (1 byte) - Length of the scriptCode
|
|
43
|
-
|
|
44
|
-
**DYNAMIC Field (uses internal length):**
|
|
45
|
-
- `scriptCode` (variable) - The script being executed
|
|
46
|
-
|
|
47
|
-
**RIGHT Fields (fixed offsets from end):**
|
|
48
|
-
- `value` (8 bytes) - Input amount in satoshis
|
|
49
|
-
- `nSequence` (4 bytes) - Current input's sequence number
|
|
50
|
-
- `hashOutputs` (32 bytes) - Hash of all outputs
|
|
51
|
-
- `nLocktime` (4 bytes) - Transaction lock time
|
|
52
|
-
- `sighashType` (4 bytes) - Signature hash type
|
|
53
|
-
|
|
54
|
-
#### Integration with Covenant Framework
|
|
55
|
-
|
|
56
|
-
The generated ASM can be used directly in covenant locking scripts:
|
|
57
|
-
|
|
58
|
-
```javascript
|
|
59
|
-
const { CovenantInterface } = require('../../lib/covenant-interface');
|
|
60
|
-
|
|
61
|
-
// Use bidirectional extraction in covenant
|
|
62
|
-
const covenant = new CovenantInterface();
|
|
63
|
-
const script = covenant.createAdvancedCovenant({
|
|
64
|
-
type: 'custom',
|
|
65
|
-
rules: {
|
|
66
|
-
// Insert generated ASM for preimage field extraction
|
|
67
|
-
extractValue: `
|
|
68
|
-
# Generated by extract_preimage_bidirectional.js
|
|
69
|
-
OP_SIZE
|
|
70
|
-
52 OP_SUB
|
|
71
|
-
OP_SPLIT
|
|
72
|
-
OP_DROP
|
|
73
|
-
8 OP_SPLIT
|
|
74
|
-
OP_DROP
|
|
75
|
-
`
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
#### BIP-143 Structure Reference
|
|
81
|
-
|
|
82
|
-
```
|
|
83
|
-
Total: LEFT(105) + scriptCode(variable) + RIGHT(52) bytes
|
|
84
|
-
|
|
85
|
-
LEFT ZONE (105 bytes): DYNAMIC: RIGHT ZONE (52 bytes):
|
|
86
|
-
├─ nVersion (4) ├─ scriptCode ├─ value (8)
|
|
87
|
-
├─ hashPrevouts (32) └─ (scriptLen bytes) ├─ nSequence (4)
|
|
88
|
-
├─ hashSequence (32) ├─ hashOutputs (32)
|
|
89
|
-
├─ outpoint_txid (32) ├─ nLocktime (4)
|
|
90
|
-
├─ outpoint_vout (4) └─ sighashType (4)
|
|
91
|
-
└─ scriptLen (1)
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
## See Also
|
|
95
|
-
- `../../docs/preimage.md` - BIP-143 technical specification
|
|
96
|
-
- `../../docs/ADVANCED_COVENANT_DEVELOPMENT.md` - Covenant implementation guide
|
|
97
|
-
- `../covenants/` - Complete covenant examples using preimage extraction
|
|
98
|
-
- `../../lib/covenant-interface.js` - CovenantPreimage class implementation
|
|
99
|
-
|
|
100
|
-
### `generate_sighash_examples.js`
|
|
101
|
-
**SIGHASH flag preimage generator demonstrating "zero hash" behavior**
|
|
102
|
-
|
|
103
|
-
Explains why multi-input transactions appear to have "extra zeros" - they're not bugs but required by BIP-143 SIGHASH rules:
|
|
104
|
-
|
|
105
|
-
#### Features
|
|
106
|
-
- ✅ Complete SIGHASH flag support (ALL, NONE, SINGLE, ANYONECANPAY)
|
|
107
|
-
- ✅ Demonstrates zero hash field behavior
|
|
108
|
-
- ✅ Educational tool for multi-input transaction analysis
|
|
109
|
-
- ✅ Integration with bidirectional extractor
|
|
110
|
-
|
|
111
|
-
#### Usage
|
|
112
|
-
```bash
|
|
113
|
-
# Generate SIGHASH examples
|
|
114
|
-
node generate_sighash_examples.js [sighash_type]
|
|
115
|
-
|
|
116
|
-
# Examples showing zero hash behavior
|
|
117
|
-
node generate_sighash_examples.js ALL_ANYONECANPAY_FORKID # Zero hashPrevouts + hashSequence
|
|
118
|
-
node generate_sighash_examples.js NONE_FORKID # Zero hashOutputs
|
|
119
|
-
node generate_sighash_examples.js NONE_ANYONECANPAY_FORKID # Zero all hash fields
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
#### SIGHASH Flag Behavior
|
|
123
|
-
| SIGHASH Type | hashPrevouts | hashSequence | hashOutputs | Use Case |
|
|
124
|
-
|--------------|-------------|-------------|-------------|-----------|
|
|
125
|
-
| ALL_FORKID | Normal | Normal | Normal | Standard signing |
|
|
126
|
-
| NONE_FORKID | Normal | Normal | **Zero** | Blank check |
|
|
127
|
-
| SINGLE_FORKID | Normal | Normal | **Zero** | One-to-one |
|
|
128
|
-
| ALL_ANYONECANPAY_FORKID | **Zero** | **Zero** | Normal | Crowdfunding |
|
|
129
|
-
| NONE_ANYONECANPAY_FORKID | **Zero** | **Zero** | **Zero** | Maximum flexibility |
|
|
130
|
-
|
|
131
|
-
### `test_varint_extraction.js`
|
|
132
|
-
**Comprehensive CompactSize varint test suite**
|
|
133
|
-
|
|
134
|
-
Validates proper parsing of 1-3 byte CompactSize varints in real-world scenarios:
|
|
135
|
-
- 1-byte encoding: 0-252 bytes (most common)
|
|
136
|
-
- 3-byte encoding: 253-65535 bytes (large scripts)
|
|
137
|
-
- 5-byte encoding: 65536+ bytes (huge scripts)
|
|
138
|
-
|
|
139
|
-
## 🧠 **Understanding the "Extra Zero" Mystery**
|
|
140
|
-
|
|
141
|
-
### The Problem
|
|
142
|
-
Developers often see patterns like this in BSV preimages and think it's a bug:
|
|
143
|
-
```
|
|
144
|
-
...1976a914000000000000...
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
### The Reality
|
|
148
|
-
These zeros are **intentional** and required by Bitcoin's BIP-143 specification:
|
|
149
|
-
|
|
150
|
-
1. **CompactSize Varint Encoding**
|
|
151
|
-
- Scripts ≥253 bytes use 3-byte encoding: `0xFD + 2-byte length`
|
|
152
|
-
- This adds "extra bytes" that look like zeros to developers expecting 1-byte
|
|
153
|
-
|
|
154
|
-
2. **SIGHASH Flag Behavior**
|
|
155
|
-
- `ANYONECANPAY`: Zeros out `hashPrevouts` and `hashSequence` (64 zero bytes)
|
|
156
|
-
- `NONE`: Zeros out `hashOutputs` (32 zero bytes)
|
|
157
|
-
- `SINGLE`: Zeros out `hashOutputs` for unmatched outputs
|
|
158
|
-
|
|
159
|
-
3. **Multi-Input Concatenation Issues**
|
|
160
|
-
- Wrong byte boundary slicing between inputs
|
|
161
|
-
- Reusing preimage buffers without proper re-serialization
|
|
162
|
-
|
|
163
|
-
### The Solution
|
|
164
|
-
Our bidirectional extractor handles all these cases:
|
|
165
|
-
- ✅ **Auto-detects** CompactSize varint size (1-3 bytes)
|
|
166
|
-
- ✅ **Warns about** zero hashes with SIGHASH flag context
|
|
167
|
-
- ✅ **Validates** preimage structure against BIP-143
|
|
168
|
-
- ✅ **Generates** optimal ASM regardless of complexity
|
|
169
|
-
|
|
170
|
-
## Performance Notes
|
|
171
|
-
|
|
172
|
-
The enhanced bidirectional strategy minimizes script operations:
|
|
173
|
-
- **LEFT fields**: Direct offset splitting (2-3 operations)
|
|
174
|
-
- **RIGHT fields**: Size-based splitting (3-4 operations)
|
|
175
|
-
- **scriptCode**: Dynamic extraction using CompactSize varint (3-4 operations)
|
|
176
|
-
- **Zero hash detection**: Automatic with contextual warnings
|
|
177
|
-
|
|
178
|
-
This is significantly more efficient than linear parsing and handles all BIP-143 edge cases that break traditional parsers.
|