@smartledger/bsv 7.9.0 → 7.10.0

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 (72) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/README.md +38 -38
  3. package/bsv-covenant.min.js +1 -1
  4. package/bsv-ecies.min.js +1 -1
  5. package/bsv-gdaf.min.js +54 -54
  6. package/bsv-ltp.min.js +58 -85
  7. package/bsv-message.min.js +2 -2
  8. package/bsv-mnemonic.min.js +12 -14
  9. package/bsv-script-helper.min.js +1 -1
  10. package/bsv-shamir.min.js +14 -16
  11. package/bsv-smartcontract.min.js +23 -25
  12. package/bsv.bundle.js +54 -54
  13. package/bsv.min.js +54 -54
  14. package/build/esbuild.js +84 -4
  15. package/docs/MODULE_REFERENCE_COMPLETE.md +27 -27
  16. package/docs/advanced/UTXO_MANAGER_GUIDE.md +1 -1
  17. package/docs/getting-started/INSTALLATION.md +23 -23
  18. package/docs/getting-started/QUICK_START.md +7 -7
  19. package/docs/migration/FROM_BSV_1_5_6.md +5 -5
  20. package/index.js +9 -1
  21. package/lib/covenant/helpers.js +146 -0
  22. package/lib/covenant/index.js +21 -0
  23. package/lib/covenant/pushtx.js +243 -0
  24. package/lib/covenant-interface.js +408 -397
  25. package/lib/custom-script-helper.js +44 -38
  26. package/lib/ecies/bitcore-ecies.js +3 -4
  27. package/lib/ecies/electrum-ecies.js +4 -6
  28. package/lib/ecies/errors.js +1 -1
  29. package/lib/gdaf/attestation-signer.js +7 -7
  30. package/lib/gdaf/attestation-verifier.js +5 -6
  31. package/lib/gdaf/did-resolver.js +10 -9
  32. package/lib/gdaf/smartledger-anchor.js +13 -12
  33. package/lib/gdaf/zk-prover.js +8 -8
  34. package/lib/ltp/anchor.js +2 -3
  35. package/lib/ltp/claim.js +2 -3
  36. package/lib/ltp/index.js +2 -3
  37. package/lib/ltp/obligation.js +9 -9
  38. package/lib/ltp/proof.js +7 -7
  39. package/lib/ltp/registry.js +4 -5
  40. package/lib/ltp/right.js +11 -11
  41. package/lib/message/index.js +5 -4
  42. package/lib/message/message.js +11 -11
  43. package/lib/mnemonic/errors.js +1 -1
  44. package/lib/mnemonic/index.js +5 -4
  45. package/lib/mnemonic/mnemonic.js +22 -10
  46. package/lib/ordinals/bsv20.js +4 -4
  47. package/lib/ordinals/inscription.js +8 -12
  48. package/lib/ordinals/ordlock.js +26 -21
  49. package/lib/smart_contract/authorizers.js +8 -6
  50. package/lib/smart_contract/builder.js +32 -26
  51. package/lib/smart_contract/covenant.js +32 -25
  52. package/lib/smart_contract/covenant_helpers.js +8 -139
  53. package/lib/smart_contract/debugger.js +9 -6
  54. package/lib/smart_contract/dsl.js +5 -6
  55. package/lib/smart_contract/index.js +11 -8
  56. package/lib/smart_contract/locks.js +3 -4
  57. package/lib/smart_contract/opcode_list.js +2 -3
  58. package/lib/smart_contract/pels.js +4 -5
  59. package/lib/smart_contract/preimage.js +11 -7
  60. package/lib/smart_contract/pushtx.js +8 -263
  61. package/lib/smart_contract/script_interpreter.js +112 -105
  62. package/lib/smart_contract/script_tester.js +24 -18
  63. package/lib/smart_contract/script_utils.js +15 -14
  64. package/lib/smart_contract/sighash.js +23 -15
  65. package/lib/smart_contract/stack_examiner.js +70 -63
  66. package/lib/smart_contract/token.js +6 -6
  67. package/lib/smart_contract/utxo_generator.js +21 -15
  68. package/lib/smartutxo.js +27 -21
  69. package/lib/spv/headerchain.js +3 -3
  70. package/lib/spv/merkleproof.js +3 -3
  71. package/package.json +4 -2
  72. package/version.js +1 -1
@@ -1,22 +1,33 @@
1
1
  /**
2
2
  * SmartLedger Covenant Interface - Advanced BSV Covenant Development
3
- *
3
+ *
4
4
  * Provides high-level abstractions for covenant development while preserving
5
5
  * full access to low-level BSV operations. Works alongside existing BSV API.
6
- *
6
+ *
7
7
  * Features:
8
8
  * - Simplified covenant creation and validation
9
- * - Automatic preimage generation and parsing
9
+ * - Automatic preimage generation and parsing
10
10
  * - Template-based covenant patterns
11
11
  * - Full compatibility with existing bsv library
12
12
  * - Granular control when needed
13
13
  */
14
14
 
15
- const bsv = require('../index.js');
15
+ var sighash = require('./transaction/sighash')
16
+ var Output = require('./transaction/output')
17
+ var Interpreter = require('./script/interpreter')
18
+ var Signature = require('./crypto/signature')
19
+ var BN = require('./crypto/bn')
20
+ var Transaction = require('./transaction')
21
+ var Opcode = require('./opcode')
22
+ var Script = require('./script')
16
23
 
