@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.
Files changed (118) hide show
  1. package/CHANGELOG.md +220 -79
  2. package/README.md +283 -71
  3. package/bsv-covenant.min.js +26 -3
  4. package/bsv-gdaf.min.js +11 -9
  5. package/bsv-ltp.min.js +10 -8
  6. package/bsv-mnemonic.min.js +4 -4
  7. package/bsv-script-helper.min.js +2 -2
  8. package/bsv-security.min.js +3 -24
  9. package/bsv-shamir.min.js +2 -2
  10. package/bsv-smartcontract.min.js +10 -8
  11. package/bsv.bundle.js +9 -9
  12. package/bsv.min.js +10 -8
  13. package/build/webpack.bundle.config.js +2 -2
  14. package/build/webpack.config.js +2 -2
  15. package/build/webpack.covenant.config.js +2 -2
  16. package/build/webpack.gdaf.config.js +6 -43
  17. package/build/webpack.script-helper.config.js +2 -2
  18. package/build/webpack.security.config.js +2 -2
  19. package/build/webpack.smartcontract.config.js +2 -2
  20. package/bundle-entry.js +1 -341
  21. package/covenant-entry.js +1 -44
  22. package/demos/README.md +188 -0
  23. package/{architecture_demo.js → demos/architecture_demo.js} +2 -2
  24. package/demos/bsv_wallet_demo.js +242 -0
  25. package/{complete_ltp_demo.js → demos/complete_ltp_demo.js} +1 -1
  26. package/demos/debug_tools_demo.js +87 -0
  27. package/demos/demo_features.js +123 -0
  28. package/demos/easy_interface_demo.js +109 -0
  29. package/demos/ecies_demo.js +182 -0
  30. package/demos/gdaf_core_test.js +131 -0
  31. package/demos/gdaf_demo.js +237 -0
  32. package/demos/ltp_demo.js +361 -0
  33. package/demos/ltp_primitives_demo.js +403 -0
  34. package/demos/message_demo.js +209 -0
  35. package/demos/preimage_separation_demo.js +383 -0
  36. package/demos/script_helper_demo.js +289 -0
  37. package/demos/security_demo.js +287 -0
  38. package/{shamir_demo.js → demos/shamir_demo.js} +1 -1
  39. package/{simple_demo.js → demos/simple_demo.js} +1 -1
  40. package/demos/simple_p2pkh_demo.js +169 -0
  41. package/demos/simple_utxo_preimage_demo.js +196 -0
  42. package/demos/smart_contract_demo.html +1347 -0
  43. package/demos/smart_contract_demo.js +910 -0
  44. package/demos/utxo_generator_demo.js +244 -0
  45. package/demos/validation_pipeline_demo.js +155 -0
  46. package/demos/web3keys.html +740 -0
  47. package/docs/BUNDLE_UPDATE_SUMMARY.md +40 -0
  48. package/docs/DOCUMENTATION_REVIEW_REPORT.md +295 -0
  49. package/docs/FIX_CREATEHMAC_ISSUE.md +91 -0
  50. package/docs/MODULE_REFERENCE_COMPLETE.md +330 -0
  51. package/docs/README.md +107 -79
  52. package/docs/SMARTLEDGER_BSV_USAGE_ANSWERS.md +477 -0
  53. package/docs/SMARTLEDGER_BSV_USAGE_EXAMPLES.js +372 -0
  54. package/docs/SMARTLEDGER_BSV_USAGE_GUIDE.md +555 -0
  55. package/docs/SMART_CONTRACT_DEVELOPMENT_GUIDE.md +1459 -0
  56. package/docs/advanced/LEGAL_TOKEN_PROTOCOL.md +411 -0
  57. package/docs/advanced/SMART_CONTRACT_GUIDE.md +1255 -0
  58. package/docs/advanced/UTXO_MANAGER_GUIDE.md +851 -0
  59. package/docs/api/LTP.md +334 -0
  60. package/docs/getting-started/INSTALLATION.md +410 -0
  61. package/docs/getting-started/QUICK_START.md +180 -0
  62. package/docs/migration/FROM_BSV_1_5_6.md +260 -0
  63. package/docs/technical/GDAF_DEVELOPER_INTERFACE.md +187 -0
  64. package/docs/technical/GDAF_IMPLEMENTATION_COMPLETE.md +190 -0
  65. package/docs/technical/SHAMIR_INTEGRATION_SUMMARY.md +165 -0
  66. package/docs/technical/roadmap.md +1250 -0
  67. package/docs/technical/trust_law.md +142 -0
  68. package/examples/complete_workflow_demo.js +783 -0
  69. package/examples/definitive_working_demo.js +261 -0
  70. package/examples/final_working_contracts.js +338 -0
  71. package/examples/smart_contract_templates.js +718 -0
  72. package/examples/working_smart_contracts.js +348 -0
  73. package/gdaf-entry.js +2 -54
  74. package/index.js +32 -0
  75. package/lib/mnemonic/pbkdf2.browser.js +69 -0
  76. package/lib/mnemonic/pbkdf2.js +2 -68
  77. package/lib/mnemonic/pbkdf2.node.js +68 -0
  78. package/ltp-entry.js +2 -92
  79. package/package.json +21 -8
  80. package/script-helper-entry.js +1 -49
  81. package/security-entry.js +1 -70
  82. package/shamir-entry.js +1 -173
  83. package/smartcontract-entry.js +1 -133
  84. package/tests/browser-compatibility/README.md +35 -0
  85. package/tests/browser-compatibility/test-cdn-vs-local.html +186 -0
  86. package/tests/browser-compatibility/test-pbkdf2.html +51 -0
  87. package/tests/test_builtin_verify.js +117 -0
  88. package/tests/test_debug_integration.js +71 -0
  89. package/tests/test_ecdsa_little.js +70 -0
  90. package/tests/test_smartverify_der.js +110 -0
  91. package/utilities/blockchain-state.js +155 -155
  92. package/utilities/blockchain-state.json +103293 -5244
  93. package/utilities/miner-simulator.js +354 -358
  94. package/utilities/mock-utxo-generator.js +54 -54
  95. package/utilities/raw-tx-examples.js +120 -122
  96. package/utilities/success-demo.js +104 -105
  97. package/utilities/transaction-examples.js +188 -188
  98. package/utilities/utxo-manager.js +91 -91
  99. package/utilities/wallet-setup.js +79 -80
  100. package/utilities/working-signature-demo.js +108 -110
  101. package/SECURITY.md +0 -75
  102. package/build/bsv-covenant.min.js +0 -10
  103. package/build/bsv-script-helper.min.js +0 -10
  104. package/build/bsv-security.min.js +0 -31
  105. package/build/bsv-smartcontract.min.js +0 -39
  106. package/build/bsv.bundle.js +0 -39
  107. package/build/bsv.min.js +0 -39
  108. package/validation_test.js +0 -97
  109. /package/docs/{ADVANCED_COVENANT_DEVELOPMENT.md → advanced/ADVANCED_COVENANT_DEVELOPMENT.md} +0 -0
  110. /package/docs/{CUSTOM_SCRIPT_DEVELOPMENT.md → advanced/CUSTOM_SCRIPT_DEVELOPMENT.md} +0 -0
  111. /package/docs/{block.md → api/BLOCKS.md} +0 -0
  112. /package/docs/{ecies.md → api/ECIES.md} +0 -0
  113. /package/docs/{networks.md → api/NETWORKS.md} +0 -0
  114. /package/docs/{script.md → api/SCRIPTS.md} +0 -0
  115. /package/docs/{transaction.md → api/TRANSACTIONS.md} +0 -0
  116. /package/docs/{unspentoutput.md → api/UTXO.md} +0 -0
  117. /package/{test_shamir.js → tests/test_shamir.js} +0 -0
  118. /package/{test_standalone_shamir.html → tests/test_standalone_shamir.html} +0 -0
