@smartledger/bsv 5.4.2 → 5.5.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 (93) hide show
  1. package/.mocharc.json +5 -0
  2. package/CHANGELOG.md +66 -0
  3. package/README.md +28 -8
  4. package/bsv-covenant.min.js +8 -8
  5. package/bsv-gdaf.min.js +11 -11
  6. package/bsv-ltp.min.js +11 -11
  7. package/bsv-smartcontract.min.js +8 -8
  8. package/bsv.bundle.js +11 -11
  9. package/bsv.min.js +11 -11
  10. package/lib/smart_contract/authorizers.js +159 -0
  11. package/lib/smart_contract/covenant_helpers.js +3 -3
  12. package/lib/smart_contract/dsl.js +1 -1
  13. package/lib/smart_contract/index.js +9 -8
  14. package/lib/smart_contract/pels.js +1 -0
  15. package/lib/smart_contract/pushtx.js +51 -7
  16. package/lib/smart_contract/token.js +179 -35
  17. package/package.json +3 -1
  18. package/test/address.js +629 -0
  19. package/test/block/block.js +239 -0
  20. package/test/block/blockheader.js +270 -0
  21. package/test/block/merkleblock.js +207 -0
  22. package/test/cli/smoke.js +261 -0
  23. package/test/credentials-test.js +329 -0
  24. package/test/crypto/bn.js +168 -0
  25. package/test/crypto/ecdsa.js +328 -0
  26. package/test/crypto/elliptic-fixed.js +61 -0
  27. package/test/crypto/hash.browser.js +121 -0
  28. package/test/crypto/hash.js +122 -0
  29. package/test/crypto/point.js +193 -0
  30. package/test/crypto/random.js +32 -0
  31. package/test/crypto/security.js +127 -0
  32. package/test/crypto/shamir.js +169 -0
  33. package/test/crypto/signature.js +318 -0
  34. package/test/data/bip69.json +215 -0
  35. package/test/data/bitcoind/base58_keys_invalid.json +152 -0
  36. package/test/data/bitcoind/base58_keys_valid.json +452 -0
  37. package/test/data/bitcoind/blocks.json +27 -0
  38. package/test/data/bitcoind/script_tests.json +2244 -0
  39. package/test/data/bitcoind/sig_canonical.json +7 -0
  40. package/test/data/bitcoind/sig_noncanonical.json +22 -0
  41. package/test/data/bitcoind/tx_invalid.json +177 -0
  42. package/test/data/bitcoind/tx_valid.json +224 -0
  43. package/test/data/blk86756-testnet.dat +0 -0
  44. package/test/data/blk86756-testnet.js +12 -0
  45. package/test/data/blk86756-testnet.json +684 -0
  46. package/test/data/ecdsa.json +230 -0
  47. package/test/data/merkleblocks.js +486 -0
  48. package/test/data/messages.json +22 -0
  49. package/test/data/sighash.json +1004 -0
  50. package/test/data/tx_creation.json +85 -0
  51. package/test/ecies/bitcore-ecies.js +170 -0
  52. package/test/ecies/electrum-ecies.js +206 -0
  53. package/test/encoding/base58.js +131 -0
  54. package/test/encoding/base58check.js +136 -0
  55. package/test/encoding/bufferreader.js +328 -0
  56. package/test/encoding/bufferwriter.js +160 -0
  57. package/test/encoding/varint.js +104 -0
  58. package/test/gdaf/canonicalize.js +140 -0
  59. package/test/hdkeys.js +365 -0
  60. package/test/hdprivatekey.js +330 -0
  61. package/test/hdpublickey.js +293 -0
  62. package/test/index.js +16 -0
  63. package/test/ltp/right.js +198 -0
  64. package/test/message/message.js +190 -0
  65. package/test/mnemonic/data/fixtures.json +300 -0
  66. package/test/mnemonic/mnemonic.js +245 -0
  67. package/test/mnemonic/mocha.opts +1 -0
  68. package/test/mnemonic/pbkdf2.test.js +43 -0
  69. package/test/networks.js +162 -0
  70. package/test/opcode.js +161 -0
  71. package/test/privatekey.js +430 -0
  72. package/test/publickey.js +411 -0
  73. package/test/script/genesis_limits.js +80 -0
  74. package/test/script/interpreter.js +723 -0
  75. package/test/script/script.js +1256 -0
  76. package/test/script/string_ops.js +72 -0
  77. package/test/smart_contract/covenants.js +247 -0
  78. package/test/smart_contract/dsl_debugger.js +103 -0
  79. package/test/smart_contract/token_generalized.js +187 -0
  80. package/test/transaction/deserialize.js +33 -0
  81. package/test/transaction/input/input.js +92 -0
  82. package/test/transaction/input/multisig.js +174 -0
  83. package/test/transaction/input/multisigscripthash.js +111 -0
  84. package/test/transaction/input/publickey.js +68 -0
  85. package/test/transaction/input/publickeyhash.js +59 -0
  86. package/test/transaction/output.js +185 -0
  87. package/test/transaction/sighash.js +71 -0
  88. package/test/transaction/signature.js +127 -0
  89. package/test/transaction/transaction.js +1299 -0
  90. package/test/transaction/unspentoutput.js +92 -0
  91. package/test/util/js.js +76 -0
  92. package/test/util/preconditions.js +79 -0
  93. package/test/vcjwt/interop.js +126 -0
