@smartledger/bsv 7.9.0 → 7.10.1

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