@@ -2,7 +2,7 @@
2
2
 
3
3
  /**
4
4
  * ⛏️ BSV Miner Simulator
5
- *
5
+ *
6
6
  * Simulates blockchain miner functionality:
7
7
  * - Accepts broadcast transactions
8
8
  * - Validates against UTXO set
@@ -11,451 +11,448 @@
11
11
  * - Mines blocks (simplified)
12
12
  */
13
13
 
14
- const bsv = require('../index.js');
15
- const fs = require('fs');
16
- const path = require('path');
14
+ const bsv = require('../index.js')
15
+ // const fs = require('fs') // Currently unused
16
+ // const path = require('path') // Currently unused
17
17
  const {
18
18
  loadBlockchainState,
19
19
  saveBlockchainState,
20
20
  getUTXO,
21
- isUTXOAvailable,
21
+ // isUTXOAvailable, // Currently unused
22
22
  spendUTXO,
23
23
  addUTXO
24
- } = require('./blockchain-state');
24
+ } = require('./blockchain-state')
25
25
 
26
26
  /**
27
27
  * Transaction validation result
28
28
  */
29
29
  class ValidationResult {
30
- constructor(valid = false, errors = [], warnings = []) {
31
- this.valid = valid;
32
- this.errors = errors;
33
- this.warnings = warnings;
30
+ constructor (valid = false, errors = [], warnings = []) {
31
+ this.valid = valid
32
+ this.errors = errors
33
+ this.warnings = warnings
34
34
  }
35
-
36
- addError(message) {
37
- this.errors.push(message);
38
- this.valid = false;
35
+
36
+ addError (message) {
37
+ this.errors.push(message)
38
+ this.valid = false
39
39
  }
40
-
41
- addWarning(message) {
42
- this.warnings.push(message);
40
+
41
+ addWarning (message) {
42
+ this.warnings.push(message)
43
43
  }
44
44
  }
45
45
 
46
46
  /**
47
47
  * Validate transaction inputs against UTXO set
48
48
  */
49
- function validateTransactionInputs(transaction) {
50
- console.log('🔍 Validating transaction inputs...');
51
-
52
- const result = new ValidationResult(true);
53
- const state = loadBlockchainState();
54
-
49
+ function validateTransactionInputs (transaction) {
50
+ console.log('🔍 Validating transaction inputs...')
51
+
52
+ const result = new ValidationResult(true)
53
+ const state = loadBlockchainState()
54
+
55
55
  // Check each input
56
56
  for (let i = 0; i < transaction.inputs.length; i++) {
57
- const input = transaction.inputs[i];
58
- const prevTxId = input.prevTxId.toString('hex');
59
- const outputIndex = input.outputIndex;
60
-
61
- console.log(` Input ${i}: ${prevTxId}:${outputIndex}`);
62
-
57
+ const input = transaction.inputs[i]
58
+ const prevTxId = input.prevTxId.toString('hex')
59
+ const outputIndex = input.outputIndex
60
+
61
+ console.log(` Input ${i}: ${prevTxId}:${outputIndex}`)
62
+
63
63
  // Check if UTXO exists and is unspent
64
- const utxoResult = getUTXO(prevTxId, outputIndex);
65
-
64
+ const utxoResult = getUTXO(prevTxId, outputIndex)
65
+
66
66
  if (!utxoResult.exists) {
67
- result.addError(`Input ${i}: UTXO ${prevTxId}:${outputIndex} does not exist`);
68
- continue;
67
+ result.addError(`Input ${i}: UTXO ${prevTxId}:${outputIndex} does not exist`)
68
+ continue
69
69
  }
70
-
70
+
71
71
  if (utxoResult.spent) {
72
- result.addError(`Input ${i}: UTXO ${prevTxId}:${outputIndex} already spent in tx ${utxoResult.utxo.spentInTx}`);
73
- continue;
72
+ result.addError(`Input ${i}: UTXO ${prevTxId}:${outputIndex} already spent in tx ${utxoResult.utxo.spentInTx}`)
73
+ continue
74
74
  }
75
-
76
- console.log(` ✅ UTXO exists: ${utxoResult.utxo.satoshis} satoshis`);
75
+
76
+ console.log(` ✅ UTXO exists: ${utxoResult.utxo.satoshis} satoshis`)
77
77
  }
78
-
79
- return result;
78
+
79
+ return result
80
80
  }
81
81
 
82
82
  /**
83
83
  * Validate transaction signatures using BSV script interpreter
84
84
  */
85
- function validateTransactionSignatures(transaction) {
86
- console.log('🔐 Validating transaction signatures with BSV script interpreter...');
87
-
88
- const result = new ValidationResult(true);
89
-
85
+ function validateTransactionSignatures (transaction) {
86
+ console.log('🔐 Validating transaction signatures with BSV script interpreter...')
87
+
88
+ const result = new ValidationResult(true)
89
+
90
90
  try {
91
91
  for (let i = 0; i < transaction.inputs.length; i++) {
92
- const input = transaction.inputs[i];
93
- const prevTxId = input.prevTxId.toString('hex');
94
- const outputIndex = input.outputIndex;
95
-
96
- console.log(` Input ${i}: ${prevTxId}:${outputIndex}`);
97
-
92
+ const input = transaction.inputs[i]
93
+ const prevTxId = input.prevTxId.toString('hex')
94
+ const outputIndex = input.outputIndex
95
+
96
+ console.log(` Input ${i}: ${prevTxId}:${outputIndex}`)
97
+
98
98
  // Get the UTXO being spent
99
- const utxoResult = getUTXO(prevTxId, outputIndex);
99
+ const utxoResult = getUTXO(prevTxId, outputIndex)
100
100
  if (!utxoResult.exists) {
101
- result.addError(`Cannot verify signature for non-existent UTXO ${prevTxId}:${outputIndex}`);
102
- continue;
101
+ result.addError(`Cannot verify signature for non-existent UTXO ${prevTxId}:${outputIndex}`)
102
+ continue
103
103
  }
104
-
105
- const utxo = utxoResult.utxo;
106
- const scriptPubKey = bsv.Script.fromHex(utxo.script);
107
- const scriptSig = input.script;
108
-
109
- console.log(` 📜 ScriptPubKey: ${scriptPubKey.toHex()}`);
110
- console.log(` 🔏 ScriptSig: ${scriptSig.toHex()}`);
111
-
112
- // Validate using BSV's built-in transaction verification
104
+
105
+ const utxo = utxoResult.utxo
106
+ const scriptPubKey = bsv.Script.fromHex(utxo.script)
107
+ const scriptSig = input.script
108
+
109
+ console.log(` 📜 ScriptPubKey: ${scriptPubKey.toHex()}`)
110
+ console.log(` 🔏 ScriptSig: ${scriptSig.toHex()}`)
111
+
112
+ // Validate using BSV's built-in transaction verification
113
+ try {
114
+ console.log(' 🔧 Using BSV Transaction.verify() - the gold standard')
115
+
116
+ // Use BSV's own transaction verification - this is what we trust!
117
+ // If the transaction was properly signed, this should pass
118
+ let isValid = false
119
+
113
120
  try {
114
- console.log(' 🔧 Using BSV Transaction.verify() - the gold standard');
115
-
116
- // Use BSV's own transaction verification - this is what we trust!
117
- // If the transaction was properly signed, this should pass
118
- let isValid = false;
119
-
120
- try {
121
- isValid = transaction.verify();
122
- console.log(' 🎯 BSV Transaction.verify() result:', isValid);
123
- } catch (verifyError) {
124
- console.log(' ⚠️ BSV verify() error:', verifyError.message);
125
- // Even if verify() throws, the transaction might still be valid
126
- // Some BSV versions have strict verification that might fail on valid transactions
127
- isValid = true; // Trust that it was properly signed if we got this far
128
- console.log(' 🤷 Defaulting to VALID (transaction was properly constructed)');
129
- }
130
-
121
+ isValid = transaction.verify()
122
+ console.log(' 🎯 BSV Transaction.verify() result:', isValid)
123
+ } catch (verifyError) {
124
+ console.log(' ⚠️ BSV verify() error:', verifyError.message)
125
+ // Even if verify() throws, the transaction might still be valid
126
+ // Some BSV versions have strict verification that might fail on valid transactions
127
+ isValid = true // Trust that it was properly signed if we got this far
128
+ console.log(' 🤷 Defaulting to VALID (transaction was properly constructed)')
129
+ }
130
+
131
131
  if (isValid) {
132
- console.log(` ✅ Script validation PASSED`);
132
+ console.log(` ✅ Script validation PASSED`)
133
133
  } else {
134
- console.log(` ❌ Script validation FAILED`);
135
- result.addError(`Input ${i}: Script validation failed - Invalid signature or script`);
134
+ console.log(` ❌ Script validation FAILED`)
135
+ result.addError(`Input ${i}: Script validation failed - Invalid signature or script`)
136
136
  }
137
-
138
137
  } catch (scriptError) {
139
- console.log(` ❌ Script interpreter error: ${scriptError.message}`);
140
- result.addError(`Input ${i}: Script interpreter error - ${scriptError.message}`);
138
+ console.log(` ❌ Script interpreter error: ${scriptError.message}`)
139
+ result.addError(`Input ${i}: Script interpreter error - ${scriptError.message}`)
141
140
  }
142
141
  }
143
142
  } catch (error) {
144
- result.addError(`Signature validation error: ${error.message}`);
143
+ result.addError(`Signature validation error: ${error.message}`)
145
144
  }
146
-
147
- return result;
145
+
146
+ return result
148
147
  }
149
148
 
150
149
  /**
151
150
  * Validate transaction outputs
152
151
  */
153
- function validateTransactionOutputs(transaction) {
154
- console.log('📤 Validating transaction outputs...');
155
-
156
- const result = new ValidationResult(true);
157
-
152
+ function validateTransactionOutputs (transaction) {
153
+ console.log('📤 Validating transaction outputs...')
154
+
155
+ const result = new ValidationResult(true)
156
+
158
157
  // Check output values are positive
159
158
  for (let i = 0; i < transaction.outputs.length; i++) {
160
- const output = transaction.outputs[i];
161
-
159
+ const output = transaction.outputs[i]
160
+
162
161
  if (output.satoshis <= 0) {
163
- result.addError(`Output ${i}: Invalid amount ${output.satoshis}`);
162
+ result.addError(`Output ${i}: Invalid amount ${output.satoshis}`)
164
163
  }
165
-
164
+
166
165
  if (!output.script) {
167
- result.addError(`Output ${i}: No script provided`);
166
+ result.addError(`Output ${i}: No script provided`)
168
167
  }
169
-
170
- console.log(` Output ${i}: ${output.satoshis} satoshis ✅`);
168
+
169
+ console.log(` Output ${i}: ${output.satoshis} satoshis ✅`)
171
170
  }
172
-
173
- return result;
171
+
172
+ return result
174
173
  }
175
174
 
176
175
  /**
177
176
  * Validate transaction balance (inputs = outputs + fees)
178
177
  */
179
- function validateTransactionBalance(transaction) {
180
- console.log('⚖️ Validating transaction balance...');
181
-
182
- const result = new ValidationResult(true);
183
-
178
+ function validateTransactionBalance (transaction) {
179
+ console.log('⚖️ Validating transaction balance...')
180
+
181
+ const result = new ValidationResult(true)
182
+
184
183
  // Calculate input value
185
- let inputValue = 0;
184
+ let inputValue = 0
186
185
  for (const input of transaction.inputs) {
187
- const prevTxId = input.prevTxId.toString('hex');
188
- const outputIndex = input.outputIndex;
189
- const utxoResult = getUTXO(prevTxId, outputIndex);
190
-
186
+ const prevTxId = input.prevTxId.toString('hex')
187
+ const outputIndex = input.outputIndex
188
+ const utxoResult = getUTXO(prevTxId, outputIndex)
189
+
191
190
  if (utxoResult.exists) {
192
- inputValue += utxoResult.utxo.satoshis;
191
+ inputValue += utxoResult.utxo.satoshis
193
192
  }
194
193
  }
195
-
194
+
196
195
  // Calculate output value
197
- const outputValue = transaction.outputs.reduce((sum, output) => sum + output.satoshis, 0);
198
-
199
- const fee = inputValue - outputValue;
200
-
201
- console.log(` Input value: ${inputValue} satoshis`);
202
- console.log(` Output value: ${outputValue} satoshis`);
203
- console.log(` Transaction fee: ${fee} satoshis`);
204
-
196
+ const outputValue = transaction.outputs.reduce((sum, output) => sum + output.satoshis, 0)
197
+
198
+ const fee = inputValue - outputValue
199
+
200
+ console.log(` Input value: ${inputValue} satoshis`)
201
+ console.log(` Output value: ${outputValue} satoshis`)
202
+ console.log(` Transaction fee: ${fee} satoshis`)
203
+
205
204
  if (fee < 0) {
206
- result.addError(`Invalid transaction: Outputs (${outputValue}) exceed inputs (${inputValue})`);
205
+ result.addError(`Invalid transaction: Outputs (${outputValue}) exceed inputs (${inputValue})`)
207
206
  }
208
-
207
+
209
208
  if (fee > 10000) { // Arbitrary high fee warning
210
- result.addWarning(`High transaction fee: ${fee} satoshis`);
209
+ result.addWarning(`High transaction fee: ${fee} satoshis`)
211
210
  }
212
-
213
- return result;
211
+
212
+ return result
214
213
  }
215
214
 
216
215
  /**
217
216
  * Analyze raw transaction hex and show detailed breakdown
218
217
  */
219
- function analyzeRawTransactionHex(rawHex) {
218
+ function analyzeRawTransactionHex (rawHex) {
220
219
  try {
221
- let offset = 0;
222
-
220
+ let offset = 0
221
+
223
222
  // Version (4 bytes)
224
- const version = rawHex.substr(offset, 8);
225
- offset += 8;
226
- console.log(` 📄 Version: ${version} (${parseInt(version.match(/.{2}/g).reverse().join(''), 16)})`);
227
-
223
+ const version = rawHex.substr(offset, 8)
224
+ offset += 8
225
+ console.log(` 📄 Version: ${version} (${parseInt(version.match(/.{2}/g).reverse().join(''), 16)})`)
226
+
228
227
  // Input count (1+ bytes, varint)
229
- const inputCount = parseInt(rawHex.substr(offset, 2), 16);
230
- offset += 2;
231
- console.log(` 🔢 Input count: ${rawHex.substr(offset-2, 2)} (${inputCount} input${inputCount > 1 ? 's' : ''})`);
232
-
228
+ const inputCount = parseInt(rawHex.substr(offset, 2), 16)
229
+ offset += 2
230
+ console.log(` 🔢 Input count: ${rawHex.substr(offset - 2, 2)} (${inputCount} input${inputCount > 1 ? 's' : ''})`)
231
+
233
232
  // Inputs
234
233
  for (let i = 0; i < inputCount; i++) {
235
- console.log(` \n 📥 Input ${i}:`);
236
-
234
+ console.log(` \n 📥 Input ${i}:`)
235
+
237
236
  // Previous transaction hash (32 bytes)
238
- const prevTxHash = rawHex.substr(offset, 64);
239
- offset += 64;
240
- console.log(` 🔗 Prev TX: ${prevTxHash}`);
241
-
237
+ const prevTxHash = rawHex.substr(offset, 64)
238
+ offset += 64
239
+ console.log(` 🔗 Prev TX: ${prevTxHash}`)
240
+
242
241
  // Output index (4 bytes)
243
- const outputIndex = rawHex.substr(offset, 8);
244
- offset += 8;
245
- console.log(` 📍 Vout: ${outputIndex} (${parseInt(outputIndex.match(/.{2}/g).reverse().join(''), 16)})`);
246
-
242
+ const outputIndex = rawHex.substr(offset, 8)
243
+ offset += 8
244
+ console.log(` 📍 Vout: ${outputIndex} (${parseInt(outputIndex.match(/.{2}/g).reverse().join(''), 16)})`)
245
+
247
246
  // Script length (1+ bytes, varint)
248
- const scriptLen = parseInt(rawHex.substr(offset, 2), 16);
249
- offset += 2;
250
- console.log(` 📏 Script length: ${rawHex.substr(offset-2, 2)} (${scriptLen} bytes)`);
251
-
247
+ const scriptLen = parseInt(rawHex.substr(offset, 2), 16)
248
+ offset += 2
249
+ console.log(` 📏 Script length: ${rawHex.substr(offset - 2, 2)} (${scriptLen} bytes)`)
250
+
252
251
  // Script (scriptLen bytes)
253
- const script = rawHex.substr(offset, scriptLen * 2);
254
- offset += scriptLen * 2;
255
- console.log(` 🔐 Script: ${script}`);
256
-
252
+ const script = rawHex.substr(offset, scriptLen * 2)
253
+ offset += scriptLen * 2
254
+ console.log(` 🔐 Script: ${script}`)
255
+
257
256
  // Parse script components
258
257
  if (script.length > 0) {
259
- let scriptOffset = 0;
260
- console.log(` 🔍 Script breakdown:`);
261
-
258
+ let scriptOffset = 0
259
+ console.log(` 🔍 Script breakdown:`)
260
+
262
261
  // First byte is signature length
263
- const sigLen = parseInt(script.substr(scriptOffset, 2), 16);
264
- scriptOffset += 2;
265
- console.log(` 🖊️ Sig length: ${sigLen} bytes`);
266
-
262
+ const sigLen = parseInt(script.substr(scriptOffset, 2), 16)
263
+ scriptOffset += 2
264
+ console.log(` 🖊️ Sig length: ${sigLen} bytes`)
265
+
267
266
  // Signature
268
- const signature = script.substr(scriptOffset, sigLen * 2);
269
- scriptOffset += sigLen * 2;
270
- console.log(` 🖊️ Signature: ${signature}`);
271
-
267
+ const signature = script.substr(scriptOffset, sigLen * 2)
268
+ scriptOffset += sigLen * 2
269
+ console.log(` 🖊️ Signature: ${signature}`)
270
+
272
271
  // Public key length
273
- const pubKeyLen = parseInt(script.substr(scriptOffset, 2), 16);
274
- scriptOffset += 2;
275
- console.log(` 🔑 PubKey length: ${pubKeyLen} bytes`);
276
-
272
+ const pubKeyLen = parseInt(script.substr(scriptOffset, 2), 16)
273
+ scriptOffset += 2
274
+ console.log(` 🔑 PubKey length: ${pubKeyLen} bytes`)
275
+
277
276
  // Public key
278
- const pubKey = script.substr(scriptOffset, pubKeyLen * 2);
279
- scriptOffset += pubKeyLen * 2;
280
- console.log(` 🔑 Public key: ${pubKey}`);
277
+ const pubKey = script.substr(scriptOffset, pubKeyLen * 2)
278
+ scriptOffset += pubKeyLen * 2
279
+ console.log(` 🔑 Public key: ${pubKey}`)
281
280
  }
282
-
281
+
283
282
  // Sequence (4 bytes)
284
- const sequence = rawHex.substr(offset, 8);
285
- offset += 8;
286
- console.log(` ⏰ Sequence: ${sequence}`);
283
+ const sequence = rawHex.substr(offset, 8)
284
+ offset += 8
285
+ console.log(` ⏰ Sequence: ${sequence}`)
287
286
  }
288
-
287
+
289
288
  // Output count (1+ bytes, varint)
290
- const outputCount = parseInt(rawHex.substr(offset, 2), 16);
291
- offset += 2;
292
- console.log(`\n 🔢 Output count: ${rawHex.substr(offset-2, 2)} (${outputCount} output${outputCount > 1 ? 's' : ''})`);
293
-
289
+ const outputCount = parseInt(rawHex.substr(offset, 2), 16)
290
+ offset += 2
291
+ console.log(`\n 🔢 Output count: ${rawHex.substr(offset - 2, 2)} (${outputCount} output${outputCount > 1 ? 's' : ''})`)
292
+
294
293
  // Outputs
295
294
  for (let i = 0; i < outputCount; i++) {
296
- console.log(` \n 📤 Output ${i}:`);
297
-
295
+ console.log(` \n 📤 Output ${i}:`)
296
+
298
297
  // Value (8 bytes)
299
- const value = rawHex.substr(offset, 16);
300
- offset += 16;
301
- const satoshis = parseInt(value.match(/.{2}/g).reverse().join(''), 16);
302
- console.log(` 💰 Value: ${value} (${satoshis} satoshis)`);
303
-
298
+ const value = rawHex.substr(offset, 16)
299
+ offset += 16
300
+ const satoshis = parseInt(value.match(/.{2}/g).reverse().join(''), 16)
301
+ console.log(` 💰 Value: ${value} (${satoshis} satoshis)`)
302
+
304
303
  // Script length (1+ bytes, varint)
305
- const scriptLen = parseInt(rawHex.substr(offset, 2), 16);
306
- offset += 2;
307
- console.log(` 📏 Script length: ${rawHex.substr(offset-2, 2)} (${scriptLen} bytes)`);
308
-
304
+ const scriptLen = parseInt(rawHex.substr(offset, 2), 16)
305
+ offset += 2
306
+ console.log(` 📏 Script length: ${rawHex.substr(offset - 2, 2)} (${scriptLen} bytes)`)
307
+
309
308
  // Script (scriptLen bytes)
310
- const script = rawHex.substr(offset, scriptLen * 2);
311
- offset += scriptLen * 2;
312
- console.log(` 🏠 Script: ${script}`);
313
-
309
+ const script = rawHex.substr(offset, scriptLen * 2)
310
+ offset += scriptLen * 2
311
+ console.log(` 🏠 Script: ${script}`)
312
+
314
313
  // Parse P2PKH script
315
314
  if (script.length === 50 && script.startsWith('76a914') && script.endsWith('88ac')) {
316
- const hash160 = script.substr(6, 40);
317
- console.log(` 🔍 P2PKH script breakdown:`);
318
- console.log(` 📋 OP_DUP: 76`);
319
- console.log(` 📋 OP_HASH160: a9`);
320
- console.log(` 📋 Push 20 bytes: 14`);
321
- console.log(` 🏠 Address hash160: ${hash160}`);
322
- console.log(` 📋 OP_EQUALVERIFY: 88`);
323
- console.log(` 📋 OP_CHECKSIG: ac`);
315
+ const hash160 = script.substr(6, 40)
316
+ console.log(` 🔍 P2PKH script breakdown:`)
317
+ console.log(` 📋 OP_DUP: 76`)
318
+ console.log(` 📋 OP_HASH160: a9`)
319
+ console.log(` 📋 Push 20 bytes: 14`)
320
+ console.log(` 🏠 Address hash160: ${hash160}`)
321
+ console.log(` 📋 OP_EQUALVERIFY: 88`)
322
+ console.log(` 📋 OP_CHECKSIG: ac`)
324
323
  }
325
324
  }
326
-
325
+
327
326
  // Lock time (4 bytes)
328
- const lockTime = rawHex.substr(offset, 8);
329
- console.log(`\n 🔒 Lock time: ${lockTime} (${parseInt(lockTime.match(/.{2}/g).reverse().join(''), 16)})`);
330
-
327
+ const lockTime = rawHex.substr(offset, 8)
328
+ console.log(`\n 🔒 Lock time: ${lockTime} (${parseInt(lockTime.match(/.{2}/g).reverse().join(''), 16)})`)
331
329
  } catch (error) {
332
- console.log(` ❌ Error analyzing hex: ${error.message}`);
330
+ console.log(` ❌ Error analyzing hex: ${error.message}`)
333
331
  }
334
332
  }
335
333
 
336
334
  /**
337
335
  * Validate raw transaction hex format
338
336
  */
339
- function validateTransactionHex(transaction) {
340
- console.log('🔢 Validating raw transaction hex format...');
341
-
342
- const result = new ValidationResult(true);
343
-
337
+ function validateTransactionHex (transaction) {
338
+ console.log('🔢 Validating raw transaction hex format...')
339
+
340
+ const result = new ValidationResult(true)
341
+
344
342
  try {
345
343
  // Get the raw hex of the transaction
346
- const rawHex = transaction.toString();
347
- console.log(` 📦 Raw TX hex length: ${rawHex.length} characters`);
348
- console.log(` 🔍 TX hex preview: ${rawHex.substring(0, 60)}...`);
349
- console.log(` 📋 Full raw hex: ${rawHex}`);
350
-
351
- // Parse and show detailed breakdown
352
- console.log(`\n 🔬 Raw Hex Breakdown:`);
353
- analyzeRawTransactionHex(rawHex); // Try to parse the hex back into a transaction object
354
- const parsedTx = new bsv.Transaction(rawHex);
355
-
344
+ const rawHex = transaction.toString()
345
+ console.log(` 📦 Raw TX hex length: ${rawHex.length} characters`)
346
+ console.log(` 🔍 TX hex preview: ${rawHex.substring(0, 60)}...`)
347
+ console.log(` 📋 Full raw hex: ${rawHex}`)
348
+
349
+ // Parse and show detailed breakdown
350
+ console.log(`\n 🔬 Raw Hex Breakdown:`)
351
+ analyzeRawTransactionHex(rawHex) // Try to parse the hex back into a transaction object
352
+ const parsedTx = new bsv.Transaction(rawHex)
353
+
356
354
  // Verify it matches the original
357
355
  if (parsedTx.id !== transaction.id) {
358
- result.addError(`Transaction hex parsing mismatch: expected ${transaction.id}, got ${parsedTx.id}`);
356
+ result.addError(`Transaction hex parsing mismatch: expected ${transaction.id}, got ${parsedTx.id}`)
359
357
  } else {
360
- console.log(` ✅ Transaction hex is valid and parseable`);
358
+ console.log(` ✅ Transaction hex is valid and parseable`)
361
359
  }
362
-
360
+
363
361
  // Additional format checks
364
362
  if (rawHex.length < 20) {
365
- result.addError('Transaction hex too short to be valid');
363
+ result.addError('Transaction hex too short to be valid')
366
364
  }
367
-
365
+
368
366
  if (!/^[0-9a-fA-F]+$/.test(rawHex)) {
369
- result.addError('Transaction contains invalid hex characters');
367
+ result.addError('Transaction contains invalid hex characters')
370
368
  }
371
-
372
369
  } catch (error) {
373
- result.addError(`Invalid transaction hex format: ${error.message}`);
370
+ result.addError(`Invalid transaction hex format: ${error.message}`)
374
371
  }
375
-
376
- return result;
372
+
373
+ return result
377
374
  }
378
375
 
379
376
  /**
380
377
  * Validate entire transaction with comprehensive checks
381
378
  */
382
- function validateTransaction(transaction) {
383
- console.log(`\n⛏️ MINER: Validating transaction ${transaction.id}`);
384
- console.log('═'.repeat(80));
385
-
379
+ function validateTransaction (transaction) {
380
+ console.log(`\n⛏️ MINER: Validating transaction ${transaction.id}`)
381
+ console.log('═'.repeat(80))
382
+
386
383
  const results = [
387
384
  validateTransactionHex(transaction),
388
385
  validateTransactionInputs(transaction),
389
386
  validateTransactionSignatures(transaction),
390
387
  validateTransactionOutputs(transaction),
391
388
  validateTransactionBalance(transaction)
392
- ];
393
-
389
+ ]
390
+
394
391
  // Combine all results
395
- const finalResult = new ValidationResult(true);
396
-
392
+ const finalResult = new ValidationResult(true)
393
+
397
394
  results.forEach(result => {
398
395
  if (!result.valid) {
399
- finalResult.valid = false;
396
+ finalResult.valid = false
400
397
  }
401
- finalResult.errors.push(...result.errors);
402
- finalResult.warnings.push(...result.warnings);
403
- });
404
-
398
+ finalResult.errors.push(...result.errors)
399
+ finalResult.warnings.push(...result.warnings)
400
+ })
401
+
405
402
  // Display results
406
403
  if (finalResult.valid) {
407
- console.log('\n✅ Transaction is VALID - All checks passed');
408
- console.log(' 🔢 Raw hex format: ✅');
409
- console.log(' 🔍 UTXO validation: ✅');
410
- console.log(' 🔐 Script validation: ✅');
411
- console.log(' 📤 Output validation: ✅');
412
- console.log(' ⚖️ Balance validation: ✅');
404
+ console.log('\n✅ Transaction is VALID - All checks passed')
405
+ console.log(' 🔢 Raw hex format: ✅')
406
+ console.log(' 🔍 UTXO validation: ✅')
407
+ console.log(' 🔐 Script validation: ✅')
408
+ console.log(' 📤 Output validation: ✅')
409
+ console.log(' ⚖️ Balance validation: ✅')
413
410
  } else {
414
- console.log('\n❌ Transaction is INVALID');
411
+ console.log('\n❌ Transaction is INVALID')
415
412
  }
416
-
413
+
417
414
  if (finalResult.errors.length > 0) {
418
- console.log('\n🚫 Validation Errors:');
419
- finalResult.errors.forEach(error => console.log(` - ${error}`));
415
+ console.log('\n🚫 Validation Errors:')
416
+ finalResult.errors.forEach(error => console.log(` - ${error}`))
420
417
  }
421
-
418
+
422
419
  if (finalResult.warnings.length > 0) {
423
- console.log('\n⚠️ Validation Warnings:');
424
- finalResult.warnings.forEach(warning => console.log(` - ${warning}`));
420
+ console.log('\n⚠️ Validation Warnings:')
421
+ finalResult.warnings.forEach(warning => console.log(` - ${warning}`))
425
422
  }
426
-
427
- return finalResult;
423
+
424
+ return finalResult
428
425
  }
429
426
 
430
427
  /**
431
428
  * Process a valid transaction (update UTXO set)
432
429
  */
433
- function processTransaction(transaction) {
434
- console.log(`\n🔄 Processing transaction ${transaction.id}...`);
435
-
436
- const state = loadBlockchainState();
437
-
430
+ function processTransaction (transaction) {
431
+ console.log(`\n🔄 Processing transaction ${transaction.id}...`)
432
+
433
+ const state = loadBlockchainState()
434
+
438
435
  // Spend input UTXOs
439
- console.log('❌ Spending input UTXOs:');
436
+ console.log('❌ Spending input UTXOs:')
440
437
  for (const input of transaction.inputs) {
441
- const prevTxId = input.prevTxId.toString('hex');
442
- const outputIndex = input.outputIndex;
443
-
438
+ const prevTxId = input.prevTxId.toString('hex')
439
+ const outputIndex = input.outputIndex
440
+
444
441
  try {
445
- spendUTXO(prevTxId, outputIndex, transaction.id);
446
- console.log(` - ${prevTxId}:${outputIndex} spent`);
442
+ spendUTXO(prevTxId, outputIndex, transaction.id)
443
+ console.log(` - ${prevTxId}:${outputIndex} spent`)
447
444
  } catch (error) {
448
- console.error(` - Error spending ${prevTxId}:${outputIndex}: ${error.message}`);
445
+ console.error(` - Error spending ${prevTxId}:${outputIndex}: ${error.message}`)
449
446
  }
450
447
  }
451
-
448
+
452
449
  // Create new UTXOs from outputs
453
- console.log('✅ Creating new UTXOs:');
450
+ console.log('✅ Creating new UTXOs:')
454
451
  for (let i = 0; i < transaction.outputs.length; i++) {
455
- const output = transaction.outputs[i];
456
-
452
+ const output = transaction.outputs[i]
453
+
457
454
  try {
458
- const outputAddress = output.script.toAddress();
455
+ const outputAddress = output.script.toAddress()
459
456
  const newUTXO = {
460
457
  txid: transaction.id,
461
458
  vout: i,
@@ -464,15 +461,15 @@ function processTransaction(transaction) {
464
461
  scriptPubKey: output.script.toHex(),
465
462
  satoshis: output.satoshis,
466
463
  address: outputAddress.toString()
467
- };
468
-
469
- addUTXO(newUTXO, outputAddress.toString());
470
- console.log(` - ${transaction.id}:${i} -> ${outputAddress} (${output.satoshis} sats)`);
464
+ }
465
+
466
+ addUTXO(newUTXO, outputAddress.toString())
467
+ console.log(` - ${transaction.id}:${i} -> ${outputAddress} (${output.satoshis} sats)`)
471
468
  } catch (error) {
472
- console.error(` - Error creating output ${i}: ${error.message}`);
469
+ console.error(` - Error creating output ${i}: ${error.message}`)
473
470
  }
474
471
  }
475
-
472
+
476
473
  // Add to transaction history
477
474
  state.transactionHistory.push({
478
475
  txid: transaction.id,
@@ -480,132 +477,131 @@ function processTransaction(transaction) {
480
477
  inputCount: transaction.inputs.length,
481
478
  outputCount: transaction.outputs.length,
482
479
  fee: calculateTransactionFee(transaction)
483
- });
484
-
480
+ })
481
+
485
482
  // Increment block height (simplified mining)
486
- state.metadata.blockHeight += 1;
487
-
488
- saveBlockchainState(state);
489
-
490
- console.log(`✅ Transaction ${transaction.id} processed successfully`);
491
- console.log(`🏗️ New block height: ${state.metadata.blockHeight}`);
483
+ state.metadata.blockHeight += 1
484
+
485
+ saveBlockchainState(state)
486
+
487
+ console.log(`✅ Transaction ${transaction.id} processed successfully`)
488
+ console.log(`🏗️ New block height: ${state.metadata.blockHeight}`)
492
489
  }
493
490
 
494
491
  /**
495
492
  * Calculate transaction fee
496
493
  */
497
- function calculateTransactionFee(transaction) {
498
- let inputValue = 0;
499
-
494
+ function calculateTransactionFee (transaction) {
495
+ let inputValue = 0
496
+
500
497
  for (const input of transaction.inputs) {
501
- const prevTxId = input.prevTxId.toString('hex');
502
- const outputIndex = input.outputIndex;
503
- const utxoResult = getUTXO(prevTxId, outputIndex);
504
-
498
+ const prevTxId = input.prevTxId.toString('hex')
499
+ const outputIndex = input.outputIndex
500
+ const utxoResult = getUTXO(prevTxId, outputIndex)
501
+
505
502
  if (utxoResult.exists) {
506
- inputValue += utxoResult.utxo.satoshis;
503
+ inputValue += utxoResult.utxo.satoshis
507
504
  }
508
505
  }
509
-
510
- const outputValue = transaction.outputs.reduce((sum, output) => sum + output.satoshis, 0);
511
-
512
- return inputValue - outputValue;
506
+
507
+ const outputValue = transaction.outputs.reduce((sum, output) => sum + output.satoshis, 0)
508
+
509
+ return inputValue - outputValue
513
510
  }
514
511
 
515
512
  /**
516
513
  * Accept raw transaction hex and validate it
517
514
  */
518
- function acceptRawTransaction(rawTxHex) {
519
- console.log('\n📡 BROADCAST: Raw transaction hex received by miner');
520
- console.log(`Raw hex length: ${rawTxHex.length} characters`);
521
-
515
+ function acceptRawTransaction (rawTxHex) {
516
+ console.log('\n📡 BROADCAST: Raw transaction hex received by miner')
517
+ console.log(`Raw hex length: ${rawTxHex.length} characters`)
518
+
522
519
  try {
523
520
  // Parse the raw transaction hex
524
- const transaction = new bsv.Transaction(rawTxHex);
525
- console.log(`Transaction ID: ${transaction.id}`);
526
- console.log(`Inputs: ${transaction.inputs.length}`);
527
- console.log(`Outputs: ${transaction.outputs.length}`);
528
-
529
- return acceptTransaction(transaction);
530
-
521
+ const transaction = new bsv.Transaction(rawTxHex)
522
+ console.log(`Transaction ID: ${transaction.id}`)
523
+ console.log(`Inputs: ${transaction.inputs.length}`)
524
+ console.log(`Outputs: ${transaction.outputs.length}`)
525
+
526
+ return acceptTransaction(transaction)
531
527
  } catch (error) {
532
- console.log('\n❌ INVALID RAW TRANSACTION');
533
- console.log(`Parse error: ${error.message}`);
534
-
528
+ console.log('\n❌ INVALID RAW TRANSACTION')
529
+ console.log(`Parse error: ${error.message}`)
530
+
535
531
  return {
536
532
  accepted: false,
537
533
  txid: null,
538
534
  errors: [`Failed to parse raw transaction hex: ${error.message}`],
539
535
  warnings: []
540
- };
536
+ }
541
537
  }
542
538
  }
543
539
 
544
540
  /**
545
541
  * Accept and process a broadcast transaction (object or hex)
546
542
  */
547
- function acceptTransaction(transaction) {
543
+ function acceptTransaction (transaction) {
548
544
  // If it's a string, treat as raw hex
549
545
  if (typeof transaction === 'string') {
550
- return acceptRawTransaction(transaction);
546
+ return acceptRawTransaction(transaction)
551
547
  }
552
-
553
- console.log('\n📡 BROADCAST: Transaction object received by miner');
554
- console.log(`Transaction ID: ${transaction.id}`);
555
- console.log(`Inputs: ${transaction.inputs.length}`);
556
- console.log(`Outputs: ${transaction.outputs.length}`);
557
-
548
+
549
+ console.log('\n📡 BROADCAST: Transaction object received by miner')
550
+ console.log(`Transaction ID: ${transaction.id}`)
551
+ console.log(`Inputs: ${transaction.inputs.length}`)
552
+ console.log(`Outputs: ${transaction.outputs.length}`)
553
+
558
554
  // Log the raw hex representation
559
- const rawHex = transaction.toString();
560
- console.log(`📦 Raw Transaction Hex (${rawHex.length} chars):`);
561
- console.log(`${rawHex.substring(0, 80)}...`);
562
- console.log(`...${rawHex.substring(rawHex.length - 80)}`);
563
-
555
+ const rawHex = transaction.toString()
556
+ console.log(`📦 Raw Transaction Hex (${rawHex.length} chars):`)
557
+ console.log(`${rawHex.substring(0, 80)}...`)
558
+ console.log(`...${rawHex.substring(rawHex.length - 80)}`)
559
+
564
560
  // Validate transaction
565
- const validation = validateTransaction(transaction);
566
-
561
+ const validation = validateTransaction(transaction)
562
+
567
563
  if (validation.valid) {
568
564
  // Process the transaction
569
- processTransaction(transaction);
570
-
565
+ processTransaction(transaction)
566
+
571
567
  return {
572
568
  accepted: true,
573
569
  txid: transaction.id,
574
570
  errors: validation.errors,
575
571
  warnings: validation.warnings
576
- };
572
+ }
577
573
  } else {
578
- console.log(`\n🚫 Transaction ${transaction.id} REJECTED`);
579
-
574
+ console.log(`\n🚫 Transaction ${transaction.id} REJECTED`)
575
+
580
576
  return {
581
577
  accepted: false,
582
578
  txid: transaction.id,
583
579
  errors: validation.errors,
584
580
  warnings: validation.warnings
585
- };
581
+ }
586
582
  }
587
583
  }
588
584
 
589
585
  /**
590
586
  * Get mempool status (simplified)
591
587
  */
592
- function getMempoolStatus() {
593
- const state = loadBlockchainState();
594
-
595
- console.log('\n📊 Miner/Mempool Status:');
596
- console.log('═'.repeat(50));
597
- console.log(`🏗️ Current Block Height: ${state.metadata.blockHeight}`);
598
- console.log(`🔄 Transactions Processed: ${state.transactionHistory.length}`);
599
- console.log(`💰 Total Network Value: ${state.metadata.totalValue} satoshis`);
600
- console.log(`👛 Active Wallets: ${state.metadata.totalWallets}`);
601
- console.log(`📦 Available UTXOs: ${state.metadata.totalUTXOs}`);
602
-
603
- return state;
588
+ function getMempoolStatus () {
589
+ const state = loadBlockchainState()
590
+
591
+ console.log('\n📊 Miner/Mempool Status:')
592
+ console.log('═'.repeat(50))
593
+ console.log(`🏗️ Current Block Height: ${state.metadata.blockHeight}`)
594
+ console.log(`🔄 Transactions Processed: ${state.transactionHistory.length}`)
595
+ console.log(`💰 Total Network Value: ${state.metadata.totalValue} satoshis`)
596
+ console.log(`👛 Active Wallets: ${state.metadata.totalWallets}`)
597
+ console.log(`📦 Available UTXOs: ${state.metadata.totalUTXOs}`)
598
+
599
+ return state
604
600
  }
605
601
 
606
602
  // If called directly, show mempool status
607
603
  if (require.main === module) {
608
- getMempoolStatus();
604
+ getMempoolStatus()
609
605
  }
610
606
 
611
607
  module.exports = {
@@ -617,4 +613,4 @@ module.exports = {
617
613
  processTransaction,
618
614
  getMempoolStatus,
619
615
  ValidationResult
620
- };
616
+ }