@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
@@ -0,0 +1,243 @@
1
+ 'use strict'
2
+ /**
3
+ * SmartContract.PushTx — a correct, interpreter-verified OP_PUSH_TX (nChain
4
+ * WP1605) for Bitcoin SV.
5
+ *
6
+ * The locking script GENERATES an ECDSA signature in-script from a preimage the
7
+ * spender pushed, then OP_CHECKSIG verifies it against a fixed public key.
8
+ * OP_CHECKSIG only passes if the message it derives internally (the genuine
9
+ * BIP-143 sighash of THIS spend) equals HASH256(preimage) — so a passing check
10
+ * proves the pushed preimage IS this transaction, letting a script read and
11
+ * constrain its own spending transaction.
12
+ *
13
+ * Optimal parameters: private key a = 1, ephemeral k = 1 => r = Gx,
14
+ * s = (e + Gx) mod n, pubkey P = 02||Gx, e = HASH256(preimage).
15
+ *
16
+ * Requires post-Genesis limits — call SmartContract.enableGenesis() (a.k.a
17
+ * Interpreter.useGenesisLimits()) before verifying these scripts.
18
+ */
19
+
20
+ var Script = require('../script')
21
+ var Opcode = require('../opcode')
22
+ var Signature = require('../crypto/signature')
23
+ var BN = require('../crypto/bn')
24
+ var Hash = require('../crypto/hash')
25
+ var H = require('./helpers')
26
+
27
+ var SIGHASH = H.SIGHASH
28
+ var scriptNum = H.scriptNum
29
+
30
+ // secp256k1 constants (big-endian)
31
+ var Gx = Buffer.from('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', 'hex')
32
+ var N = new BN('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141', 16)
33
+ var PUBKEY = Buffer.concat([Buffer.from([0x02]), Gx]) // compressed P = G (y even)
34
+
35
+ // script-number (little-endian) forms
36
+ var gxLe = Buffer.from(Gx).reverse() // 32B, top 0x79 => positive
37
+ var N_LE = Buffer.concat([Buffer.from(N.toBuffer()).reverse(), Buffer.from([0x00])]) // 33B positive
38
+
39
+ // fixed DER prefix: SEQUENCE(0x44) INTEGER(0x20) r=Gx INTEGER(0x20)
40
+ var DER_PREFIX = Buffer.concat([Buffer.from([0x30, 0x44, 0x02, 0x20]), Gx, Buffer.from([0x02, 0x20])])
41
+
42
+ /** Reverse a fixed n-byte buffer on top of the stack (big-endian <-> little-endian). */
43
+ function reverseBytes (script, n) {
44
+ var i
45
+ for (i = 0; i < n - 1; i++) script.add(Opcode.OP_1).add(Opcode.OP_SPLIT)
46
+ for (i = 0; i < n - 1; i++) script.add(Opcode.OP_SWAP).add(Opcode.OP_CAT)
47
+ return script
48
+ }
49
+
50
+ // Common SIGHASH flag combinations (all include FORKID, required on BSV). The
51
+ // marketplace/partially-signed pattern uses SINGLE|ANYONECANPAY: the signer commits
52
+ // only to its own input and its own output (the output at the same index), leaving
53
+ // a counterparty free to add funding inputs and change outputs without invalidating
54
+ // the signature.
55
+ var SIGHASH_ALL_FORKID = Signature.SIGHASH_ALL | Signature.SIGHASH_FORKID // 0x41
56
+ var SIGHASH_SINGLE_FORKID = Signature.SIGHASH_SINGLE | Signature.SIGHASH_FORKID // 0x43
57
+ var SIGHASH_SINGLE_ANYONECANPAY_FORKID =
58
+ Signature.SIGHASH_SINGLE | Signature.SIGHASH_ANYONECANPAY | Signature.SIGHASH_FORKID // 0xc3
59
+ // ALL|ANYONECANPAY commits to ALL outputs (so the covenant can pin the FULL output
60
+ // set) while leaving inputs open for a counterparty to add funding. This is the flag
61
+ // the 1Sat Ordinals OrdLock uses: the buyer supplies the surrounding outputs and the
62
+ // covenant binds the seller's payment output into the committed hashOutputs.
63
+ var SIGHASH_ALL_ANYONECANPAY_FORKID =
64
+ Signature.SIGHASH_ALL | Signature.SIGHASH_ANYONECANPAY | Signature.SIGHASH_FORKID // 0xc1
65
+
66
+ /**
67
+ * Append the in-script signature generator + verifier ("PUSH_TX core").
68
+ * Pre: top of stack = preimage. Post: top = OP_CHECKSIG result.
69
+ *
70
+ * @param {Script} script
71
+ * @param {object} [opts]
72
+ * @param {number} [opts.sighashType=0x41] the SIGHASH flag byte baked into the
73
+ * synthetic signature. OP_CHECKSIG derives the spend's sighash using THIS flag,
74
+ * so the spender must push the matching BIP-143 preimage (grind with the same
75
+ * sighashType). Defaults to SIGHASH_ALL|FORKID — existing covenants are unchanged.
76
+ */
77
+ function pushTxCore (script, opts) {
78
+ var sighashType = (opts && opts.sighashType) || SIGHASH
79
+ script.add(Opcode.OP_HASH256) // z = HASH256(preimage), 32B BE
80
+ reverseBytes(script, 32) // -> little-endian = e. The grind guarantees e is
81
+ // already positive and minimally encoded (z[0] in 0x01..0x7f), so NO 0x00 sign
82
+ // byte is appended — keeping the script MINIMALDATA-clean (mainnet-relayable).
83
+ script.add(gxLe).add(Opcode.OP_ADD) // e + Gx
84
+ script.add(N_LE).add(Opcode.OP_MOD) // s = (e + Gx) mod n
85
+ script.add(scriptNum(32)).add(Opcode.OP_NUM2BIN) // s -> 32-byte LE
86
+ reverseBytes(script, 32) // -> big-endian (DER INTEGER body) ; stack: [s_be]
87
+ // Build the DER signature and the pubkey from a SINGLE Gx push (Gx is both the
88
+ // r-value inside the DER prefix and the body of the 02||Gx pubkey). Sharing it
89
+ // via the altstack saves a 32-byte constant vs. embedding Gx twice.
90
+ script.add(Gx).add(Opcode.OP_DUP) // [s_be, Gx, Gx]
91
+ script.add(Opcode.OP_2).add(Opcode.OP_SWAP).add(Opcode.OP_CAT) // pubkey = 02||Gx (OP_2 = minimal push of 0x02)
92
+ script.add(Opcode.OP_TOALTSTACK) // park pubkey ; [s_be, Gx]
93
+ script.add(Buffer.from([0x30, 0x44, 0x02, 0x20])).add(Opcode.OP_SWAP).add(Opcode.OP_CAT) // 30440220||Gx
94
+ script.add(Buffer.from([0x02, 0x20])).add(Opcode.OP_CAT) // ||0220 => DER prefix
95
+ script.add(Opcode.OP_SWAP).add(Opcode.OP_CAT) // DER prefix || s_be
96
+ script.add(Buffer.from([sighashType])).add(Opcode.OP_CAT) // || sighash flag => full DER sig
97
+ script.add(Opcode.OP_FROMALTSTACK).add(Opcode.OP_CHECKSIG) // pubkey ; verify against P = G
98
+ return script
99
+ }
100
+
101
+ /** Bare authenticator script: unlock with the (grindable) preimage. */
102
+ function authenticator () {
103
+ return pushTxCore(new Script())
104
+ }
105
+
106
+ /** Extract the committed hashOutputs (item 9, offsetFromEnd 40, len 32) from a preimage on-stack. */
107
+ function extractHashOutputs (script) {
108
+ // last 40 bytes, then the first 32 of those = hashOutputs. (BSV string opcodes.)
109
+ script.add(scriptNum(40)).add(Opcode.OP_RIGHT).add(scriptNum(32)).add(Opcode.OP_LEFT)
110
+ return script
111
+ }
112
+
113
+ // The BIP-143 preimage ends with nHashType as a 4-byte LE word; for SIGHASH_ALL|
114
+ // FORKID that word is 0x41 00 00 00. assertSighashType builds this word per flag.
115
+
116
+ /**
117
+ * Assert the spend is SIGHASH_ALL|FORKID (0x41). Pre/Post: top of stack = preimage
118
+ * (left untouched). These covenants read fixed offsets (104 / 52 / 40) that are
119
+ * meaningful only for the 0x41 layout, and the OP_PUSH_TX core already pins the
120
+ * flag implicitly (its synthetic sig carries 0x41, so OP_CHECKSIG only accepts a
121
+ * preimage hashing to the 0x41 sighash). Note the offsets themselves are invariant
122
+ * in the number of INPUTS — hashPrevouts/hashSequence are digests of all inputs,
123
+ * so the preimage is the same length for 1 or N inputs; the covenant simply does
124
+ * not constrain sibling inputs, by design. What it does assume is a single
125
+ * recreated OUTPUT (HASH256(nextOutput) == hashOutputs). This guard makes the
126
+ * flag assumption explicit and fails fast — and survives any refactor of the core.
127
+ */
128
+ function assertSighashAll (script) {
129
+ return assertSighashType(script, SIGHASH)
130
+ }
131
+
132
+ /**
133
+ * Assert the spend uses a specific SIGHASH flag. Pre/Post: top of stack = preimage
134
+ * (left untouched). The BIP-143 preimage's trailing 4-byte LE nHashType word must
135
+ * equal `sighashType`. Use with pushTxCore({ sighashType }) + grind({ sighashType })
136
+ * to build covenants under SIGHASH_SINGLE|ANYONECANPAY (marketplace) etc.
137
+ */
138
+ function assertSighashType (script, sighashType) {
139
+ var word = Buffer.from([sighashType & 0xff, 0x00, 0x00, 0x00])
140
+ script.add(Opcode.OP_DUP).add(scriptNum(4)).add(Opcode.OP_RIGHT)
141
+ .add(word).add(Opcode.OP_EQUALVERIFY)
142
+ return script
143
+ }
144
+
145
+ /** BIP-143 hashOutputs (SIGHASH_ALL) for a set of Transaction.Output objects. */
146
+ function hashOutputs (outputs) {
147
+ var ser = Buffer.concat(outputs.map(function (o) { return o.toBufferWriter().toBuffer() }))
148
+ return Hash.sha256sha256(ser)
149
+ }
150
+
151
+ /**
152
+ * Value/output covenant: the spend is valid only if its outputs hash to
153
+ * `expectedHashOutputs` — coins can only go where the covenant says.
154
+ */
155
+ function valueCovenant (expectedHashOutputs) {
156
+ var script = new Script().add(Opcode.OP_DUP)
157
+ pushTxCore(script)
158
+ script.add(Opcode.OP_VERIFY)
159
+ extractHashOutputs(script)
160
+ script.add(Buffer.from(expectedHashOutputs)).add(Opcode.OP_EQUAL)
161
+ return script
162
+ }
163
+
164
+ // floor(n/2) — the canonical low-S boundary (matches Signature.hasLowS()).
165
+ var HALF_N = new BN('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0', 'hex')
166
+
167
+ /**
168
+ * Compute s = (HASH256(preimage)+Gx) mod n; return its 32-byte BE form, or null
169
+ * if the resulting signature would not be a clean, CANONICAL (low-S) DER.
170
+ * Requiring s <= n/2 makes the in-script signature non-malleable and standard,
171
+ * so it passes nodes enforcing SCRIPT_VERIFY_LOW_S — at zero script-size cost
172
+ * (the burden is on the spender's grind, not extra opcodes).
173
+ */
174
+ function sFromPreimage (preimage) {
175
+ var z = Hash.sha256sha256(preimage)
176
+ // Script no longer sign-extends z, so e (= reverse(z) as a number) must be
177
+ // positive AND minimally encoded: its little-endian MSB (= z[0]) in 0x01..0x7f.
178
+ // This keeps the locking script MINIMALDATA-clean (mainnet-relayable).
179
+ if (z[0] < 0x01 || z[0] > 0x7f) return null
180
+ var s = new BN(z).add(new BN(Gx)).mod(N)
181
+ if (s.gt(HALF_N)) return null // enforce low-S (canonical / non-malleable)
182
+ var sBE = s.toBuffer('be', 32)
183
+ return (sBE[0] >= 0x01) ? sBE : null // s <= n/2 already guarantees sBE[0] <= 0x7f
184
+ }
185
+
186
+ /**
187
+ * Grind a malleable field of the spend until the in-script OP_PUSH_TX signature
188
+ * is a clean, canonical (low-S) fixed-length DER. Returns { preimage, tries,
189
+ * field, nonce }; mutates the chosen field on `spend`.
190
+ *
191
+ * @param {object} [opts] grind options (a bare number is accepted as legacy maxTries):
192
+ * - maxTries {number} attempts before giving up (default 5000).
193
+ * - start {number} first nonce value to try (default 0).
194
+ * - field {'nLockTime'|'sequence'} which field carries the grind nonce
195
+ * (default 'nLockTime'). Use 'sequence' when the covenant pins nLockTime for
196
+ * a real CLTV absolute timelock: the input's sequence is swept down from
197
+ * 0xfffffffe (kept non-final, so CLTV still triggers) instead of clobbering
198
+ * nLockTime. (Not for CSV/relative-locktime covenants, which encode meaning
199
+ * in the sequence number itself.)
200
+ */
201
+ function grind (spend, inputIndex, lockingScript, satoshis, opts) {
202
+ if (typeof opts === 'number') opts = { maxTries: opts } // back-compat: legacy maxTries arg
203
+ opts = opts || {}
204
+ var maxTries = opts.maxTries || 5000
205
+ var start = opts.start || 0
206
+ var field = opts.field || 'nLockTime'
207
+ var sighashType = opts.sighashType || SIGHASH
208
+ if (field !== 'nLockTime' && field !== 'sequence') {
209
+ throw new Error("grind field must be 'nLockTime' or 'sequence'")
210
+ }
211
+ var input = spend.inputs[inputIndex]
212
+ for (var i = 0; i < maxTries; i++) {
213
+ var nonce = start + i
214
+ if (field === 'nLockTime') spend.nLockTime = nonce
215
+ else input.sequenceNumber = 0xfffffffe - nonce // stay < 0xffffffff (non-final)
216
+ var preimage = H.rawPreimage(spend, inputIndex, lockingScript, satoshis, sighashType)
217
+ if (sFromPreimage(preimage)) return { preimage: preimage, tries: i + 1, field: field, nonce: nonce }
218
+ }
219
+ throw new Error('OP_PUSH_TX grind failed after ' + maxTries + ' tries')
220
+ }
221
+
222
+ module.exports = {
223
+ Gx: Gx,
224
+ N: N,
225
+ PUBKEY: PUBKEY,
226
+ gxLe: gxLe,
227
+ N_LE: N_LE,
228
+ DER_PREFIX: DER_PREFIX,
229
+ reverseBytes: reverseBytes,
230
+ pushTxCore: pushTxCore,
231
+ authenticator: authenticator,
232
+ extractHashOutputs: extractHashOutputs,
233
+ assertSighashAll: assertSighashAll,
234
+ assertSighashType: assertSighashType,
235
+ SIGHASH_ALL_FORKID: SIGHASH_ALL_FORKID,
236
+ SIGHASH_SINGLE_FORKID: SIGHASH_SINGLE_FORKID,
237
+ SIGHASH_SINGLE_ANYONECANPAY_FORKID: SIGHASH_SINGLE_ANYONECANPAY_FORKID,
238
+ SIGHASH_ALL_ANYONECANPAY_FORKID: SIGHASH_ALL_ANYONECANPAY_FORKID,
239
+ hashOutputs: hashOutputs,
240
+ valueCovenant: valueCovenant,
241
+ sFromPreimage: sFromPreimage,
242
+ grind: grind
243
+ }