17
24
  class CovenantInterface {
18
- constructor() {
19
- this.bsv = bsv; // Full access to underlying BSV library
25
+ constructor () {
26
+ // Full access to the underlying BSV library. Required here rather than at
27
+ // module scope: this file is reached while index.js is still initializing,
28
+ // so a top-level require of the root would capture a half-built namespace.
29
+ // Constructor time is after load, so the require is safe and complete.
30
+ this.bsv = require('../index.js'); // eslint-disable-line
20
31
  }
21
32
 
22
33
  /**
@@ -24,59 +35,59 @@ class CovenantInterface {
24
35
  * @param {Object} config - Transaction configuration
25
36
  * @returns {CovenantTransaction} Enhanced transaction object
26
37
  */
27
- createCovenantTransaction(config) {
28
- const tx = new bsv.Transaction();
29
-
38
+ createCovenantTransaction (config) {
39
+ const tx = new Transaction()
40
+
30
41
  // Add inputs
31
42
  if (config.inputs) {
32
- config.inputs.forEach(input => tx.from(input));
43
+ config.inputs.forEach(input => tx.from(input))
33
44
  }
34
-
45
+
35
46
  // Add outputs
36
47
  if (config.outputs) {
37
48
  config.outputs.forEach(output => {
38
49
  if (output.script) {
39
- tx.addOutput(new bsv.Transaction.Output({
50
+ tx.addOutput(new Output({
40
51
  script: output.script,
41
52
  satoshis: output.satoshis
42
- }));
53
+ }))
43
54
  } else {
44
- tx.to(output.address, output.satoshis);
55
+ tx.to(output.address, output.satoshis)
45
56
  }
46
- });
57
+ })
47
58
  }
48
-
59
+
49
60
  // Set fee configuration
50
61
  if (config.feePerKb) {
51
- tx.feePerKb(config.feePerKb);
62
+ tx.feePerKb(config.feePerKb)
52
63
  }
53
-
54
- return new CovenantTransaction(tx, this);
64
+
65
+ return new CovenantTransaction(tx, this)
55
66
  }
56
67
 
57
68
  /**
58
69
  * Create manual signature using correct BSV API
59
70
  * @param {Transaction} transaction - BSV transaction
60
71
  * @param {PrivateKey} privateKey - Private key to sign with
61
- * @param {number} inputIndex - Input index
72
+ * @param {number} inputIndex - Input index
62
73
  * @param {Script} lockingScript - Locking script being spent
63
74
  * @param {number} satoshis - Amount in satoshis
64
75
  * @param {number} sighashType - Signature hash type
65
76
  * @returns {Buffer} Complete signature with sighash type
66
77
  */
67
- createSignature(transaction, privateKey, inputIndex, lockingScript, satoshis, sighashType = null) {
68
- sighashType = sighashType || (bsv.crypto.Signature.SIGHASH_ALL | bsv.crypto.Signature.SIGHASH_FORKID);
69
-
70
- const signature = bsv.Transaction.sighash.sign(
78
+ createSignature (transaction, privateKey, inputIndex, lockingScript, satoshis, sighashType = null) {
79
+ sighashType = sighashType || (Signature.SIGHASH_ALL | Signature.SIGHASH_FORKID)
80
+
81
+ const signature = sighash.sign(
71
82
  transaction,
72
83
  privateKey,
73
84
  sighashType,
74
85
  inputIndex,
75
86
  lockingScript,
76
- new bsv.crypto.BN(satoshis)
77
- );
78
-
79
- return Buffer.concat([signature.toDER(), Buffer.from([sighashType])]);
87
+ new BN(satoshis)
88
+ )
89
+
90
+ return Buffer.concat([signature.toDER(), Buffer.from([sighashType])])
80
91
  }
81
92
 
82
93
  /**
@@ -88,18 +99,18 @@ class CovenantInterface {
88
99
  * @param {number} sighashType - Signature hash type
89
100
  * @returns {CovenantPreimage} Parsed preimage object
90
101
  */
91
- getPreimage(transaction, inputIndex, lockingScript, satoshis, sighashType = null) {
92
- sighashType = sighashType || (bsv.crypto.Signature.SIGHASH_ALL | bsv.crypto.Signature.SIGHASH_FORKID);
93
-
94
- const preimage = bsv.Transaction.sighash.sighash(
102
+ getPreimage (transaction, inputIndex, lockingScript, satoshis, sighashType = null) {
103
+ sighashType = sighashType || (Signature.SIGHASH_ALL | Signature.SIGHASH_FORKID)
104
+
105
+ const preimage = sighash.sighash(
95
106
  transaction,
96
107
  sighashType,
97
108
  inputIndex,
98
109
  lockingScript,
99
- new bsv.crypto.BN(satoshis)
100
- );
101
-
102
- return new CovenantPreimage(preimage);
110
+ new BN(satoshis)
111
+ )
112
+
113
+ return new CovenantPreimage(preimage)
103
114
  }
104
115
 
105
116
  /**
@@ -109,73 +120,73 @@ class CovenantInterface {
109
120
  * @param {PublicKey} authorizedKey - Key authorized for state transitions
110
121
  * @returns {Script} State machine covenant script
111
122
  */
112
- createStateMachine(states, currentState, authorizedKey) {
113
- const script = new bsv.Script();
114
-
123
+ createStateMachine (states, currentState, authorizedKey) {
124
+ const script = new Script()
125
+
115
126
  // Check current state
116
- script.add(Buffer.from([currentState]));
117
- script.add(bsv.Opcode.OP_EQUAL);
118
- script.add(bsv.Opcode.OP_VERIFY);
119
-
127
+ script.add(Buffer.from([currentState]))
128
+ script.add(Opcode.OP_EQUAL)
129
+ script.add(Opcode.OP_VERIFY)
130
+
120
131
  // Validate state transition logic
121
132
  for (let i = 0; i < states.length - 1; i++) {
122
133
  if (i === currentState) {
123
134
  // Valid next states
124
135
  states[i].nextStates.forEach(nextState => {
125
- script.add(Buffer.from([nextState]));
126
- script.add(bsv.Opcode.OP_EQUAL);
127
- script.add(bsv.Opcode.OP_IF);
136
+ script.add(Buffer.from([nextState]))
137
+ script.add(Opcode.OP_EQUAL)
138
+ script.add(Opcode.OP_IF)
128
139
  // Add transition logic here
129
- script.add(bsv.Opcode.OP_ENDIF);
130
- });
140
+ script.add(Opcode.OP_ENDIF)
141
+ })
131
142
  }
132
143
  }
133
-
144
+
134
145
  // Require authorized signature
135
- script.add(bsv.Opcode.OP_DUP);
136
- script.add(bsv.Opcode.OP_HASH160);
137
- script.add(authorizedKey.toAddress().hashBuffer);
138
- script.add(bsv.Opcode.OP_EQUALVERIFY);
139
- script.add(bsv.Opcode.OP_CHECKSIG);
140
-
141
- return script;
146
+ script.add(Opcode.OP_DUP)
147
+ script.add(Opcode.OP_HASH160)
148
+ script.add(authorizedKey.toAddress().hashBuffer)
149
+ script.add(Opcode.OP_EQUALVERIFY)
150
+ script.add(Opcode.OP_CHECKSIG)
151
+
152
+ return script
142
153
  }
143
154
 
144
155
  /**
145
156
  * Covenant Template: Escrow with Arbitration
146
157
  * @param {PublicKey} buyer - Buyer public key
147
- * @param {PublicKey} seller - Seller public key
158
+ * @param {PublicKey} seller - Seller public key
148
159
  * @param {PublicKey} arbitrator - Arbitrator public key
149
160
  * @param {number} timelock - Optional timelock for refund
150
161
  * @returns {Script} Escrow covenant script
151
162
  */
152
- createEscrow(buyer, seller, arbitrator, timelock = null) {
153
- const script = new bsv.Script();
154
-
163
+ createEscrow (buyer, seller, arbitrator, timelock = null) {
164
+ const script = new Script()
165
+
155
166
  if (timelock) {
156
167
  // Time-locked refund path
157
- script.add(bsv.Opcode.OP_IF);
158
- script.add(Buffer.from(timelock.toString(16).padStart(8, '0'), 'hex').reverse());
159
- script.add(bsv.Opcode.OP_CHECKLOCKTIMEVERIFY);
160
- script.add(bsv.Opcode.OP_DROP);
161
- script.add(buyer.toBuffer());
162
- script.add(bsv.Opcode.OP_CHECKSIG);
163
- script.add(bsv.Opcode.OP_ELSE);
168
+ script.add(Opcode.OP_IF)
169
+ script.add(Buffer.from(timelock.toString(16).padStart(8, '0'), 'hex').reverse())
170
+ script.add(Opcode.OP_CHECKLOCKTIMEVERIFY)
171
+ script.add(Opcode.OP_DROP)
172
+ script.add(buyer.toBuffer())
173
+ script.add(Opcode.OP_CHECKSIG)
174
+ script.add(Opcode.OP_ELSE)
164
175
  }
165
-
176
+
166
177
  // 2-of-3 multisig: buyer + seller, buyer + arbitrator, or seller + arbitrator
167
- script.add(bsv.Opcode.OP_2);
168
- script.add(buyer.toBuffer());
169
- script.add(seller.toBuffer());
170
- script.add(arbitrator.toBuffer());
171
- script.add(bsv.Opcode.OP_3);
172
- script.add(bsv.Opcode.OP_CHECKMULTISIG);
173
-
178
+ script.add(Opcode.OP_2)
179
+ script.add(buyer.toBuffer())
180
+ script.add(seller.toBuffer())
181
+ script.add(arbitrator.toBuffer())
182
+ script.add(Opcode.OP_3)
183
+ script.add(Opcode.OP_CHECKMULTISIG)
184
+
174
185
  if (timelock) {
175
- script.add(bsv.Opcode.OP_ENDIF);
186
+ script.add(Opcode.OP_ENDIF)
176
187
  }
177
-
178
- return script;
188
+
189
+ return script
179
190
  }
180
191
 
181
192
  /**
@@ -185,30 +196,30 @@ class CovenantInterface {
185
196
  * @param {Script} additionalRules - Optional additional validation rules
186
197
  * @returns {Script} Token covenant script
187
198
  */
188
- createTokenTransfer(newOwner, minAmount, additionalRules = null) {
189
- const script = new bsv.Script();
190
-
199
+ createTokenTransfer (newOwner, minAmount, additionalRules = null) {
200
+ const script = new Script()
201
+
191
202
  // Check minimum amount
192
203
  if (minAmount > 0) {
193
- script.add(bsv.Opcode.OP_DUP);
194
- script.add(Buffer.from(minAmount.toString(16), 'hex'));
195
- script.add(bsv.Opcode.OP_GREATERTHANOREQUAL);
196
- script.add(bsv.Opcode.OP_VERIFY);
204
+ script.add(Opcode.OP_DUP)
205
+ script.add(Buffer.from(minAmount.toString(16), 'hex'))
206
+ script.add(Opcode.OP_GREATERTHANOREQUAL)
207
+ script.add(Opcode.OP_VERIFY)
197
208
  }
198
-
209
+
199
210
  // Add custom rules
200
211
  if (additionalRules) {
201
- script.add(additionalRules.toBuffer());
212
+ script.add(additionalRules.toBuffer())
202
213
  }
203
-
214
+
204
215
  // Transfer to new owner
205
- script.add(bsv.Opcode.OP_DUP);
206
- script.add(bsv.Opcode.OP_HASH160);
207
- script.add(newOwner.toAddress().hashBuffer);
208
- script.add(bsv.Opcode.OP_EQUALVERIFY);
209
- script.add(bsv.Opcode.OP_CHECKSIG);
210
-
211
- return script;
216
+ script.add(Opcode.OP_DUP)
217
+ script.add(Opcode.OP_HASH160)
218
+ script.add(newOwner.toAddress().hashBuffer)
219
+ script.add(Opcode.OP_EQUALVERIFY)
220
+ script.add(Opcode.OP_CHECKSIG)
221
+
222
+ return script
212
223
  }
213
224
 
214
225
  /**
@@ -219,20 +230,20 @@ class CovenantInterface {
219
230
  * @param {Script} lockingScript - Locking script
220
231
  * @returns {CovenantValidation} Validation result
221
232
  */
222
- validateCovenant(transaction, inputIndex, unlockingScript, lockingScript) {
233
+ validateCovenant (transaction, inputIndex, unlockingScript, lockingScript) {
223
234
  try {
224
- const interpreter = new bsv.Script.Interpreter();
225
- const flags = bsv.Script.Interpreter.SCRIPT_VERIFY_P2SH |
226
- bsv.Script.Interpreter.SCRIPT_VERIFY_STRICTENC |
227
- bsv.Script.Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID |
228
- bsv.Script.Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES |
229
- bsv.Script.Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES;
230
-
231
- const isValid = interpreter.verify(unlockingScript, lockingScript, transaction, inputIndex, flags);
232
-
233
- return new CovenantValidation(isValid, interpreter.errstr || 'Success');
235
+ const interpreter = new Interpreter()
236
+ const flags = Interpreter.SCRIPT_VERIFY_P2SH |
237
+ Interpreter.SCRIPT_VERIFY_STRICTENC |
238
+ Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID |
239
+ Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES |
240
+ Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES
241
+
242
+ const isValid = interpreter.verify(unlockingScript, lockingScript, transaction, inputIndex, flags)
243
+
244
+ return new CovenantValidation(isValid, interpreter.errstr || 'Success')
234
245
  } catch (error) {
235
- return new CovenantValidation(false, error.message);
246
+ return new CovenantValidation(false, error.message)
236
247
  }
237
248
  }
238
249
 
@@ -242,20 +253,20 @@ class CovenantInterface {
242
253
  * @param {Object} params - Covenant parameters
243
254
  * @returns {Script} Advanced covenant script
244
255
  */
245
- createAdvancedCovenant(type, params = {}) {
256
+ createAdvancedCovenant (type, params = {}) {
246
257
  const templates = {
247
258
  'pushtx': this.createPushtxCovenant,
248
259
  'perpetual': this.createPerpetualCovenant,
249
260
  'pels': this.createPerpetualCovenant, // PELS is a type of perpetual covenant
250
261
  'introspection': this.createIntrospectionCovenant
251
- };
252
-
253
- const templateFn = templates[type];
262
+ }
263
+
264
+ const templateFn = templates[type]
254
265
  if (!templateFn) {
255
- throw new Error(`Unknown advanced covenant type: ${type}. Available types: ${Object.keys(templates).join(', ')}`);
266
+ throw new Error(`Unknown advanced covenant type: ${type}. Available types: ${Object.keys(templates).join(', ')}`)
256
267
  }
257
-
258
- return templateFn.call(this, params);
268
+
269
+ return templateFn.call(this, params)
259
270
  }
260
271
 
261
272
  /**
@@ -264,62 +275,62 @@ class CovenantInterface {
264
275
  * @param {Object} params - PUSHTX parameters
265
276
  * @returns {Script} PUSHTX covenant script
266
277
  */
267
- createPushtxCovenant(params = {}) {
278
+ createPushtxCovenant (params = {}) {
268
279
  const {
269
280
  publicKey = '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
270
281
  enforceOutputs = true,
271
282
  sighashType = 0x41 // SIGHASH_ALL | SIGHASH_FORKID
272
- } = params;
273
-
274
- const script = new bsv.Script();
275
-
283
+ } = params
284
+
285
+ const script = new Script()
286
+
276
287
  // Message construction for covenant validation (items 1-7 from preimage)
277
- script.add(bsv.Opcode.OP_2DUP)
278
- .add(bsv.Opcode.OP_HASH256) // Hash outputs (item 9)
279
- .add(bsv.Opcode.OP_SWAP);
280
-
288
+ script.add(Opcode.OP_2DUP)
289
+ .add(Opcode.OP_HASH256) // Hash outputs (item 9)
290
+ .add(Opcode.OP_SWAP)
291
+
281
292
  // Add sequence number (item 8)
282
293
  script.add(Buffer.from('ffffffff', 'hex'))
283
- .add(bsv.Opcode.OP_CAT)
284
- .add(bsv.Opcode.OP_SWAP)
285
- .add(bsv.Opcode.OP_CAT);
286
-
294
+ .add(Opcode.OP_CAT)
295
+ .add(Opcode.OP_SWAP)
296
+ .add(Opcode.OP_CAT)
297
+
287
298
  // Add locktime (item 10) and sighash flag (item 11)
288
299
  script.add(Buffer.from('00000000', 'hex')) // nLockTime
289
- .add(Buffer.from('41000000', 'hex')) // sighashType in little-endian
290
- .add(bsv.Opcode.OP_CAT)
291
- .add(bsv.Opcode.OP_CAT);
292
-
300
+ .add(Buffer.from('41000000', 'hex')) // sighashType in little-endian
301
+ .add(Opcode.OP_CAT)
302
+ .add(Opcode.OP_CAT)
303
+
293
304
  // PUSHTX signature generation (k=a=1 optimization)
294
- script.add(bsv.Opcode.OP_HASH256);
295
-
305
+ script.add(Opcode.OP_HASH256)
306
+
296
307
  // Add generator point x-coordinate
297
- const generatorX = '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798';
308
+ const generatorX = '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'
298
309
  script.add(Buffer.from(generatorX, 'hex'))
299
- .add(bsv.Opcode.OP_ADD);
300
-
310
+ .add(Opcode.OP_ADD)
311
+
301
312
  // Modular arithmetic with secp256k1 order
302
- const secp256k1Order = 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141';
313
+ const secp256k1Order = 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'
303
314
  script.add(Buffer.from(secp256k1Order, 'hex'))
304
- .add(bsv.Opcode.OP_MOD);
305
-
315
+ .add(Opcode.OP_MOD)
316
+
306
317
  // Convert to canonical DER format
307
- this._addDERConversion(script);
308
-
318
+ this._addDERConversion(script)
319
+
309
320
  // Add sighash flag and public key
310
321
  script.add(Buffer.from([sighashType]))
311
- .add(bsv.Opcode.OP_CAT)
312
- .add(Buffer.from(publicKey, 'hex'));
313
-
322
+ .add(Opcode.OP_CAT)
323
+ .add(Buffer.from(publicKey, 'hex'))
324
+
314
325
  // Verify signature with OP_CHECKSIGVERIFY
315
- script.add(bsv.Opcode.OP_CHECKSIGVERIFY);
316
-
326
+ script.add(Opcode.OP_CHECKSIGVERIFY)
327
+
317
328
  if (enforceOutputs) {
318
329
  // Message is now on stack - add output enforcement
319
- this._addOutputValidation(script, params);
330
+ this._addOutputValidation(script, params)
320
331
  }
321
-
322
- return script;
332
+
333
+ return script
323
334
  }
324
335
 
325
336
  /**
@@ -328,70 +339,70 @@ class CovenantInterface {
328
339
  * @param {Object} params - PELS parameters
329
340
  * @returns {Script} PELS covenant script
330
341
  */
331
- createPerpetualCovenant(params = {}) {
342
+ createPerpetualCovenant (params = {}) {
332
343
  const {
333
344
  publicKeyHash,
334
345
  feeDeduction = 512,
335
346
  enforceScript = true,
336
347
  enforceValue = true
337
- } = params;
338
-
348
+ } = params
349
+
339
350
  if (!publicKeyHash) {
340
- throw new Error('publicKeyHash required for perpetual covenant');
351
+ throw new Error('publicKeyHash required for perpetual covenant')
341
352
  }
342
-
343
- const script = new bsv.Script();
344
-
353
+
354
+ const script = new Script()
355
+
345
356
  // Construct message with fee-adjusted output validation
346
- script.add(bsv.Opcode.OP_2DUP)
347
- .add(bsv.Opcode.OP_BIN2NUM);
348
-
357
+ script.add(Opcode.OP_2DUP)
358
+ .add(Opcode.OP_BIN2NUM)
359
+
349
360
  // Deduct transaction fee if specified
350
361
  if (feeDeduction > 0) {
351
362
  script.add(Buffer.from(feeDeduction.toString(16).padStart(4, '0'), 'hex'))
352
- .add(bsv.Opcode.OP_SUB);
363
+ .add(Opcode.OP_SUB)
353
364
  }
354
-
365
+
355
366
  // Convert back to 8-byte little-endian
356
367
  script.add(Buffer.from([0x08]))
357
- .add(bsv.Opcode.OP_NUM2BIN)
358
- .add(bsv.Opcode.OP_SWAP)
359
- .add(bsv.Opcode.OP_CAT);
360
-
368
+ .add(Opcode.OP_NUM2BIN)
369
+ .add(Opcode.OP_SWAP)
370
+ .add(Opcode.OP_CAT)
371
+
361
372
  // Hash the new output for message construction
362
- script.add(bsv.Opcode.OP_HASH256);
363
-
373
+ script.add(Opcode.OP_HASH256)
374
+
364
375
  // Build complete sighash preimage
365
- this._addPreimageConstruction(script, params);
366
-
367
- // Generate and verify PUSHTX signature
368
- this._addPushtxSignature(script, params);
369
-
376
+ this._addPreimageConstruction(script, params)
377
+
378
+ // Generate and verify PUSHTX signature
379
+ this._addPushtxSignature(script, params)
380
+
370
381
  // Extract and validate output structure against previous output
371
382
  // Skip to value field (104 bytes into preimage)
372
- script.add(bsv.Opcode.OP_SWAP)
373
- .add(Buffer.from([0x68])) // 104 decimal = 0x68 hex
374
- .add(bsv.Opcode.OP_SPLIT)
375
- .add(bsv.Opcode.OP_NIP)
376
- .add(bsv.Opcode.OP_SWAP)
377
- .add(Buffer.from([0x08])) // 8 bytes for value
378
- .add(bsv.Opcode.OP_SPLIT)
379
- .add(bsv.Opcode.OP_SWAP)
380
- .add(bsv.Opcode.OP_CAT);
381
-
383
+ script.add(Opcode.OP_SWAP)
384
+ .add(Buffer.from([0x68])) // 104 decimal = 0x68 hex
385
+ .add(Opcode.OP_SPLIT)
386
+ .add(Opcode.OP_NIP)
387
+ .add(Opcode.OP_SWAP)
388
+ .add(Buffer.from([0x08])) // 8 bytes for value
389
+ .add(Opcode.OP_SPLIT)
390
+ .add(Opcode.OP_SWAP)
391
+ .add(Opcode.OP_CAT)
392
+
382
393
  // Verify current output matches previous output format
383
394
  if (enforceValue || enforceScript) {
384
- script.add(bsv.Opcode.OP_EQUALVERIFY);
395
+ script.add(Opcode.OP_EQUALVERIFY)
385
396
  }
386
-
397
+
387
398
  // Final P2PKH check for authenticity
388
- script.add(bsv.Opcode.OP_DUP)
389
- .add(bsv.Opcode.OP_HASH160)
390
- .add(Buffer.from(publicKeyHash, 'hex'))
391
- .add(bsv.Opcode.OP_EQUALVERIFY)
392
- .add(bsv.Opcode.OP_CHECKSIG);
393
-
394
- return script;
399
+ script.add(Opcode.OP_DUP)
400
+ .add(Opcode.OP_HASH160)
401
+ .add(Buffer.from(publicKeyHash, 'hex'))
402
+ .add(Opcode.OP_EQUALVERIFY)
403
+ .add(Opcode.OP_CHECKSIG)
404
+
405
+ return script
395
406
  }
396
407
 
397
408
  /**
@@ -399,152 +410,152 @@ class CovenantInterface {
399
410
  * @param {Object} params - Introspection parameters
400
411
  * @returns {Script} Introspection covenant script
401
412
  */
402
- createIntrospectionCovenant(params = {}) {
413
+ createIntrospectionCovenant (params = {}) {
403
414
  const {
404
415
  validateInputs = false,
405
416
  validateOutputs = true,
406
417
  validateSequence = false,
407
418
  validateLocktime = false
408
- } = params;
409
-
410
- const script = new bsv.Script();
411
-
419
+ } = params
420
+
421
+ const script = new Script()
422
+
412
423
  // Get preimage for analysis
413
- this._addPushtxSignature(script, params);
414
-
424
+ this._addPushtxSignature(script, params)
425
+
415
426
  // Parse preimage fields for validation
416
427
  if (validateInputs) {
417
- script.add(bsv.Opcode.OP_DUP)
418
- .add(Buffer.from([0x04, 0x24])) // Skip to hashPrevouts
419
- .add(bsv.Opcode.OP_SPLIT)
420
- .add(bsv.Opcode.OP_DROP);
428
+ script.add(Opcode.OP_DUP)
429
+ .add(Buffer.from([0x04, 0x24])) // Skip to hashPrevouts
430
+ .add(Opcode.OP_SPLIT)
431
+ .add(Opcode.OP_DROP)
421
432
  // Add input validation logic here
422
433
  }
423
-
434
+
424
435
  if (validateOutputs) {
425
436
  // Extract hashOutputs for validation
426
- script.add(bsv.Opcode.OP_DUP)
427
- .add(Buffer.from([0x64])) // Skip to hashOutputs position
428
- .add(bsv.Opcode.OP_SPLIT)
429
- .add(bsv.Opcode.OP_NIP)
430
- .add(Buffer.from([0x20])) // 32 bytes
431
- .add(bsv.Opcode.OP_SPLIT)
432
- .add(bsv.Opcode.OP_DROP);
433
- // Add output validation logic here
437
+ script.add(Opcode.OP_DUP)
438
+ .add(Buffer.from([0x64])) // Skip to hashOutputs position
439
+ .add(Opcode.OP_SPLIT)
440
+ .add(Opcode.OP_NIP)
441
+ .add(Buffer.from([0x20])) // 32 bytes
442
+ .add(Opcode.OP_SPLIT)
443
+ .add(Opcode.OP_DROP)
444
+ // Add output validation logic here
434
445
  }
435
-
436
- return script;
446
+
447
+ return script
437
448
  }
438
449
 
439
450
  // Helper methods for advanced covenant construction
440
-
441
- _addDERConversion(script) {
451
+
452
+ _addDERConversion (script) {
442
453
  // Convert s value to canonical form (s <= n/2)
443
- const secp256k1HalfOrder = '7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0';
444
-
445
- script.add(bsv.Opcode.OP_DUP)
446
- .add(Buffer.from(secp256k1HalfOrder, 'hex'))
447
- .add(bsv.Opcode.OP_GREATERTHAN)
448
- .add(bsv.Opcode.OP_IF);
449
-
454
+ const secp256k1HalfOrder = '7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0'
455
+
456
+ script.add(Opcode.OP_DUP)
457
+ .add(Buffer.from(secp256k1HalfOrder, 'hex'))
458
+ .add(Opcode.OP_GREATERTHAN)
459
+ .add(Opcode.OP_IF)
460
+
450
461
  // If s > n/2, compute n - s to prevent malleability
451
- const secp256k1Order = 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141';
462
+ const secp256k1Order = 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'
452
463
  script.add(Buffer.from(secp256k1Order, 'hex'))
453
- .add(bsv.Opcode.OP_SWAP)
454
- .add(bsv.Opcode.OP_SUB);
455
-
456
- script.add(bsv.Opcode.OP_ENDIF);
457
-
464
+ .add(Opcode.OP_SWAP)
465
+ .add(Opcode.OP_SUB)
466
+
467
+ script.add(Opcode.OP_ENDIF)
468
+
458
469
  // Add DER sequence formatting
459
- script.add(bsv.Opcode.OP_SIZE)
460
- .add(bsv.Opcode.OP_DUP)
461
- .add(Buffer.from([0x24])) // 36 bytes total length
462
- .add(bsv.Opcode.OP_ADD)
463
- .add(Buffer.from([0x30])) // DER sequence tag
464
- .add(bsv.Opcode.OP_SWAP)
465
- .add(bsv.Opcode.OP_CAT);
466
-
470
+ script.add(Opcode.OP_SIZE)
471
+ .add(Opcode.OP_DUP)
472
+ .add(Buffer.from([0x24])) // 36 bytes total length
473
+ .add(Opcode.OP_ADD)
474
+ .add(Buffer.from([0x30])) // DER sequence tag
475
+ .add(Opcode.OP_SWAP)
476
+ .add(Opcode.OP_CAT)
477
+
467
478
  // Add r component (using generator x-coordinate as r)
468
479
  script.add(Buffer.from('022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179802', 'hex'))
469
- .add(bsv.Opcode.OP_CAT)
470
- .add(bsv.Opcode.OP_SWAP)
471
- .add(bsv.Opcode.OP_CAT)
472
- .add(bsv.Opcode.OP_SWAP)
473
- .add(bsv.Opcode.OP_CAT);
480
+ .add(Opcode.OP_CAT)
481
+ .add(Opcode.OP_SWAP)
482
+ .add(Opcode.OP_CAT)
483
+ .add(Opcode.OP_SWAP)
484
+ .add(Opcode.OP_CAT)
474
485
  }
475
-
476
- _addOutputValidation(script, params) {
477
- const { enforceValue, enforceScript, enforceCount } = params;
478
-
486
+
487
+ _addOutputValidation (script, params) {
488
+ const { enforceValue, enforceScript, enforceCount } = params
489
+
479
490
  // Output validation after CHECKSIGVERIFY leaves preimage on stack
480
491
  if (enforceValue) {
481
- script.add(bsv.Opcode.OP_DUP)
482
- .add(Buffer.from([0x08])) // 8 bytes for value
483
- .add(bsv.Opcode.OP_SPLIT);
492
+ script.add(Opcode.OP_DUP)
493
+ .add(Buffer.from([0x08])) // 8 bytes for value
494
+ .add(Opcode.OP_SPLIT)
484
495
  // Add value enforcement logic
485
496
  }
486
-
497
+
487
498
  if (enforceScript) {
488
499
  // Extract and validate locking script
489
- script.add(bsv.Opcode.OP_DUP)
490
- .add(bsv.Opcode.OP_SIZE)
491
- .add(Buffer.from([0x09])) // Skip value + length byte
492
- .add(bsv.Opcode.OP_SUB)
493
- .add(bsv.Opcode.OP_SPLIT)
494
- .add(bsv.Opcode.OP_NIP);
500
+ script.add(Opcode.OP_DUP)
501
+ .add(Opcode.OP_SIZE)
502
+ .add(Buffer.from([0x09])) // Skip value + length byte
503
+ .add(Opcode.OP_SUB)
504
+ .add(Opcode.OP_SPLIT)
505
+ .add(Opcode.OP_NIP)
495
506
  }
496
-
507
+
497
508
  if (enforceCount) {
498
509
  // Validate number of outputs in hashOutputs
499
510
  // This requires parsing the actual outputs, not just hash
500
511
  }
501
512
  }
502
-
503
- _addPreimageConstruction(script, params) {
504
- const {
505
- version = 1,
506
- locktime = 0,
513
+
514
+ _addPreimageConstruction (script, params) {
515
+ const {
516
+ version = 1,
517
+ locktime = 0,
507
518
  sighashType = 0x41,
508
- sequence = 0xffffffff
509
- } = params;
510
-
519
+ sequence = 0xffffffff
520
+ } = params
521
+
511
522
  // Construct fields for complete BIP143 preimage
512
523
  // Items 8-11: sequence, hashOutputs, locktime, sighashType
513
524
  script.add(Buffer.from(sequence.toString(16).padStart(8, '0'), 'hex'))
514
- .add(bsv.Opcode.OP_CAT)
515
- .add(bsv.Opcode.OP_SWAP) // hashOutputs already computed
516
- .add(bsv.Opcode.OP_CAT)
517
- .add(Buffer.from(locktime.toString(16).padStart(8, '0'), 'hex'))
518
- .add(bsv.Opcode.OP_CAT)
519
- .add(Buffer.from(sighashType.toString(16).padStart(8, '0'), 'hex'))
520
- .add(bsv.Opcode.OP_CAT);
525
+ .add(Opcode.OP_CAT)
526
+ .add(Opcode.OP_SWAP) // hashOutputs already computed
527
+ .add(Opcode.OP_CAT)
528
+ .add(Buffer.from(locktime.toString(16).padStart(8, '0'), 'hex'))
529
+ .add(Opcode.OP_CAT)
530
+ .add(Buffer.from(sighashType.toString(16).padStart(8, '0'), 'hex'))
531
+ .add(Opcode.OP_CAT)
521
532
  }
522
-
523
- _addPushtxSignature(script, params) {
524
- const {
533
+
534
+ _addPushtxSignature (script, params) {
535
+ const {
525
536
  publicKey = '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
526
537
  sighashType = 0x41
527
- } = params;
528
-
538
+ } = params
539
+
529
540
  // Generate signature using PUSHTX technique (k=a=1)
530
- script.add(bsv.Opcode.OP_HASH256);
531
-
541
+ script.add(Opcode.OP_HASH256)
542
+
532
543
  // s = z + Gx mod n (where z = hash256(message), Gx = generator x-coord)
533
- const generatorX = '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798';
544
+ const generatorX = '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'
534
545
  script.add(Buffer.from(generatorX, 'hex'))
535
- .add(bsv.Opcode.OP_ADD);
536
-
546
+ .add(Opcode.OP_ADD)
547
+
537
548
  // Modular reduction with secp256k1 order
538
- const secp256k1Order = 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141';
549
+ const secp256k1Order = 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'
539
550
  script.add(Buffer.from(secp256k1Order, 'hex'))
540
- .add(bsv.Opcode.OP_MOD);
541
-
551
+ .add(Opcode.OP_MOD)
552
+
542
553
  // Convert to DER format and verify
543
- this._addDERConversion(script);
554
+ this._addDERConversion(script)
544
555
  script.add(Buffer.from([sighashType]))
545
- .add(bsv.Opcode.OP_CAT)
546
- .add(Buffer.from(publicKey, 'hex'))
547
- .add(bsv.Opcode.OP_CHECKSIGVERIFY);
556
+ .add(Opcode.OP_CAT)
557
+ .add(Buffer.from(publicKey, 'hex'))
558
+ .add(Opcode.OP_CHECKSIGVERIFY)
548
559
  }
549
560
  }
550
561
 
@@ -552,56 +563,56 @@ class CovenantInterface {
552
563
  * Enhanced transaction with covenant-specific methods
553
564
  */
554
565
  class CovenantTransaction {
555
- constructor(transaction, covenantInterface) {
556
- this.tx = transaction;
557
- this.covenant = covenantInterface;
558
- this.preimages = new Map();
566
+ constructor (transaction, covenantInterface) {
567
+ this.tx = transaction
568
+ this.covenant = covenantInterface
569
+ this.preimages = new Map()
559
570
  }
560
571
 
561
572
  /**
562
573
  * Get preimage for specific input with caching
563
574
  */
564
- getPreimage(inputIndex, lockingScript, satoshis) {
565
- const key = `${inputIndex}-${lockingScript.toHex()}-${satoshis}`;
566
-
575
+ getPreimage (inputIndex, lockingScript, satoshis) {
576
+ const key = `${inputIndex}-${lockingScript.toHex()}-${satoshis}`
577
+
567
578
  if (!this.preimages.has(key)) {
568
- const preimage = this.covenant.getPreimage(this.tx, inputIndex, lockingScript, satoshis);
569
- this.preimages.set(key, preimage);
579
+ const preimage = this.covenant.getPreimage(this.tx, inputIndex, lockingScript, satoshis)
580
+ this.preimages.set(key, preimage)
570
581
  }
571
-
572
- return this.preimages.get(key);
582
+
583
+ return this.preimages.get(key)
573
584
  }
574
585
 
575
586
  /**
576
587
  * Sign input with covenant-compatible signature
577
588
  */
578
- signInput(inputIndex, privateKey, lockingScript, satoshis) {
579
- const signature = this.covenant.createSignature(this.tx, privateKey, inputIndex, lockingScript, satoshis);
580
-
581
- const unlockingScript = new bsv.Script()
589
+ signInput (inputIndex, privateKey, lockingScript, satoshis) {
590
+ const signature = this.covenant.createSignature(this.tx, privateKey, inputIndex, lockingScript, satoshis)
591
+
592
+ const unlockingScript = new Script()
582
593
  .add(signature)
583
- .add(privateKey.publicKey.toBuffer());
584
-
585
- this.tx.inputs[inputIndex].setScript(unlockingScript);
586
- return this;
594
+ .add(privateKey.publicKey.toBuffer())
595
+
596
+ this.tx.inputs[inputIndex].setScript(unlockingScript)
597
+ return this
587
598
  }
588
599
 
589
600
  /**
590
601
  * Access underlying BSV transaction
591
602
  */
592
- getTransaction() {
593
- return this.tx;
603
+ getTransaction () {
604
+ return this.tx
594
605
  }
595
606
 
596
607
  /**
597
608
  * Verify transaction with enhanced error reporting
598
609
  */
599
- verify() {
610
+ verify () {
600
611
  try {
601
- return this.tx.verify();
612
+ return this.tx.verify()
602
613
  } catch (error) {
603
- console.error('Transaction validation error:', error.message);
604
- return false;
614
+ console.error('Transaction validation error:', error.message)
615
+ return false
605
616
  }
606
617
  }
607
618
  }
@@ -610,98 +621,98 @@ class CovenantTransaction {
610
621
  * Parsed preimage with convenient access methods
611
622
  */
612
623
  class CovenantPreimage {
613
- constructor(preimageHex) {
614
- this.hex = preimageHex;
615
- this.buffer = Buffer.from(preimageHex, 'hex');
616
- this.parseFields();
617
- }
624
+ constructor (preimageHex) {
625
+ this.hex = preimageHex
626
+ this.buffer = Buffer.from(preimageHex, 'hex')
627
+ this.parseFields()
628
+ }
618
629
 
619
- parseFields() {
620
- let offset = 0;
621
-
622
- // BIP143 sighash preimage structure (detailed field-by-field parsing)
623
- // Field 1: nVersion (4 bytes, little-endian)
624
- this.nVersion = this.buffer.subarray(offset, offset + 4);
625
- this.nVersionValue = this.buffer.readUInt32LE(offset);
626
- offset += 4;
627
-
628
- // Field 2: hashPrevouts (32 bytes) - double SHA256 of all input outpoints
629
- this.hashPrevouts = this.buffer.subarray(offset, offset + 32);
630
- offset += 32;
631
-
632
- // Field 3: hashSequence (32 bytes) - double SHA256 of all input sequences
633
- this.hashSequence = this.buffer.subarray(offset, offset + 32);
634
- offset += 32;
635
-
636
- // Field 4: outpoint (36 bytes) - prevTxId (32) + outputIndex (4, little-endian)
637
- this.outpoint = this.buffer.subarray(offset, offset + 36);
638
- this.prevTxId = this.buffer.subarray(offset, offset + 32);
639
- offset += 32;
640
- this.outputIndex = this.buffer.subarray(offset, offset + 4);
641
- this.outputIndexValue = this.buffer.readUInt32LE(offset);
642
- offset += 4;
643
-
644
- // Field 5: scriptCode - variable length with proper parsing
645
- const scriptLen = this.readVarInt(offset);
646
- offset += this.getVarIntLength(scriptLen);
647
- this.scriptCode = this.buffer.subarray(offset, offset + scriptLen);
648
- offset += scriptLen;
649
-
650
- // Field 6: amount (8 bytes, little-endian) - value of UTXO being spent
651
- this.amount = this.buffer.subarray(offset, offset + 8);
652
- this.amountValue = this.buffer.readBigUInt64LE(offset);
653
- offset += 8;
654
-
655
- // Field 7: nSequence (4 bytes, little-endian)
656
- this.nSequence = this.buffer.subarray(offset, offset + 4);
657
- this.nSequenceValue = this.buffer.readUInt32LE(offset);
658
- offset += 4;
659
-
660
- // Field 8: hashOutputs (32 bytes) - double SHA256 of all outputs
661
- this.hashOutputs = this.buffer.subarray(offset, offset + 32);
662
- offset += 32;
663
-
664
- // Field 9: nLockTime (4 bytes, little-endian)
665
- this.nLockTime = this.buffer.subarray(offset, offset + 4);
666
- this.nLockTimeValue = this.buffer.readUInt32LE(offset);
667
- offset += 4;
668
-
669
- // Field 10: sighashType (4 bytes, little-endian)
670
- this.sighashType = this.buffer.subarray(offset, offset + 4);
671
- this.sighashTypeValue = this.buffer.readUInt32LE(offset);
672
- offset += 4;
673
-
674
- // Validate preimage structure (typical 108+ bytes)
675
- this.isValid = offset === this.buffer.length && this.buffer.length >= 108;
676
- }
677
-
678
- readVarInt(offset) {
679
- const first = this.buffer.readUInt8(offset);
680
- if (first < 0xfd) return first;
681
- if (first === 0xfd) return this.buffer.readUInt16LE(offset + 1);
682
- if (first === 0xfe) return this.buffer.readUInt32LE(offset + 1);
683
- if (first === 0xff) return this.buffer.readBigUInt64LE(offset + 1);
684
- }
685
-
686
- getVarIntLength(value) {
687
- if (value < 0xfd) return 1;
688
- if (value <= 0xffff) return 3;
689
- if (value <= 0xffffffff) return 5;
690
- return 9;
691
- }
630
+ parseFields () {
631
+ let offset = 0
632
+
633
+ // BIP143 sighash preimage structure (detailed field-by-field parsing)
634
+ // Field 1: nVersion (4 bytes, little-endian)
635
+ this.nVersion = this.buffer.subarray(offset, offset + 4)
636
+ this.nVersionValue = this.buffer.readUInt32LE(offset)
637
+ offset += 4
638
+
639
+ // Field 2: hashPrevouts (32 bytes) - double SHA256 of all input outpoints
640
+ this.hashPrevouts = this.buffer.subarray(offset, offset + 32)
641
+ offset += 32
642
+
643
+ // Field 3: hashSequence (32 bytes) - double SHA256 of all input sequences
644
+ this.hashSequence = this.buffer.subarray(offset, offset + 32)
645
+ offset += 32
646
+
647
+ // Field 4: outpoint (36 bytes) - prevTxId (32) + outputIndex (4, little-endian)
648
+ this.outpoint = this.buffer.subarray(offset, offset + 36)
649
+ this.prevTxId = this.buffer.subarray(offset, offset + 32)
650
+ offset += 32
651
+ this.outputIndex = this.buffer.subarray(offset, offset + 4)
652
+ this.outputIndexValue = this.buffer.readUInt32LE(offset)
653
+ offset += 4
654
+
655
+ // Field 5: scriptCode - variable length with proper parsing
656
+ const scriptLen = this.readVarInt(offset)
657
+ offset += this.getVarIntLength(scriptLen)
658
+ this.scriptCode = this.buffer.subarray(offset, offset + scriptLen)
659
+ offset += scriptLen
660
+
661
+ // Field 6: amount (8 bytes, little-endian) - value of UTXO being spent
662
+ this.amount = this.buffer.subarray(offset, offset + 8)
663
+ this.amountValue = this.buffer.readBigUInt64LE(offset)
664
+ offset += 8
665
+
666
+ // Field 7: nSequence (4 bytes, little-endian)
667
+ this.nSequence = this.buffer.subarray(offset, offset + 4)
668
+ this.nSequenceValue = this.buffer.readUInt32LE(offset)
669
+ offset += 4
670
+
671
+ // Field 8: hashOutputs (32 bytes) - double SHA256 of all outputs
672
+ this.hashOutputs = this.buffer.subarray(offset, offset + 32)
673
+ offset += 32
674
+
675
+ // Field 9: nLockTime (4 bytes, little-endian)
676
+ this.nLockTime = this.buffer.subarray(offset, offset + 4)
677
+ this.nLockTimeValue = this.buffer.readUInt32LE(offset)
678
+ offset += 4
679
+
680
+ // Field 10: sighashType (4 bytes, little-endian)
681
+ this.sighashType = this.buffer.subarray(offset, offset + 4)
682
+ this.sighashTypeValue = this.buffer.readUInt32LE(offset)
683
+ offset += 4
684
+
685
+ // Validate preimage structure (typical 108+ bytes)
686
+ this.isValid = offset === this.buffer.length && this.buffer.length >= 108
687
+ }
688
+
689
+ readVarInt (offset) {
690
+ const first = this.buffer.readUInt8(offset)
691
+ if (first < 0xfd) return first
692
+ if (first === 0xfd) return this.buffer.readUInt16LE(offset + 1)
693
+ if (first === 0xfe) return this.buffer.readUInt32LE(offset + 1)
694
+ if (first === 0xff) return this.buffer.readBigUInt64LE(offset + 1)
695
+ }
696
+
697
+ getVarIntLength (value) {
698
+ if (value < 0xfd) return 1
699
+ if (value <= 0xffff) return 3
700
+ if (value <= 0xffffffff) return 5
701
+ return 9
702
+ }
692
703
  }
693
704
 
694
705
  /**
695
706
  * Covenant validation result
696
707
  */
697
708
  class CovenantValidation {
698
- constructor(isValid, message) {
699
- this.isValid = isValid;
700
- this.message = message;
709
+ constructor (isValid, message) {
710
+ this.isValid = isValid
711
+ this.message = message
701
712
  }
702
713
 
703
- toString() {
704
- return `${this.isValid ? 'VALID' : 'INVALID'}: ${this.message}`;
714
+ toString () {
715
+ return `${this.isValid ? 'VALID' : 'INVALID'}: ${this.message}`
705
716
  }
706
717
  }
707
718
 
@@ -710,4 +721,4 @@ module.exports = {
710
721
  CovenantTransaction,
711
722
  CovenantPreimage,
712
723
  CovenantValidation
713
- };
724
+ }