package/.mocharc.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "recursive": true,
3
+ "timeout": 8000,
4
+ "spec": "test/**/*.js"
5
+ }
package/CHANGELOG.md CHANGED
@@ -5,6 +5,72 @@ All notable changes to SmartLedger-BSV will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [5.5.1] - 2026-06-25
9
+
10
+ Patch release. Credibility/transparency cleanup — no API or behavior changes.
11
+
12
+ ### Changed
13
+
14
+ - **Tests now ship in the published tarball.** `test/` and `.mocharc.json` are
15
+ added to `package.json` `files`, so a consumer can independently run the suite
16
+ (`npm test`, with mocha/chai installed) instead of taking "4267 passing" on
17
+ faith.
18
+ - **`SmartContract.version` tracks the package version** (read from
19
+ `package.json`) instead of a hardcoded `'v1.0.0'` that had drifted from the
20
+ 5.x package.
21
+ - **Dropped the `PRODUCTION_READY` feature flag** — it asserted a claim rather
22
+ than describing a capability.
23
+ - **Softened an unverifiable comment** in `covenant_helpers.js` ("covenants
24
+ verified here have been deployed and spent on BSV mainnet") to an accurate
25
+ statement: the local verify flags mirror mainnet relay/consensus policy, so a
26
+ covenant that passes is expected to be accepted on broadcast.
27
+
28
+ ## [5.5.0] - 2026-06-25
29
+
30
+ Minor release. Closes a front-running theft flaw in the ownership-token covenant
31
+ and generalizes the covenant core into a pluggable, multi-output state machine.
32
+
33
+ ### Security
34
+
35
+ - **`SmartContract.Token` ownership is now ECDSA-authorized.** The previous design
36
+ gated a transfer on revealing `ownerSecret` with `SHA256(ownerSecret) ==
37
+ ownerHash` — a hash-lock. The secret was exposed in the mempool on the first
38
+ spend and the spender freely chose the next owner, so a watcher could lift the
39
+ revealed secret and broadcast a competing spend redirecting the token to
40
+ themselves. Ownership is now a key: state is `HASH160(ownerPubKey)` and a
41
+ transfer requires the current owner's signature over the spend
42
+ (`OP_CHECKSIGVERIFY`), which commits via `SIGHASH_ALL` `hashOutputs` to the
43
+ exact recreated output — so altering the destination invalidates the proof.
44
+
45
+ ### Added
46
+
47
+ - **Pluggable ownership — `SmartContract.Authorizers`.** Token ownership is always
48
+ a 20-byte commitment, so the transfer plumbing is identical across schemes:
49
+ - `singleKey()` — signature over the spend (the model above).
50
+ - `multisig(m, n)` — m-of-n group ownership; the key set is committed by hashing
51
+ the canonical redeem script, revealed at spend, bound to the commitment, and
52
+ checked with `OP_CHECKMULTISIG`.
53
+ - `predicate({ commit, emit, unlockArgs })` — escape hatch for custom schemes.
54
+ - **Multi-output (N-output) tokens** — `Token.ownershipTokenMulti` /
55
+ `unlockTransferMulti` let the recreated token output sit among other outputs
56
+ (payments, change, data); the spender reveals the surrounding output bytes and
57
+ the covenant binds them into the committed `hashOutputs`.
58
+ - **`PushTx.grind` configurable nonce** — `{ field: 'nLockTime' | 'sequence' }`,
59
+ so a covenant pinning `nLockTime` for a CLTV timelock can grind the input
60
+ sequence instead. `PushTx.assertSighashAll()` guard added to token/PELS scripts.
61
+
62
+ ### Changed (breaking, `SmartContract.Token` only)
63
+
64
+ - `Token.ownershipToken(fee, owner)` — `owner` is now `HASH160(pubkey)` (use
65
+ `Token.ownerId(key)`), not `SHA256(secret)`.
66
+ - `Token.unlockTransfer(signer, newOwnerHash, spend, satoshis, lockingScript[, opts])`
67
+ — now takes the owner key and the spend (it grinds and signs), not a precomputed
68
+ preimage. The rest of the package's API is unchanged and fully compatible.
69
+
70
+ ### Notes
71
+
72
+ - Full suite **4267 passing**; `lib/` and `test/` lint clean.
73
+
8
74
  ## [5.4.2] - 2026-06-25
9
75
 
10
76
  Patch release. Dependency security maintenance — no API or behavior changes.
package/README.md CHANGED
@@ -37,9 +37,9 @@ SC.enableGenesis() // post-Genesis limits (OP_PUSH_TX need
37
37
  // Self-replicating covenant — every spend recreates the same script (value − fee).
38
38
  const lock = SC.perpetualCovenant(500)
39
39
 
40
- // Stateful ownership token (NFT) — transfer requires the owner's secret,
41
- // rewrites state, perpetuates the token code.
42
- const token = SC.ownershipToken(500, ownerHash)
40
+ // Stateful ownership token (NFT) — transfer requires the owner's ECDSA signature
41
+ // over the spend, rewrites state, perpetuates the token code.
42
+ const token = SC.ownershipToken(500, ownerHash) // ownerHash = SC.Token.ownerId(ownerKey)
43
43
 
44
44
  // Value covenant — forces spend outputs to match a specific hashOutputs.
45
45
  const vlock = SC.valueCovenant(SC.PushTx.hashOutputs(requiredOutputs))
@@ -54,7 +54,8 @@ const ok = SC.verifyScript(unlockScript, lockingScript, tx, inputIndex, satoshis
54
54
  |---|---|
55
55
  | `PushTx` | nChain WP1605 OP_PUSH_TX — `authenticator()`, `valueCovenant()`, `hashOutputs()`, `extractHashOutputs()`, `grind()` |
56
56
  | `PELS` | Perpetually Enforcing Locking Scripts — `perpetualCovenant(fee)` |
57
- | `Token` | Stateful ownership token (NFT) — `ownershipToken(fee, ownerHash)` |
57
+ | `Token` | Stateful ownership token (NFT) — `ownershipToken(fee, owner[, auth])`, `ownershipTokenMulti(owner[, auth])`, `ownerId(key)`, `unlockTransfer(...)`, `unlockTransferMulti(...)` |
58
+ | `Authorizers` | Pluggable token ownership — `singleKey()`, `multisig(m, n)`, `predicate({...})` |
58
59
  | `Locks` | Hash-lock, P2PKH, CLTV time-lock, m-of-n multisig, HTLC |
59
60
  | `CovenantHelpers` | Consensus-flag `verify()` harness, raw BIP-143 preimage, signing, fund/spend scaffolding |
60
61
 
@@ -729,11 +730,30 @@ const pels = SC.perpetualCovenant(500) // fee in satoshis deducted each hop
729
730
 
730
731
  ### Ownership Tokens (NFT) — v4.2.0 API
731
732
  ```javascript
732
- // Stateful ownership token. Owner is carried as on-chain state; transfer
733
- // requires the current owner's secret and rewrites state, perpetuating
734
- // the token code across the chain of spends.
735
- const ownerHash = bsv.crypto.Hash.sha256ripemd160(currentOwnerPubKey.toBuffer())
733
+ // Stateful ownership token. Owner is carried as on-chain state (HASH160 of the
734
+ // owner's public key); transfer requires the current owner's ECDSA SIGNATURE over
735
+ // the spend (OP_CHECKSIG) and rewrites state, perpetuating the token code across
736
+ // the chain of spends. The signature commits to the chosen next owner, so a
737
+ // mempool watcher cannot redirect a pending transfer (no hash-lock front-running).
738
+ const ownerHash = SC.Token.ownerId(currentOwnerKey) // = HASH160(pubkey)
736
739
  const token = SC.ownershipToken(500, ownerHash)
740
+ // To spend it forward to `nextOwnerHash`, the current owner signs:
741
+ // tokenInput.setScript(SC.Token.unlockTransfer(currentOwnerKey, nextOwnerHash, spendTx, sats, token))
742
+
743
+ // Pluggable ownership — the SAME covenant, owned by an m-of-n group. Ownership is
744
+ // committed as a 20-byte hash either way, so the transfer plumbing is identical.
745
+ const ms = SC.Authorizers.multisig(2, 3)
746
+ const groupToken = SC.Token.ownershipToken(500, ms.commit([pkA, pkB, pkC]), ms)
747
+ // transfer requires any 2 of the 3 keys:
748
+ // SC.Token.unlockTransfer({ keys: [pkA, pkB, pkC], signWith: [skA, skC] },
749
+ // nextOwnerHash, spendTx, sats, groupToken, { auth: ms })
750
+ // Custom schemes: SC.Authorizers.predicate({ commit, emit, unlockArgs }).
751
+
752
+ // N-output: recreate the token alongside other outputs (payments, change, data).
753
+ // The spender reveals the surrounding output bytes; the covenant binds them all.
754
+ const multi = SC.Token.ownershipTokenMulti(ownerHash)
755
+ // SC.Token.unlockTransferMulti(currentOwnerKey, nextOwnerHash, spendTx, sats, multi,
756
+ // { before: serializedOutputsBeforeToken, after: serializedOutputsAfterToken, tokenValue: le8(value) })
737
757
  ```
738
758
 
739
759
  ### End-to-end verification