@smartledger/bsv 8.3.1 → 9.1.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.
- package/CHANGELOG.md +228 -0
- package/README.md +152 -1031
- package/STABILITY.md +134 -0
- package/bsv-gdaf.min.js +58 -53
- package/bsv-ltp.min.js +23 -18
- package/bsv-script-helper.min.js +1 -1
- package/bsv-smartcontract.min.js +21 -21
- package/bsv.bundle.js +58 -53
- package/bsv.d.ts +0 -4
- package/bsv.min.js +58 -53
- package/docs/BRC220_BATCH_LEAF_AMENDMENT.md +82 -7
- package/docs/MODULE_REFERENCE_COMPLETE.md +27 -27
- package/docs/README.md +2 -1
- package/docs/THREAT_MODEL.md +10 -2
- package/docs/advanced/UTXO_MANAGER_GUIDE.md +1 -1
- package/docs/getting-started/INSTALLATION.md +23 -23
- package/docs/getting-started/QUICK_START.md +7 -7
- package/docs/migration/FROM_BSV_1_5_6.md +5 -5
- package/docs/proposals/10.0.0-package-split.md +131 -0
- package/index.js +15 -26
- package/lib/block/merkleblock.js +19 -5
- package/lib/covenant/helpers.js +34 -35
- package/lib/covenant/pushtx.js +2 -2
- package/lib/custom-script-helper.js +0 -16
- package/lib/hdprivatekey.js +15 -0
- package/lib/ordinals/ordlock.js +1 -1
- package/lib/script/interpreter.js +109 -1
- package/lib/smart_contract/builder.js +14 -0
- package/lib/smart_contract/debugger.js +2 -2
- package/lib/smart_contract/dsl.js +2 -2
- package/lib/smart_contract/index.js +0 -3
- package/lib/smart_contract/locks.js +1 -41
- package/lib/smart_contract/pels.js +1 -1
- package/lib/smart_contract/token.js +1 -1
- package/lib/util/deprecate.js +159 -0
- package/package.json +19 -82
- package/tools/gen-brc220-batch-vector.js +205 -0
- package/version.js +1 -1
- package/.mocharc.json +0 -5
- package/test/address.js +0 -629
- package/test/block/block.js +0 -239
- package/test/block/blockheader.js +0 -270
- package/test/block/merkleblock.js +0 -207
- package/test/build/bundle_crypto_shim.js +0 -104
- package/test/build/bundle_externals.js +0 -125
- package/test/build/bundle_smoke.js +0 -55
- package/test/build/esbuild_main.js +0 -65
- package/test/build/esm_wrapper.js +0 -73
- package/test/build/exports_resolution.js +0 -84
- package/test/build/version_sync.js +0 -14
- package/test/cli/smoke.js +0 -261
- package/test/consensus/base58-vectors.js +0 -120
- package/test/consensus/sv-script-vectors.js +0 -81
- package/test/consensus/sv-sighash-vectors.js +0 -51
- package/test/consensus/sv-tx-vectors.js +0 -48
- package/test/credentials-test.js +0 -332
- package/test/crypto/backend_selection.js +0 -126
- package/test/crypto/bn.js +0 -168
- package/test/crypto/ecdsa.js +0 -426
- package/test/crypto/elliptic-fixed.js +0 -61
- package/test/crypto/hash.browser.js +0 -121
- package/test/crypto/hash.js +0 -122
- package/test/crypto/point.js +0 -193
- package/test/crypto/random.js +0 -105
- package/test/crypto/security.js +0 -176
- package/test/crypto/shamir.js +0 -177
- package/test/crypto/shamir_rngcap.js +0 -29
- package/test/crypto/signature.js +0 -399
- package/test/data/bip69.json +0 -215
- package/test/data/bitcoin-sv/README.md +0 -170
- package/test/data/bitcoin-sv/base58_encode_decode.json +0 -14
- package/test/data/bitcoin-sv/base58_keys_invalid.json +0 -152
- package/test/data/bitcoin-sv/base58_keys_valid.json +0 -452
- package/test/data/bitcoin-sv/script_tests.json +0 -2591
- package/test/data/bitcoin-sv/sighash.json +0 -1003
- package/test/data/bitcoin-sv/tx_invalid.json +0 -285
- package/test/data/bitcoin-sv/tx_valid.json +0 -367
- package/test/data/bitcoind/base58_keys_invalid.json +0 -152
- package/test/data/bitcoind/base58_keys_valid.json +0 -452
- package/test/data/bitcoind/blocks.json +0 -27
- package/test/data/bitcoind/script_tests.json +0 -2244
- package/test/data/bitcoind/sig_canonical.json +0 -7
- package/test/data/bitcoind/sig_noncanonical.json +0 -22
- package/test/data/bitcoind/tx_invalid.json +0 -177
- package/test/data/bitcoind/tx_valid.json +0 -224
- package/test/data/blk86756-testnet.dat +0 -0
- package/test/data/blk86756-testnet.js +0 -12
- package/test/data/blk86756-testnet.json +0 -684
- package/test/data/ecdsa.json +0 -230
- package/test/data/merkleblocks.js +0 -486
- package/test/data/messages.json +0 -22
- package/test/data/sighash.json +0 -1004
- package/test/data/tx_creation.json +0 -85
- package/test/didweb/relationships.js +0 -144
- package/test/ecies/bitcore-ecies.js +0 -178
- package/test/ecies/electrum-ecies.js +0 -206
- package/test/encoding/base58.js +0 -131
- package/test/encoding/base58check.js +0 -145
- package/test/encoding/bufferreader.js +0 -328
- package/test/encoding/bufferwriter.js +0 -160
- package/test/encoding/varint.js +0 -104
- package/test/gdaf/anchor_no_key_leak.js +0 -146
- package/test/gdaf/anchor_spv.js +0 -163
- package/test/gdaf/canonicalization.js +0 -106
- package/test/gdaf/canonicalize.js +0 -140
- package/test/gdaf/zk_prover.js +0 -204
- package/test/hdkeys.js +0 -365
- package/test/hdprivatekey.js +0 -339
- package/test/hdpublickey.js +0 -293
- package/test/index.js +0 -16
- package/test/ltp/ids.js +0 -74
- package/test/ltp/right.js +0 -198
- package/test/ltp/verify_failclosed.js +0 -134
- package/test/message/message.js +0 -190
- package/test/mnemonic/data/fixtures.json +0 -300
- package/test/mnemonic/mnemonic.js +0 -277
- package/test/mnemonic/mocha.opts +0 -1
- package/test/mnemonic/pbkdf2.test.js +0 -43
- package/test/networks.js +0 -207
- package/test/notaryhash/batch_leaf.js +0 -140
- package/test/notaryhash/certificate.js +0 -249
- package/test/notaryhash/encoding.js +0 -186
- package/test/notaryhash/interop.js +0 -112
- package/test/notaryhash/merkle.js +0 -181
- package/test/notaryhash/script.js +0 -270
- package/test/notaryhash/verify.js +0 -342
- package/test/opcode.js +0 -186
- package/test/ordinals/bsv20.js +0 -337
- package/test/ordinals/inscription.js +0 -319
- package/test/ordinals/ordlock.js +0 -613
- package/test/privatekey.js +0 -540
- package/test/publickey.js +0 -411
- package/test/regressions.js +0 -215
- package/test/script/chronicle.js +0 -543
- package/test/script/defaults.js +0 -160
- package/test/script/genesis_limits.js +0 -203
- package/test/script/interpreter.js +0 -776
- package/test/script/script.js +0 -1259
- package/test/script/string_ops.js +0 -88
- package/test/security/fail_closed_contracts.js +0 -104
- package/test/security/threat_model_coverage.js +0 -31
- package/test/smart_contract/covenants.js +0 -245
- package/test/smart_contract/dsl_debugger.js +0 -101
- package/test/smart_contract/extract_field.js +0 -61
- package/test/smart_contract/nonenforcing_guard.js +0 -44
- package/test/smart_contract/ordinal_transfer.js +0 -81
- package/test/smart_contract/preimage.js +0 -98
- package/test/smart_contract/sighash_marketplace.js +0 -108
- package/test/smart_contract/token_generalized.js +0 -185
- package/test/spv/headerchain.js +0 -86
- package/test/spv/merkleproof.js +0 -133
- package/test/statuslist/failclosed.js +0 -78
- package/test/transaction/deserialize.js +0 -33
- package/test/transaction/input/input.js +0 -92
- package/test/transaction/input/multisig.js +0 -174
- package/test/transaction/input/multisigscripthash.js +0 -111
- package/test/transaction/input/publickey.js +0 -68
- package/test/transaction/input/publickeyhash.js +0 -59
- package/test/transaction/output.js +0 -185
- package/test/transaction/sighash.js +0 -91
- package/test/transaction/signature.js +0 -127
- package/test/transaction/transaction.js +0 -1299
- package/test/transaction/unspentoutput.js +0 -97
- package/test/types/dts_drift.js +0 -124
- package/test/types/surface_honesty.js +0 -102
- package/test/util/id.js +0 -72
- package/test/util/js.js +0 -76
- package/test/util/preconditions.js +0 -79
- package/test/vcjwt/interop.js +0 -126
package/README.md
CHANGED
|
@@ -1,1122 +1,243 @@
|
|
|
1
1
|
# SmartLedger-BSV
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Bitcoin SV library with an interpreter-verified script engine.
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/@smartledger/bsv)
|
|
6
6
|
[](LICENSE)
|
|
7
|
-
[](#-16-loading-options---choose-your-approach)
|
|
9
|
-
[](#-legally-recognizable-credentials-v34x)
|
|
7
|
+
[](STABILITY.md)
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
reference node's own
|
|
14
|
-
rather than
|
|
15
|
-
|
|
9
|
+
Its defaults describe BSV as the network actually runs it. `verify()` with no
|
|
10
|
+
flags means current mainnet consensus, not "no rules"; the interpreter is
|
|
11
|
+
measured against the reference node's own vectors (1483/1483, zero false
|
|
12
|
+
accepts) rather than the Bitcoin Core vectors inherited from the upstream fork;
|
|
13
|
+
and all secp256k1 work runs on the audited, constant-time
|
|
16
14
|
[`@noble`](https://github.com/paulmillr/noble-curves) suite with `elliptic`
|
|
17
|
-
removed
|
|
18
|
-
ownership tokens), a legally-recognizable DID:web + VC-JWT toolkit, and 16
|
|
19
|
-
distribution methods.
|
|
15
|
+
removed.
|
|
20
16
|
|
|
21
|
-
> **
|
|
22
|
-
>
|
|
23
|
-
>
|
|
24
|
-
>
|
|
25
|
-
>
|
|
26
|
-
> **8.0.0 was a breaking release.** `verify()` with no flags now means BSV
|
|
27
|
-
> mainnet rather than "no rules", and two flag constants changed value. Read
|
|
28
|
-
> [Upgrading to v8.0.0](#upgrading-to-v800-breaking-changes) before moving from
|
|
29
|
-
> 7.x or earlier.
|
|
17
|
+
> **9.x will not break your code until at least 2027-09-01.** Patch and minor
|
|
18
|
+
> releases only. This library published six majors in the 82 days before that
|
|
19
|
+
> commitment; [STABILITY.md](STABILITY.md) explains what changed and how
|
|
20
|
+
> correctness fixes now ship without breaking callers.
|
|
30
21
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
The full covenant stack lives at `bsv.SmartContract` and verifies end-to-end
|
|
34
|
-
through `Script.Interpreter`. Every locking script has both a positive
|
|
35
|
-
(must-accept) and negative (must-reject) test.
|
|
36
|
-
|
|
37
|
-
```javascript
|
|
38
|
-
const bsv = require('@smartledger/bsv')
|
|
39
|
-
const SC = bsv.SmartContract
|
|
40
|
-
SC.enableGenesis() // OP_PUSH_TX needs the lifted element cap — but note this is
|
|
41
|
-
// process-wide and weakens pre-Genesis validation. See
|
|
42
|
-
// "Consensus defaults" below before calling it in an app.
|
|
43
|
-
|
|
44
|
-
// Self-replicating covenant — every spend recreates the same script (value − fee).
|
|
45
|
-
const lock = SC.perpetualCovenant(500)
|
|
46
|
-
|
|
47
|
-
// Stateful ownership token (NFT) — transfer requires the owner's ECDSA signature
|
|
48
|
-
// over the spend, rewrites state, perpetuates the token code.
|
|
49
|
-
const token = SC.ownershipToken(500, ownerHash) // ownerHash = SC.Token.ownerId(ownerKey)
|
|
50
|
-
|
|
51
|
-
// Value covenant — forces spend outputs to match a specific hashOutputs.
|
|
52
|
-
const vlock = SC.valueCovenant(SC.PushTx.hashOutputs(requiredOutputs))
|
|
53
|
-
|
|
54
|
-
// Verify any locking script end-to-end through Script.Interpreter.
|
|
55
|
-
// Returns { ok, err } — `err` names the interpreter error when ok is false.
|
|
56
|
-
const { ok, err } = SC.verifyScript(unlockScript, lockingScript, { tx, inputIndex, satoshis })
|
|
22
|
+
```bash
|
|
23
|
+
npm install @smartledger/bsv
|
|
57
24
|
```
|
|
58
25
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
| Namespace | Purpose |
|
|
62
|
-
|---|---|
|
|
63
|
-
| `PushTx` | nChain WP1605 OP_PUSH_TX — `authenticator()`, `valueCovenant()`, `hashOutputs()`, `extractHashOutputs()`, `grind()` |
|
|
64
|
-
| `PELS` | Perpetually Enforcing Locking Scripts — `perpetualCovenant(fee)` |
|
|
65
|
-
| `Token` | Stateful ownership token (NFT) — `ownershipToken(fee, owner[, auth])`, `ownershipTokenMulti(owner[, auth])`, `ownerId(key)`, `unlockTransfer(...)`, `unlockTransferMulti(...)` |
|
|
66
|
-
| `Authorizers` | Pluggable token ownership — `singleKey()`, `multisig(m, n)`, `predicate({...})` |
|
|
67
|
-
| `Locks` | Hash-lock, P2PKH, CLTV time-lock, m-of-n multisig, HTLC |
|
|
68
|
-
| `CovenantHelpers` | Consensus-flag `verify()` harness, raw BIP-143 preimage, signing, fund/spend scaffolding |
|
|
69
|
-
|
|
70
|
-
> ⚠️ Research-grade. Review carefully before mainnet value: the OP_PUSH_TX key
|
|
71
|
-
> is the intentionally public `a=k=1` construction, and low-S malleability is
|
|
72
|
-
> left unenforced for the in-script signature.
|
|
73
|
-
|
|
74
|
-
## 🔏 NotaryHash (BRC-220)
|
|
26
|
+
## Covenants that actually enforce
|
|
75
27
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
against
|
|
81
|
-
|
|
82
|
-
Available as `bsv.NotaryHash`, or `require('@smartledger/bsv/lib/notaryhash')`.
|
|
28
|
+
A covenant constrains the transaction that spends it. The script has no opcode
|
|
29
|
+
for reading its own spend, so OP_PUSH_TX fixes the private key `a = 1` and
|
|
30
|
+
ephemeral key `k = 1`, collapsing ECDSA to `s = (z + Gx) mod n` — plain
|
|
31
|
+
arithmetic the script can do on a BIP-143 preimage sitting on the stack.
|
|
32
|
+
`OP_CHECKSIG` against the generator `G` then proves that data really is this
|
|
33
|
+
transaction's preimage. No trusted signer is involved.
|
|
83
34
|
|
|
84
35
|
```javascript
|
|
85
36
|
const bsv = require('@smartledger/bsv')
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
// 1. Hash the document. Only the hash is ever published.
|
|
89
|
-
const payloadHash = bsv.crypto.Hash.sha256(Buffer.from(documentBytes))
|
|
37
|
+
const { Script, Transaction, crypto } = bsv
|
|
38
|
+
const P = bsv.SmartContract.PushTx
|
|
90
39
|
|
|
91
|
-
//
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
// BRC-220 verifier will accept.
|
|
96
|
-
const ecdsa = bsv.crypto.ECDSA().set({ hashbuf: payloadHash, privkey: key })
|
|
97
|
-
ecdsa.sign()
|
|
98
|
-
const signatureBuffer = Buffer.concat([ // 64 raw bytes, r || s
|
|
99
|
-
ecdsa.sig.r.toArrayLike(Buffer, 'be', 32),
|
|
100
|
-
ecdsa.sig.s.toArrayLike(Buffer, 'be', 32)
|
|
101
|
-
])
|
|
102
|
-
const publicKeyBuffer = key.toPublicKey().toBuffer()
|
|
40
|
+
// Commit to the only outputs this coin may ever be spent to.
|
|
41
|
+
const dest = Script.fromASM('OP_FALSE OP_RETURN 636f76656e616e74')
|
|
42
|
+
const allowed = [new Transaction.Output({ script: dest, satoshis: 99000 })]
|
|
43
|
+
const lock = P.valueCovenant(P.hashOutputs(allowed)) // ~419 bytes
|
|
103
44
|
|
|
104
|
-
//
|
|
105
|
-
//
|
|
106
|
-
|
|
107
|
-
const
|
|
108
|
-
mode: NotaryHash.MODE.FULL,
|
|
109
|
-
algorithm: 'ECDSA-secp256k1',
|
|
110
|
-
hashAlgorithm: 'SHA-256',
|
|
111
|
-
payloadHash: payloadHash,
|
|
112
|
-
publicKey: publicKeyBuffer,
|
|
113
|
-
signature: signatureBuffer,
|
|
114
|
-
createdAt: new Date().toISOString(),
|
|
115
|
-
anchor: { txid: txid, blockHeight: height }
|
|
116
|
-
})
|
|
45
|
+
// Spend it. `grind` nudges nLockTime until the script-derived signature is
|
|
46
|
+
// canonical (low-S); the cost falls on the spender, not on script size.
|
|
47
|
+
const g = P.grind(spendingTx, 0, lock, 100000)
|
|
48
|
+
const unlock = new Script().add(g.preimage) // the preimage IS the unlock
|
|
117
49
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
mode: NotaryHash.MODE.FULL,
|
|
121
|
-
algorithm: 'ECDSA-secp256k1',
|
|
122
|
-
hashAlgorithm: 'SHA-256',
|
|
123
|
-
payloadHash: payloadHash,
|
|
124
|
-
proofHash: Buffer.from(certificate.proofHash, 'hex'),
|
|
125
|
-
publicKey: publicKeyBuffer,
|
|
126
|
-
signature: signatureBuffer
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
// 5. Checks. Every verify entry point returns a STRICT boolean.
|
|
130
|
-
NotaryHash.Certificate.proofHashMatches(certificate) // proof integrity, offline
|
|
131
|
-
NotaryHash.Script.isNotaryHash(script) // is this a NotaryHash output
|
|
132
|
-
NotaryHash.isValid(certificate, options) // all three spec checks
|
|
50
|
+
new Script.Interpreter().verify(unlock, lock, spendingTx, 0, undefined, new crypto.BN(100000))
|
|
51
|
+
// => true, and false for any transaction that redirects the outputs
|
|
133
52
|
```
|
|
134
53
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
| Mode | On chain | Use when |
|
|
138
|
-
|---|---|---|
|
|
139
|
-
| `MODE.FULL` | public key and signature in full | ECDSA, where both are small |
|
|
140
|
-
| `MODE.HYBRID` | `sha256` of each instead | post-quantum signatures, which run to tens of KB |
|
|
141
|
-
| `MODE.BATCH` | a 32-byte Merkle root and a `u32be` leaf count | notarizing many documents in one output |
|
|
142
|
-
|
|
143
|
-
Batch mode uses **RFC 6962** Merkle trees — domain-separated leaves
|
|
144
|
-
(`sha256(0x00‖d)`), internal nodes (`sha256(0x01‖L‖R)`), and a rightmost leaf that
|
|
145
|
-
is *never* duplicated. This is deliberately not the Bitcoin tree in `lib/spv` nor
|
|
146
|
-
the one in `lib/gdaf`; reusing either would produce a root no other BRC-220
|
|
147
|
-
implementation computes. The batch leaf is a certificate's `proofHash` — see
|
|
148
|
-
[`docs/BRC220_BATCH_LEAF_AMENDMENT.md`](./docs/BRC220_BATCH_LEAF_AMENDMENT.md).
|
|
149
|
-
|
|
150
|
-
**Post-quantum signatures are supported but not bundled.** `ECDSA-secp256k1` is
|
|
151
|
-
registered by default; ML-DSA and SLH-DSA are reached by registering a suite, so
|
|
152
|
-
callers who do not need them pay nothing in bundle size or audit surface:
|
|
54
|
+
Every locking script in `bsv.SmartContract` ships with both a must-accept and a
|
|
55
|
+
must-reject test. Higher-level pieces built on the same core:
|
|
153
56
|
|
|
154
57
|
```javascript
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
58
|
+
const SC = bsv.SmartContract
|
|
59
|
+
SC.perpetualCovenant(500) // every spend recreates the same script (value − fee)
|
|
60
|
+
SC.ownershipToken(500, ownerHash) // NFT; transfer needs the owner's signature over the spend
|
|
61
|
+
SC.policy({ /* ... */ }) // declarative front-end over OP_PUSH_TX
|
|
158
62
|
```
|
|
159
63
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
## 🆕 **Legally-Recognizable Credentials (v3.4.x+)**
|
|
64
|
+
## The one thing that will bite you
|
|
163
65
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
- ✅ **Blockchain Native**: ES256K (secp256k1) for BSV integration
|
|
168
|
-
- ✅ **Revocation Built-in**: StatusList2021 standard for credential management
|
|
169
|
-
- ✅ **Privacy Preserving**: Hash-only BSV anchoring (no PII on-chain)
|
|
170
|
-
- ✅ **CLI Tools**: Complete command-line interface for credential operations
|
|
66
|
+
Flags and **limits** are separate mechanisms. The era bits (`SCRIPT_GENESIS`,
|
|
67
|
+
`SCRIPT_UTXO_AFTER_GENESIS`, and the Chronicle pair) are what the interpreter
|
|
68
|
+
derives its element-size, script-size, opcode-count and script-number caps from.
|
|
171
69
|
|
|
172
|
-
|
|
70
|
+
Hand-assemble a flag word out of named constants — the idiom every pre-Genesis
|
|
71
|
+
tutorial teaches — and you get the feature opcodes you asked for while silently
|
|
72
|
+
keeping the 2019 caps. The script *runs*, so nothing looks wrong until a
|
|
73
|
+
586-byte preimage is rejected against a 520-byte limit and the error blames the
|
|
74
|
+
push instead of the flags.
|
|
173
75
|
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
|
|
76
|
+
```javascript
|
|
77
|
+
// Correct — resolves to current mainnet:
|
|
78
|
+
interp.verify(unlock, lock, tx, 0, undefined, satoshisBN)
|
|
79
|
+
interp.verify(unlock, lock, tx, 0, Script.Interpreter.mainnetFlags(), satoshisBN)
|
|
177
80
|
|
|
178
|
-
|
|
179
|
-
|
|
81
|
+
// Silently pre-Genesis, and the reason your covenant "doesn't work":
|
|
82
|
+
interp.verify(unlock, lock, tx, 0, SCRIPT_ENABLE_MONOLITH_OPCODES | ..., satoshisBN)
|
|
83
|
+
```
|
|
180
84
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
--claims '{"licenseNumber":"DL123456","class":"C"}' \
|
|
187
|
-
> credential.jwt
|
|
85
|
+
Since 9.1.0 a failure caused this way sets `interp.eraHint` and prints one
|
|
86
|
+
explanatory warning per process. Deliberate pre-Genesis testing is legitimate
|
|
87
|
+
and stays silent unless it trips an era-derived limit; set
|
|
88
|
+
`Interpreter.eraDiagnostics = false` or `BSV_NO_ERA_HINT=1` to turn the notice
|
|
89
|
+
off entirely.
|
|
188
90
|
|
|
189
|
-
|
|
190
|
-
npx smartledger-bsv vc verify credential.jwt
|
|
91
|
+
## Core Bitcoin API
|
|
191
92
|
|
|
192
|
-
|
|
193
|
-
npx smartledger-bsv anchor hash credential.jwt
|
|
93
|
+
Drop-in compatible with the classic `bsv` 1.5.6 surface.
|
|
194
94
|
|
|
195
|
-
|
|
196
|
-
|
|
95
|
+
```javascript
|
|
96
|
+
const { PrivateKey, Transaction, Script, Address, HDPrivateKey } = require('@smartledger/bsv')
|
|
197
97
|
|
|
198
|
-
|
|
199
|
-
|
|
98
|
+
const key = PrivateKey.fromRandom()
|
|
99
|
+
const tx = new Transaction()
|
|
100
|
+
.from(utxos)
|
|
101
|
+
.to(address, 50000)
|
|
102
|
+
.change(key.toAddress())
|
|
103
|
+
.sign(key)
|
|
200
104
|
```
|
|
201
105
|
|
|
202
|
-
|
|
106
|
+
Custom locking scripts need the subscript and amount passed explicitly — BIP-143
|
|
107
|
+
signs both, and `tx.sign()` only knows P2PKH:
|
|
203
108
|
|
|
204
109
|
```javascript
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
// Build DID documents (.well-known/did.json and jwks.json)
|
|
211
|
-
const docs = bsv.DIDWeb.buildDidWebDocuments({
|
|
212
|
-
domain: 'example.com',
|
|
213
|
-
p256: { jwk: keys.publicJwk, kid: keys.kid },
|
|
214
|
-
controllerName: 'Example Corp'
|
|
215
|
-
})
|
|
216
|
-
// Deploy docs.didDocument to https://example.com/.well-known/did.json
|
|
217
|
-
// Deploy docs.jwks to https://example.com/.well-known/jwks.json
|
|
110
|
+
const sig = Transaction.sighash.sign(
|
|
111
|
+
tx, privateKey, sighashType, inputIndex, lockingScript, new crypto.BN(satoshis)
|
|
112
|
+
)
|
|
113
|
+
const push = Buffer.concat([sig.toDER(), Buffer.from([sighashType])]) // flag byte required
|
|
114
|
+
```
|
|
218
115
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
issuerDid: docs.did,
|
|
222
|
-
subjectId: 'did:example:alice',
|
|
223
|
-
types: ['VerifiableCredential', 'AgeCredential'],
|
|
224
|
-
credentialSubject: {
|
|
225
|
-
ageOver: 18,
|
|
226
|
-
country: 'US'
|
|
227
|
-
},
|
|
228
|
-
privateJwk: keys.privateJwk,
|
|
229
|
-
alg: 'ES256',
|
|
230
|
-
kid: keys.kid
|
|
231
|
-
})
|
|
116
|
+
Also included: `Block`, `MerkleBlock`, `SPV`, `Mnemonic` (BIP-39), `ECIES`,
|
|
117
|
+
`Message`, `Shamir`, `Ordinals`, `NotaryHash` (BRC-220).
|
|
232
118
|
|
|
233
|
-
|
|
119
|
+
## Credentials and legal tokens
|
|
234
120
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
didResolver: async (did) => {
|
|
238
|
-
// In production, fetch https://example.com/.well-known/jwks.json
|
|
239
|
-
return { jwks: docs.jwks }
|
|
240
|
-
},
|
|
241
|
-
expectedIssuerDid: docs.did
|
|
242
|
-
})
|
|
121
|
+
Standards-based issuance and verification, ES256/ES256K, with on-chain BSV
|
|
122
|
+
anchoring. These are substantial subsystems; each has its own guide.
|
|
243
123
|
|
|
244
|
-
|
|
124
|
+
```javascript
|
|
125
|
+
const { createDID, createEmailCredential, verifyCredential } = require('@smartledger/bsv')
|
|
126
|
+
```
|
|
245
127
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
128
|
+
| Area | Entry point | Guide |
|
|
129
|
+
|---|---|---|
|
|
130
|
+
| DID:web + VC-JWT | `bsv.DIDWeb`, `bsv.VcJwt` | [docs/technical/GDAF_DEVELOPER_INTERFACE.md](docs/technical/GDAF_DEVELOPER_INTERFACE.md) |
|
|
131
|
+
| Revocation (StatusList2021) | `bsv.StatusList` | [docs/MODULE_REFERENCE_COMPLETE.md](docs/MODULE_REFERENCE_COMPLETE.md) |
|
|
132
|
+
| Legal Token Protocol | `bsv.LTP` | [docs/advanced/LEGAL_TOKEN_PROTOCOL.md](docs/advanced/LEGAL_TOKEN_PROTOCOL.md) |
|
|
133
|
+
| Attestation (GDAF) | `bsv.GDAF` | [docs/technical/GDAF_IMPLEMENTATION_COMPLETE.md](docs/technical/GDAF_IMPLEMENTATION_COMPLETE.md) |
|
|
134
|
+
| Blockchain anchoring | `bsv.Anchor` | [docs/MODULE_REFERENCE_COMPLETE.md](docs/MODULE_REFERENCE_COMPLETE.md) |
|
|
253
135
|
|
|
254
|
-
|
|
255
|
-
// Later: verify with bsv.Anchor.verifyAnchorHash(originalData, anchorHash)
|
|
136
|
+
A CLI covers the common credential workflow end to end:
|
|
256
137
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
138
|
+
```bash
|
|
139
|
+
npx smartledger-bsv didweb:init --domain example.com
|
|
140
|
+
npx smartledger-bsv vc:issue --subject did:web:example.com:alice --type EmailCredential
|
|
141
|
+
npx smartledger-bsv vc:verify --token ./credential.jwt
|
|
142
|
+
```
|
|
262
143
|
|
|
263
|
-
|
|
264
|
-
const updated = await bsv.StatusList.updateStatusList({
|
|
265
|
-
listVcJwt: statusList.listVcJwt,
|
|
266
|
-
index: 42,
|
|
267
|
-
status: 'revoked',
|
|
268
|
-
privateJwk: keys.privateJwk
|
|
269
|
-
})
|
|
144
|
+
## Loading options
|
|
270
145
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
index: 42
|
|
275
|
-
})
|
|
146
|
+
Node and bundlers get tree-shakeable subpaths; browsers can take a single file
|
|
147
|
+
from a CDN. Importing the package root pulls in every subsystem, so prefer a
|
|
148
|
+
subpath when you only need part of it:
|
|
276
149
|
|
|
277
|
-
|
|
150
|
+
```javascript
|
|
151
|
+
const Script = require('@smartledger/bsv/lib/script') // 24 modules
|
|
152
|
+
const bsv = require('@smartledger/bsv') // 128 modules
|
|
278
153
|
```
|
|
279
154
|
|
|
280
|
-
## 🎯 **16 Loading Options - Choose Your Approach**
|
|
281
|
-
|
|
282
155
|
### **Core Modules**
|
|
283
156
|
| Module | Size | Use Case | CDN |
|
|
284
157
|
|--------|------|----------|-----|
|
|
285
|
-
| **bsv.min.js** |
|
|
286
|
-
| **bsv.bundle.js** |
|
|
158
|
+
| **bsv.min.js** | 1041KB | Core BSV + SmartContract | `unpkg.com/@smartledger/bsv@9.1.0/bsv.min.js` |
|
|
159
|
+
| **bsv.bundle.js** | 1041KB | Everything in one file | `unpkg.com/@smartledger/bsv@9.1.0/bsv.bundle.js` |
|
|
287
160
|
|
|
288
161
|
### **W3C Verifiable Credentials**
|
|
289
162
|
| Module | Size | Use Case | CDN |
|
|
290
163
|
|--------|------|----------|-----|
|
|
291
|
-
| **🟢 bsv-didweb.min.js** | 166KB | **DID:web generation** | `unpkg.com/@smartledger/bsv@
|
|
292
|
-
| **🟢 bsv-vcjwt.min.js** | 166KB | **VC-JWT issue/verify** | `unpkg.com/@smartledger/bsv@
|
|
293
|
-
| **🟢 bsv-statuslist.min.js** | 256KB | **StatusList2021 revocation** | `unpkg.com/@smartledger/bsv@
|
|
294
|
-
| **🟢 bsv-anchor.min.js** | 164KB | **BSV anchoring (hash-only)** | `unpkg.com/@smartledger/bsv@
|
|
164
|
+
| **🟢 bsv-didweb.min.js** | 166KB | **DID:web generation** | `unpkg.com/@smartledger/bsv@9.1.0/bsv-didweb.min.js` |
|
|
165
|
+
| **🟢 bsv-vcjwt.min.js** | 166KB | **VC-JWT issue/verify** | `unpkg.com/@smartledger/bsv@9.1.0/bsv-vcjwt.min.js` |
|
|
166
|
+
| **🟢 bsv-statuslist.min.js** | 256KB | **StatusList2021 revocation** | `unpkg.com/@smartledger/bsv@9.1.0/bsv-statuslist.min.js` |
|
|
167
|
+
| **🟢 bsv-anchor.min.js** | 164KB | **BSV anchoring (hash-only)** | `unpkg.com/@smartledger/bsv@9.1.0/bsv-anchor.min.js` |
|
|
295
168
|
|
|
296
169
|
### **Smart Contract & Development**
|
|
297
170
|
| Module | Size | Use Case | CDN |
|
|
298
171
|
|--------|------|----------|-----|
|
|
299
|
-
| **bsv-smartcontract.min.js** | 140KB | Complete covenant framework | `unpkg.com/@smartledger/bsv@
|
|
300
|
-
| **bsv-covenant.min.js** | 35KB | Covenant operations | `unpkg.com/@smartledger/bsv@
|
|
301
|
-
| **bsv-script-helper.min.js** | 33KB | Custom script tools | `unpkg.com/@smartledger/bsv@
|
|
302
|
-
| **bsv-security.min.js** | 32KB | Security enhancements | `unpkg.com/@smartledger/bsv@
|
|
172
|
+
| **bsv-smartcontract.min.js** | 140KB | Complete covenant framework | `unpkg.com/@smartledger/bsv@9.1.0/bsv-smartcontract.min.js` |
|
|
173
|
+
| **bsv-covenant.min.js** | 35KB | Covenant operations | `unpkg.com/@smartledger/bsv@9.1.0/bsv-covenant.min.js` |
|
|
174
|
+
| **bsv-script-helper.min.js** | 33KB | Custom script tools | `unpkg.com/@smartledger/bsv@9.1.0/bsv-script-helper.min.js` |
|
|
175
|
+
| **bsv-security.min.js** | 32KB | Security enhancements | `unpkg.com/@smartledger/bsv@9.1.0/bsv-security.min.js` |
|
|
303
176
|
|
|
304
177
|
### **Legal & Compliance**
|
|
305
178
|
| Module | Size | Use Case | CDN |
|
|
306
179
|
|--------|------|----------|-----|
|
|
307
|
-
| **bsv-ltp.min.js** |
|
|
308
|
-
| **bsv-gdaf.min.js** |
|
|
180
|
+
| **bsv-ltp.min.js** | 535KB | Legal Token Protocol | `unpkg.com/@smartledger/bsv@9.1.0/bsv-ltp.min.js` |
|
|
181
|
+
| **bsv-gdaf.min.js** | 1041KB | Digital Identity & Attestation | `unpkg.com/@smartledger/bsv@9.1.0/bsv-gdaf.min.js` |
|
|
309
182
|
|
|
310
183
|
### **Advanced Cryptography**
|
|
311
184
|
| Module | Size | Use Case | CDN |
|
|
312
185
|
|--------|------|----------|-----|
|
|
313
|
-
| **bsv-shamir.min.js** | 177KB | Threshold Cryptography | `unpkg.com/@smartledger/bsv@
|
|
186
|
+
| **bsv-shamir.min.js** | 177KB | Threshold Cryptography | `unpkg.com/@smartledger/bsv@9.1.0/bsv-shamir.min.js` |
|
|
314
187
|
|
|
315
188
|
### **Utilities**
|
|
316
189
|
| Module | Size | Use Case | CDN |
|
|
317
190
|
|--------|------|----------|-----|
|
|
318
|
-
| **bsv-ecies.min.js** | 137KB | Encryption | `unpkg.com/@smartledger/bsv@
|
|
319
|
-
| **bsv-message.min.js** | 34KB | Message signing | `unpkg.com/@smartledger/bsv@
|
|
320
|
-
| **bsv-mnemonic.min.js** | 320KB | HD wallets | `unpkg.com/@smartledger/bsv@
|
|
321
|
-
|
|
322
|
-
## ⚡ **2-Minute Quick Start**
|
|
323
|
-
|
|
324
|
-
Get started with Bitcoin SV development in under 2 minutes:
|
|
325
|
-
|
|
326
|
-
```bash
|
|
327
|
-
# Install via npm
|
|
328
|
-
npm install @smartledger/bsv
|
|
329
|
-
|
|
330
|
-
# Or include in HTML
|
|
331
|
-
<script src="https://unpkg.com/@smartledger/bsv@8.3.1/bsv.min.js"></script>
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
> **🔒 Upgrading?** 8.0.0 changed what `verify()` means with no flags, and moved
|
|
335
|
-
> two flag constants. Read [Upgrading to v8.0.0](#upgrading-to-v800-breaking-changes)
|
|
336
|
-
> before moving from 7.x or earlier; the older
|
|
337
|
-
> [v5.0.0 notes](#upgrading-to-v500-breaking-changes) still apply if you are coming
|
|
338
|
-
> from 4.x.
|
|
339
|
-
|
|
340
|
-
**Basic Transaction (30 seconds):**
|
|
341
|
-
```javascript
|
|
342
|
-
const bsv = require('@smartledger/bsv'); // Node.js
|
|
343
|
-
// const bsv = window.bsv; // Browser
|
|
344
|
-
|
|
345
|
-
// 1. Generate keys
|
|
346
|
-
const privateKey = new bsv.PrivateKey();
|
|
347
|
-
const address = privateKey.toAddress();
|
|
348
|
-
|
|
349
|
-
// 2. Create transaction
|
|
350
|
-
const tx = new bsv.Transaction()
|
|
351
|
-
.from(utxo) // Add input
|
|
352
|
-
.to(targetAddress, 50000) // Send 50,000 satoshis
|
|
353
|
-
.change(address) // Send change back
|
|
354
|
-
.sign(privateKey); // Sign transaction
|
|
355
|
-
|
|
356
|
-
console.log('Transaction ID:', tx.id);
|
|
357
|
-
```
|
|
358
|
-
|
|
359
|
-
**🆕 Legal Token Development (60 seconds):**
|
|
360
|
-
```javascript
|
|
361
|
-
// Create a legal property-title token
|
|
362
|
-
const result = bsv.LTP.createRightToken({
|
|
363
|
-
type: bsv.LTP.Right.RightTypes.PROPERTY_TITLE,
|
|
364
|
-
owner: ownerDID,
|
|
365
|
-
jurisdiction: 'us_delaware',
|
|
366
|
-
legalDescription: 'Lot 15, Block 3, Subdivision ABC'
|
|
367
|
-
}, issuerPrivateKey);
|
|
368
|
-
console.log(result.success, result.token.tokenHash);
|
|
369
|
-
|
|
370
|
-
// Generate W3C Verifiable Credential
|
|
371
|
-
const credential = bsv.createEmailCredential(
|
|
372
|
-
issuerDID, subjectDID, 'user@example.com', issuerPrivateKey
|
|
373
|
-
);
|
|
374
|
-
|
|
375
|
-
// Threshold cryptography — split(secret, threshold, shares)
|
|
376
|
-
const shares = bsv.Shamir.split('private_key_backup', 3, 5); // 3 of 5 needed
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
**🆕 Smart Contract Development (90 seconds):**
|
|
380
|
-
```javascript
|
|
381
|
-
// Generate authentic UTXOs for testing
|
|
382
|
-
const utxoGenerator = new bsv.SmartContract.UTXOGenerator();
|
|
383
|
-
const utxos = utxoGenerator.createRealUTXOs(2, 100000);
|
|
384
|
-
|
|
385
|
-
// Create BIP-143 preimage and extract fields
|
|
386
|
-
const preimage = new bsv.SmartContract.Preimage(preimageHex);
|
|
387
|
-
const amount = preimage.getField('amount');
|
|
388
|
-
|
|
389
|
-
// Build covenant with JavaScript-to-Script translation
|
|
390
|
-
const covenant = bsv.SmartContract.createCovenantBuilder()
|
|
391
|
-
.extractField('amount')
|
|
392
|
-
.push(50000)
|
|
393
|
-
.greaterThanOrEqual()
|
|
394
|
-
.verify()
|
|
395
|
-
.build();
|
|
396
|
-
```
|
|
397
|
-
|
|
398
|
-
**Next Steps:**
|
|
399
|
-
- 📖 [SmartContract Guide](docs/advanced/SMART_CONTRACT_GUIDE.md)
|
|
400
|
-
- ⚖️ [Legal Token Protocol Guide](docs/advanced/LEGAL_TOKEN_PROTOCOL.md)
|
|
401
|
-
- 🌐 [Digital Identity Guide](docs/technical/GDAF_DEVELOPER_INTERFACE.md)
|
|
402
|
-
- 🔐 [Threshold Cryptography Guide](docs/technical/SHAMIR_INTEGRATION_SUMMARY.md)
|
|
403
|
-
- 🗃️ [UTXO Manager Guide](docs/advanced/UTXO_MANAGER_GUIDE.md)
|
|
404
|
-
- 💡 [Examples Directory](https://github.com/codenlighten/smartledger-bsv/tree/main/examples)
|
|
405
|
-
|
|
406
|
-
## 🔧 **API Reference**
|
|
407
|
-
|
|
408
|
-
| Component | Method | Purpose | Example |
|
|
409
|
-
|-----------|--------|---------|---------|
|
|
410
|
-
| **Core** | `new PrivateKey()` | Generate private key | `const key = new bsv.PrivateKey()` |
|
|
411
|
-
| | `new Transaction()` | Create transaction | `const tx = new bsv.Transaction()` |
|
|
412
|
-
| | `Script.fromASM()` | Parse script | `const script = bsv.Script.fromASM('OP_DUP')` |
|
|
413
|
-
| **Covenant** | `SmartContract.perpetualCovenant()` | Self-replicating covenant | `SC.perpetualCovenant(500)` |
|
|
414
|
-
| | `SmartContract.verifyScript()` | Verify a script pair; returns `{ ok, err }` | `SC.verifyScript(unlock, lock, { tx, satoshis })` |
|
|
415
|
-
| | `CustomScriptHelper.getPreimage()` | BIP143 preimage | `bsv.CustomScriptHelper.getPreimage(tx, 0, script, sats)` |
|
|
416
|
-
| **Custom Scripts** | `CustomScriptHelper` | Script utilities — **all methods are static**, do not instantiate | `bsv.CustomScriptHelper.createDataScript(data)` |
|
|
417
|
-
| | `createSignature()` | Manual signature | `bsv.CustomScriptHelper.createSignature(tx, key, 0, script, sats)` |
|
|
418
|
-
| | `createMultisigScript()` | Multi-signature | `bsv.CustomScriptHelper.createMultisigScript(2, [pk1, pk2])` |
|
|
419
|
-
| **Debug Tools** | `SmartContract.examineStack()` | Analyze script | `SmartContract.examineStack(script)` |
|
|
420
|
-
| | `interpretScript()` | Execute script | `SmartContract.interpretScript(script)` |
|
|
421
|
-
| | `getScriptMetrics()` | Performance data | `SmartContract.getScriptMetrics(script)` |
|
|
422
|
-
| **Security (opt-in)** | `SmartVerify.smartVerify()` | Hardened verify with strict input validation — call explicitly; default `signature.verify()` does NOT route through this | `bsv.SmartVerify.smartVerify(msgHash, sig, pubkey)` |
|
|
423
|
-
| | `EllipticFixed.sign()` | Canonicalized signing wrapper over the `@noble` secp256k1 backend | `bsv.EllipticFixed.sign(hash, privateKey)` |
|
|
424
|
-
|
|
425
|
-
> 💡 **Tip:** All methods include comprehensive error handling and validation. See [documentation links](#documentation) for detailed guides.
|
|
426
|
-
|
|
427
|
-
## 📚 **Quick Start Examples**
|
|
428
|
-
|
|
429
|
-
### 🔧 **Basic Development** (~1.05MB total)
|
|
191
|
+
| **bsv-ecies.min.js** | 137KB | Encryption | `unpkg.com/@smartledger/bsv@9.1.0/bsv-ecies.min.js` |
|
|
192
|
+
| **bsv-message.min.js** | 34KB | Message signing | `unpkg.com/@smartledger/bsv@9.1.0/bsv-message.min.js` |
|
|
193
|
+
| **bsv-mnemonic.min.js** | 320KB | HD wallets | `unpkg.com/@smartledger/bsv@9.1.0/bsv-mnemonic.min.js` |
|
|
430
194
|
```html
|
|
431
|
-
<script src="https://unpkg.com/@smartledger/bsv@
|
|
432
|
-
<script src="https://unpkg.com/@smartledger/bsv@8.3.1/bsv-script-helper.min.js"></script>
|
|
195
|
+
<script src="https://unpkg.com/@smartledger/bsv@9.1.0/bsv.min.js"></script>
|
|
433
196
|
<script>
|
|
434
|
-
const
|
|
435
|
-
const utxos = new bsv.SmartContract.UTXOGenerator().createRealUTXOs(2, 100000);
|
|
197
|
+
const key = bsv.PrivateKey.fromRandom()
|
|
436
198
|
</script>
|
|
437
199
|
```
|
|
438
200
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
<script src="https://unpkg.com/@smartledger/bsv@8.3.1/bsv.min.js"></script>
|
|
442
|
-
<script src="https://unpkg.com/@smartledger/bsv@8.3.1/bsv-covenant.min.js"></script>
|
|
443
|
-
<script src="https://unpkg.com/@smartledger/bsv@8.3.1/bsv-smartcontract.min.js"></script>
|
|
444
|
-
<script>
|
|
445
|
-
const covenant = bsv.SmartContract.createCovenantBuilder()
|
|
446
|
-
.extractField('amount').push(50000).greaterThanOrEqual().verify().build();
|
|
447
|
-
const debugInfo = bsv.SmartContract.examineStack(script);
|
|
448
|
-
</script>
|
|
449
|
-
```
|
|
450
|
-
|
|
451
|
-
### 🆕 **Legal & Identity Development** (~2.55MB total — each bundle re-embeds core BSV)
|
|
452
|
-
```html
|
|
453
|
-
<script src="https://unpkg.com/@smartledger/bsv@8.3.1/bsv.min.js"></script>
|
|
454
|
-
<script src="https://unpkg.com/@smartledger/bsv@8.3.1/bsv-ltp.min.js"></script>
|
|
455
|
-
<script src="https://unpkg.com/@smartledger/bsv@8.3.1/bsv-gdaf.min.js"></script>
|
|
456
|
-
<script>
|
|
457
|
-
// Legal Token Protocol
|
|
458
|
-
const result = bsv.LTP.createRightToken({
|
|
459
|
-
type: bsv.LTP.Right.RightTypes.PROPERTY_TITLE,
|
|
460
|
-
owner: ownerDID, jurisdiction: 'us_delaware'
|
|
461
|
-
}, key);
|
|
462
|
-
|
|
463
|
-
// Digital Identity
|
|
464
|
-
const credential = bsv.createEmailCredential(issuerDID, subjectDID, 'user@example.com', key);
|
|
465
|
-
</script>
|
|
466
|
-
```
|
|
467
|
-
|
|
468
|
-
### 🆕 **Security & Cryptography** (~1.22MB total)
|
|
469
|
-
```html
|
|
470
|
-
<script src="https://unpkg.com/@smartledger/bsv@8.3.1/bsv.min.js"></script>
|
|
471
|
-
<script src="https://unpkg.com/@smartledger/bsv@8.3.1/bsv-security.min.js"></script>
|
|
472
|
-
<script src="https://unpkg.com/@smartledger/bsv@8.3.1/bsv-shamir.min.js"></script>
|
|
473
|
-
<script>
|
|
474
|
-
// Threshold Cryptography
|
|
475
|
-
const shares = bsv.Shamir.split('my_secret_key', 3, 5); // 5 shares, any 3 recover
|
|
476
|
-
|
|
477
|
-
// Enhanced Security
|
|
478
|
-
const verified = bsvSecurity.SmartVerify.smartVerify(hash, signature, publicKey);
|
|
479
|
-
</script>
|
|
480
|
-
```
|
|
481
|
-
|
|
482
|
-
### 🎯 **Everything Bundle** (~1.02MB)
|
|
483
|
-
```html
|
|
484
|
-
<script src="https://unpkg.com/@smartledger/bsv@8.3.1/bsv.bundle.js"></script>
|
|
485
|
-
<script>
|
|
486
|
-
// Everything available immediately
|
|
487
|
-
const shares = bsv.Shamir.split('secret', 3, 5); // Shamir Secret Sharing
|
|
488
|
-
const did = bsv.createDID(publicKey); // Digital Identity
|
|
489
|
-
const token = bsv.LTP.createRightToken({ /* ... */ }, key); // Legal Tokens
|
|
490
|
-
const covenant = bsv.SmartContract.createCovenantBuilder(); // Smart Contracts
|
|
491
|
-
</script>
|
|
492
|
-
```
|
|
493
|
-
|
|
494
|
-
## 🎯 **Key Features**
|
|
495
|
-
|
|
496
|
-
### 🚀 **Unique Capabilities** (Only Bitcoin Library with These Features)
|
|
497
|
-
- ✅ **Legal Token Protocol**: Compliant tokenization of real-world assets → [Legal Guide](docs/advanced/LEGAL_TOKEN_PROTOCOL.md)
|
|
498
|
-
- ✅ **Digital Identity Framework**: W3C Verifiable Credentials and DIDs → [Identity Guide](docs/technical/GDAF_DEVELOPER_INTERFACE.md)
|
|
499
|
-
- ✅ **Threshold Cryptography**: Shamir Secret Sharing for secure key management → [Cryptography Guide](docs/technical/SHAMIR_INTEGRATION_SUMMARY.md)
|
|
500
|
-
- ✅ **Complete Smart Contract Suite**: 23+ production-ready covenant features → [SmartContract Guide](docs/advanced/SMART_CONTRACT_GUIDE.md)
|
|
501
|
-
|
|
502
|
-
### 💼 **Core Library Excellence**
|
|
503
|
-
- ✅ **Complete BSV API**: Full Bitcoin SV blockchain operations → [API Reference](#-api-reference)
|
|
504
|
-
- ✅ **Opt-in security helpers**: `bsv.SmartVerify` and `bsv.EllipticFixed` add input validation and low-`s` canonicalization on top of standard verification — **not on the default verify path**, see [Security](#-security)
|
|
505
|
-
- ✅ **Browser + Node.js**: Universal compatibility with proper polyfills → [Loading Options](#-16-loading-options---choose-your-approach)
|
|
506
|
-
- ✅ **TypeScript Ready**: Complete type definitions included
|
|
507
|
-
- ✅ **Ultra-Low Fees**: 0.01 sats/byte configuration (91% fee reduction)
|
|
508
|
-
|
|
509
|
-
### 🛠️ **Advanced Development Tools**
|
|
510
|
-
- 🔧 **JavaScript-to-Script**: High-level covenant development with 121 opcode mapping → [Covenant Guide](docs/advanced/ADVANCED_COVENANT_DEVELOPMENT.md)
|
|
511
|
-
- 🔧 **UTXO Generator**: Create authentic test UTXOs for development → [UTXO Guide](docs/advanced/UTXO_MANAGER_GUIDE.md)
|
|
512
|
-
- 🔧 **Preimage Parser**: Complete BIP-143 field extraction and manipulation → [Preimage Tools](https://github.com/codenlighten/smartledger-bsv/tree/main/examples/preimage)
|
|
513
|
-
- 🔧 **Debug Framework**: Script interpreter, stack examiner, and optimizer → [Debug Examples](https://github.com/codenlighten/smartledger-bsv/blob/main/tests/smartcontract-test.html)
|
|
514
|
-
- 🔧 **PUSHTX Integration**: nChain techniques for advanced covenant patterns → [PUSHTX Insights](docs/pushtx-key-insights.md)
|
|
515
|
-
|
|
516
|
-
### 📦 **Flexible Architecture**
|
|
517
|
-
- 📦 **16 Modular Options**: Load only what you need (32KB to 1039KB) → [Loading Strategy](#-16-loading-options---choose-your-approach)
|
|
518
|
-
- 📦 **Standalone Modules**: Independent legal, identity, and crypto modules → [Standalone Test](https://github.com/codenlighten/smartledger-bsv/blob/main/tests/standalone-modules-test.html)
|
|
519
|
-
- 📦 **Complete Bundle**: Everything in one file for convenience → [Bundle Demo](https://github.com/codenlighten/smartledger-bsv/blob/main/tests/bundle-demo.html)
|
|
520
|
-
- 📦 **CDN Ready**: All modules available via unpkg and jsDelivr
|
|
521
|
-
- 📦 **Webpack Optimized**: Tree-shakeable and build-tool friendly
|
|
522
|
-
|
|
523
|
-
## ⚡ **Installation & Usage**
|
|
524
|
-
|
|
525
|
-
> 💡 **Quick Start**: Jump to [2-Minute Quick Start](#-2-minute-quick-start) for instant setup examples
|
|
526
|
-
|
|
527
|
-
### NPM Installation
|
|
528
|
-
```bash
|
|
529
|
-
npm install @smartledger/bsv
|
|
530
|
-
```
|
|
531
|
-
|
|
532
|
-
> 📖 **Next Steps**: After installation, see [Loading Options](#-16-loading-options---choose-your-approach) to choose your distribution method
|
|
533
|
-
|
|
534
|
-
### Upgrading to v8.0.0 (Breaking Changes)
|
|
535
|
-
|
|
536
|
-
8.0.0 moved the defaults onto BSV as the network actually runs it. Two changes
|
|
537
|
-
need action.
|
|
538
|
-
|
|
539
|
-
**1. `verify()` with no flags now means BSV mainnet, not "no rules".**
|
|
540
|
-
|
|
541
|
-
```javascript
|
|
542
|
-
interp.verify(sig, pubkey, tx, nin) // was: Bitcoin 2015; now: current mainnet
|
|
543
|
-
interp.verify(sig, pubkey, tx, nin, 0) // the old behaviour, stated explicitly
|
|
544
|
-
|
|
545
|
-
// Spending a pre-Chronicle output — state the era of the output being spent,
|
|
546
|
-
// because that is the input the caller knows and the library cannot infer.
|
|
547
|
-
bsv.Script.Interpreter.mainnetFlags({ afterChronicle: false })
|
|
548
|
-
```
|
|
549
|
-
|
|
550
|
-
**2. Two flag constants changed numeric value.** The node assigns `1<<18` and
|
|
551
|
-
`1<<19` to `SCRIPT_GENESIS` and `SCRIPT_UTXO_AFTER_GENESIS`, so ours had to move:
|
|
552
|
-
|
|
553
|
-
```
|
|
554
|
-
SCRIPT_ENABLE_MONOLITH_OPCODES 1<<18 → 1<<11
|
|
555
|
-
SCRIPT_ENABLE_MAGNETIC_OPCODES 1<<19 → 1<<12
|
|
556
|
-
```
|
|
557
|
-
|
|
558
|
-
Code using the **named constants** is unaffected. Code that **persisted or
|
|
559
|
-
hardcoded the numbers** must be updated: `262144` no longer means "Monolith
|
|
560
|
-
opcodes", it now means `SCRIPT_GENESIS`, so a stored value silently selects a
|
|
561
|
-
different era model.
|
|
562
|
-
|
|
563
|
-
Also in 8.0.0: a signature carrying `SIGHASH_CHRONICLE` outside Chronicle is
|
|
564
|
-
rejected rather than reinterpreted, and `MAX_OPS_PER_SCRIPT` is BSV's 500 rather
|
|
565
|
-
than Bitcoin Core's 201. Full details in the
|
|
566
|
-
[CHANGELOG](./CHANGELOG.md#800---2026-08-13).
|
|
567
|
-
|
|
568
|
-
### Upgrading to v5.0.0 (Breaking Changes)
|
|
569
|
-
|
|
570
|
-
v5.0.0 hardens the cryptography. Most apps need **no code changes** — the
|
|
571
|
-
breaking changes only affect data produced by older versions:
|
|
572
|
-
|
|
573
|
-
- **Shamir shares.** `Shamir.split()` now returns the **v2 share format**
|
|
574
|
-
(backed by a vetted GF(2⁸) engine). Shares created with ≤ 4.x still
|
|
575
|
-
reconstruct — `Shamir.combine()` and `Shamir.verifyShare()` auto-detect and
|
|
576
|
-
accept legacy shares for recovery. No flag needed.
|
|
577
|
-
- **VC-JWT signatures.** Tokens are now signed and verified as JOSE-standard
|
|
578
|
-
**IEEE P1363** (`r||s`) instead of DER, so they interoperate with `jose`,
|
|
579
|
-
`jsonwebtoken`, etc. Tokens **issued by ≤ 4.6.0 are DER-encoded** and will
|
|
580
|
-
fail verification by default — pass `{ allowLegacyDER: true }` while you
|
|
581
|
-
re-issue:
|
|
582
|
-
```javascript
|
|
583
|
-
const result = await bsv.VcJwt.verifyVcJwt(oldToken, {
|
|
584
|
-
didResolver,
|
|
585
|
-
allowLegacyDER: true // accept ≤ 4.6.0 DER-signed tokens during migration
|
|
586
|
-
});
|
|
587
|
-
```
|
|
588
|
-
- **VC-JWT algorithm pinning.** `verifyVcJwt` rejects any token whose `alg` is
|
|
589
|
-
outside `['ES256','ES256K']` (override via `opts.allowedAlgs`) and binds the
|
|
590
|
-
key's curve to the algorithm — defense against alg-substitution attacks.
|
|
591
|
-
- **Browser bundles changed size.** The full bundles ship a real `crypto`
|
|
592
|
-
polyfill so Shamir can source a CSPRNG. Sizes have moved since; `bsv.min.js` is
|
|
593
|
-
~1039KB at 8.3.0, after the ~20% reduction in 8.0.0. The dedicated
|
|
594
|
-
single-feature module bundles are unaffected.
|
|
201
|
+
Pin the version in CDN URLs. A floating `@latest` will move under you even
|
|
202
|
+
within 9.x.
|
|
595
203
|
|
|
596
|
-
|
|
204
|
+
## Documentation
|
|
597
205
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
const metrics = bsv.SmartContract.getScriptMetrics(script);
|
|
610
|
-
const stackInfo = bsv.SmartContract.examineStack(script);
|
|
611
|
-
|
|
612
|
-
// Covenant development — see bsv.SmartContract for the covenant stack
|
|
613
|
-
const lock = bsv.SmartContract.perpetualCovenant(500);
|
|
614
|
-
const { ok, err } = bsv.SmartContract.verifyScript(unlockScript, lock, { tx, satoshis });
|
|
615
|
-
```
|
|
616
|
-
|
|
617
|
-
### Browser CDN (Choose Your Loading Strategy)
|
|
618
|
-
|
|
619
|
-
#### 1. **Minimal Setup** - Core + Script Helper (~1.05MB)
|
|
620
|
-
```html
|
|
621
|
-
<script src="https://unpkg.com/@smartledger/bsv@8.3.1/bsv.min.js"></script>
|
|
622
|
-
<script src="https://unpkg.com/@smartledger/bsv@8.3.1/bsv-script-helper.min.js"></script>
|
|
623
|
-
<script>
|
|
624
|
-
const tx = new bsv.Transaction();
|
|
625
|
-
const sig = bsvScriptHelper.createSignature(tx, privateKey, 0, script, satoshis);
|
|
626
|
-
</script>
|
|
627
|
-
```
|
|
628
|
-
|
|
629
|
-
#### 2. **DeFi Development** - Core + Covenants + Debug (~1.2MB — each bundle re-embeds core BSV)
|
|
630
|
-
```html
|
|
631
|
-
<script src="https://unpkg.com/@smartledger/bsv@8.3.1/bsv.min.js"></script>
|
|
632
|
-
<script src="https://unpkg.com/@smartledger/bsv@8.3.1/bsv-covenant.min.js"></script>
|
|
633
|
-
<script src="https://unpkg.com/@smartledger/bsv@8.3.1/bsv-smartcontract.min.js"></script>
|
|
634
|
-
<script>
|
|
635
|
-
const lock = bsv.SmartContract.perpetualCovenant(500);
|
|
636
|
-
const debugInfo = bsv.SmartContract.interpretScript(script);
|
|
637
|
-
const optimized = bsv.SmartContract.optimizeScript(script);
|
|
638
|
-
</script>
|
|
639
|
-
```
|
|
640
|
-
|
|
641
|
-
#### 3. **Security First** - Core + Enhanced Security (~1.05MB)
|
|
642
|
-
```html
|
|
643
|
-
<script src="https://unpkg.com/@smartledger/bsv@8.3.1/bsv.min.js"></script>
|
|
644
|
-
<script src="https://unpkg.com/@smartledger/bsv@8.3.1/bsv-security.min.js"></script>
|
|
645
|
-
<script>
|
|
646
|
-
const verified = bsvSecurity.SmartVerify.smartVerify(hash, signature, publicKey);
|
|
647
|
-
const enhanced = bsvSecurity.EllipticFixed.sign(hash, privateKey);
|
|
648
|
-
</script>
|
|
649
|
-
```
|
|
650
|
-
|
|
651
|
-
#### 4. **Everything Bundle** - One File Solution (~1.02MB)
|
|
652
|
-
```html
|
|
653
|
-
<script src="https://unpkg.com/@smartledger/bsv@8.3.1/bsv.bundle.js"></script>
|
|
654
|
-
<script>
|
|
655
|
-
// Everything available under the bsv namespace
|
|
656
|
-
const key = bsv.PrivateKey.fromRandom();
|
|
657
|
-
const lock = bsv.SmartContract.perpetualCovenant(500);
|
|
658
|
-
const message = new bsv.Message('Hello BSV');
|
|
659
|
-
const encrypted = new bsv.ECIES()
|
|
660
|
-
.privateKey(key)
|
|
661
|
-
.publicKey(recipientPublicKey)
|
|
662
|
-
.encrypt('secret');
|
|
663
|
-
</script>
|
|
664
|
-
```
|
|
665
|
-
|
|
666
|
-
## 🔨 Basic Usage
|
|
667
|
-
|
|
668
|
-
### Creating Transactions
|
|
669
|
-
```javascript
|
|
670
|
-
const bsv = require('@smartledger/bsv');
|
|
671
|
-
|
|
672
|
-
// Create transaction with optimized fees
|
|
673
|
-
const transaction = new bsv.Transaction()
|
|
674
|
-
.from({
|
|
675
|
-
txId: 'prev_tx_id',
|
|
676
|
-
outputIndex: 0,
|
|
677
|
-
script: 'prev_locking_script',
|
|
678
|
-
satoshis: 100000
|
|
679
|
-
})
|
|
680
|
-
.to('1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa', 95000)
|
|
681
|
-
.feePerKb(10) // Ultra-low fee: 0.01 sats/byte
|
|
682
|
-
.sign(privateKey);
|
|
683
|
-
|
|
684
|
-
console.log('Transaction ID:', transaction.id);
|
|
685
|
-
console.log('Fee rate: 0.01 sats/byte (91% reduction)');
|
|
686
|
-
```
|
|
687
|
-
|
|
688
|
-
### UTXO Management
|
|
689
|
-
```javascript
|
|
690
|
-
// Advanced UTXO state management
|
|
691
|
-
const utxoManager = {
|
|
692
|
-
createWithChange: (inputs, outputs, changeAddress) => {
|
|
693
|
-
const tx = new bsv.Transaction()
|
|
694
|
-
.from(inputs)
|
|
695
|
-
.to(outputs.address, outputs.amount)
|
|
696
|
-
.change(changeAddress)
|
|
697
|
-
.feePerKb(10);
|
|
698
|
-
|
|
699
|
-
// Automatic change output creation and UTXO state update
|
|
700
|
-
return tx;
|
|
701
|
-
}
|
|
702
|
-
};
|
|
703
|
-
```
|
|
704
|
-
|
|
705
|
-
## 🆕 **Advanced Features** (Unique to SmartLedger-BSV)
|
|
706
|
-
|
|
707
|
-
### ⚖️ Legal Token Protocol (LTP)
|
|
708
|
-
```javascript
|
|
709
|
-
const bsv = require('@smartledger/bsv');
|
|
710
|
-
|
|
711
|
-
// Create a property-rights token. `type` must be one of LTP.Right.RightTypes —
|
|
712
|
-
// an unrecognized type is rejected rather than silently accepted.
|
|
713
|
-
const result = bsv.LTP.createRightToken({
|
|
714
|
-
type: bsv.LTP.Right.RightTypes.PROPERTY_TITLE,
|
|
715
|
-
owner: ownerDID,
|
|
716
|
-
jurisdiction: 'us_delaware',
|
|
717
|
-
legalDescription: 'Lot 15, Block 3, Subdivision ABC'
|
|
718
|
-
}, issuerPrivateKey);
|
|
719
|
-
|
|
720
|
-
console.log(result.success); // true
|
|
721
|
-
console.log(result.token.tokenHash); // hash committed by the token's proof
|
|
722
|
-
|
|
723
|
-
// Obligation tokens
|
|
724
|
-
const obligation = bsv.LTP.Obligation.prepareObligationToken({
|
|
725
|
-
obligationType: 'payment',
|
|
726
|
-
amount: 100000, // satoshis
|
|
727
|
-
dueDate: '2026-12-31',
|
|
728
|
-
creditor: creditorDID,
|
|
729
|
-
debtor: debtorDID
|
|
730
|
-
});
|
|
731
|
-
|
|
732
|
-
// Validate claim data against a registered schema
|
|
733
|
-
// (schema names come from bsv.LTP.Claim.getSchemaNames())
|
|
734
|
-
const validation = bsv.validateLegalClaim(claimData, schemaType);
|
|
735
|
-
```
|
|
736
|
-
|
|
737
|
-
### 🌐 Global Digital Attestation Framework (GDAF)
|
|
738
|
-
```javascript
|
|
739
|
-
// Simple Interface - Direct from bsv object
|
|
740
|
-
const issuerDID = bsv.createDID(privateKey.toPublicKey());
|
|
741
|
-
|
|
742
|
-
// Create W3C Verifiable Credentials
|
|
743
|
-
const emailCredential = bsv.createEmailCredential(
|
|
744
|
-
issuerDID, subjectDID, 'user@example.com', issuerPrivateKey
|
|
745
|
-
);
|
|
746
|
-
|
|
747
|
-
// Generate zero-knowledge proofs
|
|
748
|
-
const proof = bsv.generateSelectiveProof(
|
|
749
|
-
emailCredential,
|
|
750
|
-
['credentialSubject.verified'],
|
|
751
|
-
nonce
|
|
752
|
-
);
|
|
753
|
-
|
|
754
|
-
// Verify age without revealing exact age
|
|
755
|
-
const ageProof = bsv.generateAgeProof(credential, 18);
|
|
756
|
-
const isAdult = bsv.verifyAgeProof(ageProof, 18, issuerDID);
|
|
757
|
-
|
|
758
|
-
// Advanced Interface for complex applications
|
|
759
|
-
const gdaf = new bsv.GDAF({
|
|
760
|
-
anchor: { network: 'mainnet' },
|
|
761
|
-
attestationSigner: { customConfig: true }
|
|
762
|
-
});
|
|
763
|
-
```
|
|
764
|
-
|
|
765
|
-
### 🔐 Shamir Secret Sharing
|
|
766
|
-
```javascript
|
|
767
|
-
// Split a secret into threshold shares.
|
|
768
|
-
// Signature is split(secret, threshold, shares) — THRESHOLD FIRST.
|
|
769
|
-
const secret = 'my_private_key_backup';
|
|
770
|
-
const shares = bsv.Shamir.split(secret, 3, 5); // 5 shares, any 3 reconstruct
|
|
771
|
-
|
|
772
|
-
console.log('Generated', shares.length, 'shares');
|
|
773
|
-
|
|
774
|
-
// Reconstruct from any 3 shares
|
|
775
|
-
const reconstructed = bsv.Shamir.combine([shares[0], shares[2], shares[4]]);
|
|
776
|
-
console.log('Secret recovered:', reconstructed === secret); // true
|
|
777
|
-
|
|
778
|
-
// Validate share integrity
|
|
779
|
-
shares.forEach((share, i) => {
|
|
780
|
-
console.log(`Share ${i + 1} valid:`, bsv.Shamir.verifyShare(share));
|
|
781
|
-
});
|
|
782
|
-
|
|
783
|
-
// Use cases: Key backup, multi-party security, recovery systems
|
|
784
|
-
```
|
|
785
|
-
|
|
786
|
-
## 🔒 Covenant Framework
|
|
787
|
-
|
|
788
|
-
### JavaScript-to-Bitcoin Script Translation
|
|
789
|
-
```javascript
|
|
790
|
-
const { CovenantBuilder, CovenantTemplates } = require('@smartledger/bsv/lib/smart_contract');
|
|
791
|
-
|
|
792
|
-
// Write covenant logic in JavaScript
|
|
793
|
-
const valueLock = CovenantTemplates.valueLock('50c3000000000000');
|
|
794
|
-
const script = valueLock.build();
|
|
795
|
-
console.log(script.cleanedASM);
|
|
796
|
-
// Output: OP_SIZE 34 OP_SUB OP_SPLIT OP_DROP OP_8 OP_SPLIT OP_DROP 50c3000000000000 OP_EQUALVERIFY OP_1
|
|
797
|
-
|
|
798
|
-
// Custom covenant builder
|
|
799
|
-
const custom = new CovenantBuilder()
|
|
800
|
-
.comment('Validate preimage value field')
|
|
801
|
-
.extractField('value')
|
|
802
|
-
.push('50c3000000000000')
|
|
803
|
-
.equalVerify()
|
|
804
|
-
.push(1);
|
|
805
|
-
```
|
|
806
|
-
|
|
807
|
-
### Complete Opcode Mapping (116 Opcodes)
|
|
808
|
-
```javascript
|
|
809
|
-
const SmartContract = require('@smartledger/bsv/lib/smart_contract');
|
|
810
|
-
|
|
811
|
-
// Simulate script execution in JavaScript
|
|
812
|
-
const result = SmartContract.simulateScript(['OP_1', 'OP_2', 'OP_ADD', 'OP_3', 'OP_EQUAL']);
|
|
813
|
-
console.log(result.finalStack); // ['01'] - TRUE
|
|
814
|
-
|
|
815
|
-
// Get comprehensive opcode information
|
|
816
|
-
const opcodes = SmartContract.getOpcodeMap();
|
|
817
|
-
console.log(Object.keys(opcodes).length); // 116 opcodes mapped
|
|
818
|
-
```
|
|
819
|
-
|
|
820
|
-
### BIP143 Preimage Parsing
|
|
821
|
-
```javascript
|
|
822
|
-
const { CovenantPreimage } = require('@smartledger/bsv/lib/covenant-interface');
|
|
823
|
-
|
|
824
|
-
// Enhanced preimage parsing with field-by-field access
|
|
825
|
-
const preimage = new CovenantPreimage(preimageHex);
|
|
826
|
-
|
|
827
|
-
console.log('Version:', preimage.nVersionValue); // uint32 accessor
|
|
828
|
-
console.log('Amount:', preimage.amountValue); // BigInt accessor
|
|
829
|
-
console.log('Valid structure:', preimage.isValid); // Boolean validation
|
|
830
|
-
```
|
|
831
|
-
|
|
832
|
-
### PUSHTX Covenants (nChain WP1605)
|
|
833
|
-
```javascript
|
|
834
|
-
const bsv = require('@smartledger/bsv')
|
|
835
|
-
const SC = bsv.SmartContract
|
|
836
|
-
SC.enableGenesis() // OP_PUSH_TX needs post-Genesis limits
|
|
837
|
-
|
|
838
|
-
// Bare OP_PUSH_TX authenticator: unlocks only with the (grindable) preimage of
|
|
839
|
-
// THIS transaction. Built from the nChain `a=k=1` public-key construction —
|
|
840
|
-
// the script generates an ECDSA signature in-script from the pushed preimage
|
|
841
|
-
// (r=Gx, s=(e+Gx) mod n) and verifies it with OP_CHECKSIG, which only passes
|
|
842
|
-
// if the preimage matches this very spend.
|
|
843
|
-
const authLock = SC.PushTx.authenticator()
|
|
844
|
-
|
|
845
|
-
// Value covenant — force spend outputs to match a specific hashOutputs.
|
|
846
|
-
const requiredOutputs = [/* bsv.Transaction.Output objects */]
|
|
847
|
-
const valueLock = SC.PushTx.valueCovenant(SC.PushTx.hashOutputs(requiredOutputs))
|
|
848
|
-
```
|
|
849
|
-
|
|
850
|
-
### Perpetually Enforcing Locking Scripts (PELS)
|
|
851
|
-
```javascript
|
|
852
|
-
// Self-replicating covenant: every spend must recreate the same script
|
|
853
|
-
// (value − fee), reading its own code out of the authenticated preimage's
|
|
854
|
-
// scriptCode field. No self-hash circularity.
|
|
855
|
-
const pels = SC.perpetualCovenant(500) // fee in satoshis deducted each hop
|
|
856
|
-
```
|
|
857
|
-
|
|
858
|
-
### Ownership Tokens (NFT)
|
|
859
|
-
```javascript
|
|
860
|
-
// Stateful ownership token. Owner is carried as on-chain state (HASH160 of the
|
|
861
|
-
// owner's public key); transfer requires the current owner's ECDSA SIGNATURE over
|
|
862
|
-
// the spend (OP_CHECKSIG) and rewrites state, perpetuating the token code across
|
|
863
|
-
// the chain of spends. The signature commits to the chosen next owner, so a
|
|
864
|
-
// mempool watcher cannot redirect a pending transfer (no hash-lock front-running).
|
|
865
|
-
const ownerHash = SC.Token.ownerId(currentOwnerKey) // = HASH160(pubkey)
|
|
866
|
-
const token = SC.ownershipToken(500, ownerHash)
|
|
867
|
-
// To spend it forward to `nextOwnerHash`, the current owner signs:
|
|
868
|
-
// tokenInput.setScript(SC.Token.unlockTransfer(currentOwnerKey, nextOwnerHash, spendTx, sats, token))
|
|
869
|
-
|
|
870
|
-
// Pluggable ownership — the SAME covenant, owned by an m-of-n group. Ownership is
|
|
871
|
-
// committed as a 20-byte hash either way, so the transfer plumbing is identical.
|
|
872
|
-
const ms = SC.Authorizers.multisig(2, 3)
|
|
873
|
-
const groupToken = SC.Token.ownershipToken(500, ms.commit([pkA, pkB, pkC]), ms)
|
|
874
|
-
// transfer requires any 2 of the 3 keys:
|
|
875
|
-
// SC.Token.unlockTransfer({ keys: [pkA, pkB, pkC], signWith: [skA, skC] },
|
|
876
|
-
// nextOwnerHash, spendTx, sats, groupToken, { auth: ms })
|
|
877
|
-
// Custom schemes: SC.Authorizers.predicate({ commit, emit, unlockArgs }).
|
|
878
|
-
|
|
879
|
-
// N-output: recreate the token alongside other outputs (payments, change, data).
|
|
880
|
-
// The spender reveals the surrounding output bytes; the covenant binds them all.
|
|
881
|
-
const multi = SC.Token.ownershipTokenMulti(ownerHash)
|
|
882
|
-
// SC.Token.unlockTransferMulti(currentOwnerKey, nextOwnerHash, spendTx, sats, multi,
|
|
883
|
-
// { before: serializedOutputsBeforeToken, after: serializedOutputsAfterToken, tokenValue: le8(value) })
|
|
884
|
-
```
|
|
885
|
-
|
|
886
|
-
### End-to-end verification
|
|
887
|
-
|
|
888
|
-
```javascript
|
|
889
|
-
// Any locking script can be verified end-to-end through Script.Interpreter,
|
|
890
|
-
// with the consensus flags this library was tested against.
|
|
891
|
-
const ok = SC.verifyScript(unlockScript, lockingScript, tx, inputIndex, satoshis)
|
|
892
|
-
```
|
|
893
|
-
|
|
894
|
-
### Consensus defaults — BSV mainnet, no flags required (8.0.0+)
|
|
895
|
-
|
|
896
|
-
**Since 8.0.0 you do not opt in to BSV.** `verify()` with no flags means
|
|
897
|
-
current BSV mainnet consensus, and `MAX_OPS_PER_SCRIPT` is BSV's 500 rather
|
|
898
|
-
than Bitcoin Core's 201. Earlier versions defaulted to a 2015-era Bitcoin
|
|
899
|
-
rule set and required an explicit call to reach post-Genesis behaviour; that
|
|
900
|
-
is no longer the case.
|
|
901
|
-
|
|
902
|
-
```javascript
|
|
903
|
-
const bsv = require('@smartledger/bsv');
|
|
904
|
-
const interp = new bsv.Script.Interpreter();
|
|
905
|
-
|
|
906
|
-
// Current BSV mainnet — this is the default.
|
|
907
|
-
const ok = interp.verify(unlockScript, lockScript, tx, 0, undefined, satoshisBN);
|
|
908
|
-
|
|
909
|
-
// Spending a pre-Chronicle output: state the era of the output you are spending,
|
|
910
|
-
// because the library cannot infer it.
|
|
911
|
-
const flags = bsv.Script.Interpreter.mainnetFlags({ afterChronicle: false });
|
|
912
|
-
const ok2 = interp.verify(unlockScript, lockScript, tx, 0, flags, satoshisBN);
|
|
913
|
-
|
|
914
|
-
// The pre-8.0.0 "no rules" behaviour, if you genuinely want it, is now explicit:
|
|
915
|
-
const ok3 = interp.verify(unlockScript, lockScript, tx, 0, 0, satoshisBN);
|
|
916
|
-
```
|
|
917
|
-
|
|
918
|
-
**Covenants need no special setup.** The element and script-number caps are
|
|
919
|
-
derived from the era flags, not from the `MAX_SCRIPT_ELEMENT_SIZE` static — which
|
|
920
|
-
still reads 520 because it is only the pre-Genesis fallback. An OP_PUSH_TX
|
|
921
|
-
covenant pushing a ~585-byte preimage verifies under the defaults:
|
|
922
|
-
|
|
923
|
-
```javascript
|
|
924
|
-
const interp = new bsv.Script.Interpreter();
|
|
925
|
-
const ok = interp.verify(unlockScript, lockScript, tx, 0, undefined, satoshisBN);
|
|
926
|
-
```
|
|
927
|
-
|
|
928
|
-
> ⚠️ **`Interpreter.useGenesisLimits()` is legacy and should not be used to enable
|
|
929
|
-
> covenants.** It cannot enable post-Genesis arithmetic — that comes from the era
|
|
930
|
-
> flags — and because it mutates process-wide statics it *weakens* pre-Genesis
|
|
931
|
-
> validation: raising `MAXIMUM_ELEMENT_SIZE` turns 15 of the reference node's 22
|
|
932
|
-
> `SCRIPTNUM_OVERFLOW` vectors into false accepts. If you must call it, capture
|
|
933
|
-
> and restore the caps around it with `Interpreter.getLimits()` /
|
|
934
|
-
> `Interpreter.setLimits()`.
|
|
935
|
-
|
|
936
|
-
## 🛠️ Custom Scripts
|
|
937
|
-
|
|
938
|
-
### Multi-signature Scripts
|
|
939
|
-
```javascript
|
|
940
|
-
const { CustomScriptHelper } = require('@smartledger/bsv/lib/custom-script-helper');
|
|
941
|
-
const helper = new CustomScriptHelper();
|
|
942
|
-
|
|
943
|
-
// Create 2-of-3 multisig script
|
|
944
|
-
const multisigScript = helper.createMultisigScript([
|
|
945
|
-
publicKey1, publicKey2, publicKey3
|
|
946
|
-
], 2);
|
|
947
|
-
```
|
|
948
|
-
|
|
949
|
-
### Timelock Contracts
|
|
950
|
-
```javascript
|
|
951
|
-
// Create timelock script (block height)
|
|
952
|
-
const timelockScript = helper.createTimelockScript(
|
|
953
|
-
publicKey,
|
|
954
|
-
750000, // block height
|
|
955
|
-
'block'
|
|
956
|
-
);
|
|
957
|
-
```
|
|
958
|
-
|
|
959
|
-
## 📁 Examples
|
|
960
|
-
|
|
961
|
-
### Basic Examples
|
|
962
|
-
- **[Advanced Covenant Demo](advanced_covenant_demo.js)**: Complete covenant showcase
|
|
963
|
-
- **[Custom Script Tests](test/custom_script_signature_test.js)**: Script development examples
|
|
964
|
-
- **[Covenant Resolution](covenant_manual_signature_resolved.js)**: Working covenant patterns
|
|
965
|
-
|
|
966
|
-
### Documentation
|
|
967
|
-
- **[Advanced Covenant Development](ADVANCED_COVENANT_DEVELOPMENT.md)**: Complete BIP143 + PUSHTX guide
|
|
968
|
-
- **[Custom Script Development](CUSTOM_SCRIPT_DEVELOPMENT.md)**: Script creation patterns
|
|
969
|
-
- **[Covenant Development Resolved](COVENANT_DEVELOPMENT_RESOLVED.md)**: Problem solutions
|
|
970
|
-
|
|
971
|
-
## 🔧 CDN Bundles
|
|
972
|
-
|
|
973
|
-
See the **[16 Loading Options](#-16-loading-options---choose-your-approach)**
|
|
974
|
-
table near the top for the full list of bundles with current sizes and
|
|
975
|
-
canonical `unpkg.com/@smartledger/bsv@8.3.1/...` URLs.
|
|
976
|
-
|
|
977
|
-
## 🔐 Security
|
|
978
|
-
|
|
979
|
-
### What's actually in the box
|
|
980
|
-
|
|
981
|
-
| Surface | Status | Notes |
|
|
982
|
-
|---------|--------|-------|
|
|
983
|
-
| secp256k1 primitives | `@noble/curves` | `elliptic` was removed entirely — it is not a dependency and is not in the bundles. The Noble suite carries a published Cure53 audit. |
|
|
984
|
-
| Default `transaction.verify()` / `signature.verify()` / `Message().verify()` | uses BSV's own `lib/crypto/ecdsa.js` | This path does **not** import elliptic and is **not** routed through `SmartVerify` or `EllipticFixed`. |
|
|
985
|
-
| `bsv.SmartVerify` (opt-in helper) | available | Hardened standalone verify: rejects `r=0`, `s=0`, `r≥n`, `s≥n`; canonicalizes `s` to low half. Built on BSV's own `BN`/`ECDSA`. You must call it explicitly. |
|
|
986
|
-
| `bsv.EllipticFixed` (opt-in helper) | available | An elliptic-*compatible* secp256k1 surface — the name is kept for API compatibility, but it is backed by `@noble/curves`. Adds the same input checks plus low-`s` on sign. |
|
|
987
|
-
| `signature.validate()` / `isCanonical()` / `toCanonical()` | available | Real methods on `bsv.Signature`. |
|
|
988
|
-
| DER canonicalization on TX signing | available | BSV's signature path produces low-`s` DER by default. |
|
|
989
|
-
| BIP143 preimage utilities | available | `lib/smart_contract/preimage.js` and `examples/preimage/`. |
|
|
990
|
-
|
|
991
|
-
### Using the opt-in helpers
|
|
992
|
-
|
|
993
|
-
```js
|
|
994
|
-
const bsv = require('@smartledger/bsv')
|
|
995
|
-
|
|
996
|
-
// Hardened verify (recommended if you accept signatures from untrusted sources):
|
|
997
|
-
const ok = bsv.SmartVerify.smartVerify(msgHashBuffer, derSigBuffer, publicKey)
|
|
998
|
-
|
|
999
|
-
// Or call BSV's own ECDSA via the standard API (no SmartVerify hardening):
|
|
1000
|
-
const okDefault = bsv.crypto.ECDSA.verify(msgHashBuffer, signature, publicKey)
|
|
1001
|
-
```
|
|
1002
|
-
|
|
1003
|
-
### What this library does **not** claim
|
|
1004
|
-
|
|
1005
|
-
- It does not silently route every `verify()` call through `SmartVerify`. If you want the strict input validation on every verification, call `SmartVerify` explicitly or wrap `bsv.crypto.ECDSA.prototype.verify`.
|
|
1006
|
-
- It no longer depends on `elliptic` at all. `lib/crypto/elliptic-fixed.js` keeps the name for API compatibility but is backed by `@noble/curves`; it adds input validation and low-`s` canonicalization on top of that.
|
|
1007
|
-
- It does not turn `bsv.isHardened = true` into an automatic guarantee. That property indicates the hardening helpers ship; whether they're used is up to your code.
|
|
1008
|
-
|
|
1009
|
-
v4.0.0 fixed three critical, exploitable vulnerabilities in the GDAF
|
|
1010
|
-
credential-verification path (`_canonicalizeJSON` excluded nested claims
|
|
1011
|
-
from the signed hash; `_verifySignature` always returned truthy regardless
|
|
1012
|
-
of validity; `verificationMethod` was not bound to the credential issuer)
|
|
1013
|
-
and removed a live mainnet WIF that had been shipping inside the
|
|
1014
|
-
package. **All ≤ 3.4.5 releases should be considered untrustworthy for
|
|
1015
|
-
credential verification and must be upgraded to 4.x.** See
|
|
1016
|
-
[CHANGELOG `## [4.0.0]`](./CHANGELOG.md#400---2026-05-31) for details
|
|
1017
|
-
and [SECURITY.md](./SECURITY.md) for the supported-versions policy.
|
|
1018
|
-
|
|
1019
|
-
## 📝 Changelog
|
|
1020
|
-
|
|
1021
|
-
The authoritative version history lives in [CHANGELOG.md](./CHANGELOG.md).
|
|
1022
|
-
Highlights of the current line:
|
|
1023
|
-
|
|
1024
|
-
- **[8.3.0](./CHANGELOG.md#830---2026-08-16)** — BRC-220 **NotaryHash**:
|
|
1025
|
-
signed-hash notarization, SPV-verifiable certificates, a pluggable signature
|
|
1026
|
-
suite registry, and RFC 6962 Merkle trees for batch mode.
|
|
1027
|
-
- **[8.2.0](./CHANGELOG.md#820---2026-08-15)** — RFC 8785 (JCS) canonical JSON
|
|
1028
|
-
extracted to `lib/util/jcs.js`, so GDAF signatures verify under other
|
|
1029
|
-
implementations.
|
|
1030
|
-
- **[8.1.0](./CHANGELOG.md#810---2026-08-13)** — `useGenesisLimits()` edge-case
|
|
1031
|
-
fix.
|
|
1032
|
-
- **[8.0.0](./CHANGELOG.md#800---2026-08-13)** — **breaking.** Measured against
|
|
1033
|
-
the reference node's own consensus vectors (1483/1483, from an initial
|
|
1034
|
-
1426/1483 with 21 false accepts). `verify()` with no flags now means BSV
|
|
1035
|
-
mainnet; `SCRIPT_ENABLE_MONOLITH_OPCODES` and `SCRIPT_ENABLE_MAGNETIC_OPCODES`
|
|
1036
|
-
changed numeric value. See [Upgrading](#upgrading-to-v800-breaking-changes).
|
|
1037
|
-
- **[4.0.0](./CHANGELOG.md#400---2026-05-31)** — **security release.** Fixed
|
|
1038
|
-
three exploitable credential-verification flaws in GDAF/VC-JWT and removed a
|
|
1039
|
-
live mainnet WIF that shipped inside prior versions. All ≤ 3.4.5 should be
|
|
1040
|
-
considered untrustworthy.
|
|
1041
|
-
|
|
1042
|
-
Earlier entries are preserved in `CHANGELOG.md`.
|
|
1043
|
-
|
|
1044
|
-
---
|
|
1045
|
-
|
|
1046
|
-
## 📚 **Complete Documentation**
|
|
1047
|
-
|
|
1048
|
-
### 🚀 Getting Started
|
|
1049
|
-
- **[2-Minute Quick Start](#-2-minute-quick-start)** — npm, CDN, browser setup
|
|
1050
|
-
- **[16 Loading Options](#-16-loading-options---choose-your-approach)** — pick the bundles you need
|
|
1051
|
-
- **[API Reference](#-api-reference)** — quick method lookup
|
|
1052
|
-
- **[CHANGELOG](./CHANGELOG.md)** — version history (current line: 4.x)
|
|
1053
|
-
- **[SECURITY.md](./SECURITY.md)** — supported-versions policy + how to report
|
|
1054
|
-
|
|
1055
|
-
### 🔒 Smart Contracts & Covenants
|
|
1056
|
-
- **[Smart Contract Guide](docs/advanced/SMART_CONTRACT_GUIDE.md)** — comprehensive covenant development
|
|
1057
|
-
- **[Advanced Covenant Development](docs/advanced/ADVANCED_COVENANT_DEVELOPMENT.md)** — full BIP-143 + OP_PUSH_TX guide
|
|
1058
|
-
- **[Custom Script Development](docs/advanced/CUSTOM_SCRIPT_DEVELOPMENT.md)** — multi-sig, timelock, conditional patterns
|
|
1059
|
-
- **[UTXO Manager Guide](docs/advanced/UTXO_MANAGER_GUIDE.md)** — UTXO management + mock generation
|
|
1060
|
-
- **[Covenant Development Resolved](docs/COVENANT_DEVELOPMENT_RESOLVED.md)** — solutions to common issues
|
|
1061
|
-
- **[PUSHTX Key Insights](docs/pushtx-key-insights.md)** — nChain WP1605 implementation notes
|
|
1062
|
-
- **[SmartContract Development Guide](docs/SMART_CONTRACT_DEVELOPMENT_GUIDE.md)** — end-to-end workflow
|
|
1063
|
-
|
|
1064
|
-
### 🆕 Advanced Features
|
|
1065
|
-
- **[Legal Token Protocol](docs/advanced/LEGAL_TOKEN_PROTOCOL.md)** — property rights & obligation tokens (LTP)
|
|
1066
|
-
- **[GDAF Developer Interface](docs/technical/GDAF_DEVELOPER_INTERFACE.md)** — Global Digital Attestation Framework
|
|
1067
|
-
- **[Shamir Integration Summary](docs/technical/SHAMIR_INTEGRATION_SUMMARY.md)** — threshold cryptography & key backup
|
|
1068
|
-
|
|
1069
|
-
### 📊 Technical References
|
|
1070
|
-
- **[Module Reference](docs/MODULE_REFERENCE_COMPLETE.md)** — every shipped module
|
|
1071
|
-
- **[Documentation Review Report](docs/DOCUMENTATION_REVIEW_REPORT.md)** — internal doc audit (historical)
|
|
1072
|
-
- **[API Reference (docs/api/)](https://github.com/codenlighten/smartledger-bsv/tree/main/docs/api)** — per-module API docs
|
|
206
|
+
| | |
|
|
207
|
+
|---|---|
|
|
208
|
+
| [STABILITY.md](STABILITY.md) | release policy, deprecation process, what's covered |
|
|
209
|
+
| [docs/advanced/ADVANCED_COVENANT_DEVELOPMENT.md](docs/advanced/ADVANCED_COVENANT_DEVELOPMENT.md) | covenant patterns beyond the basics |
|
|
210
|
+
| [docs/advanced/CUSTOM_SCRIPT_DEVELOPMENT.md](docs/advanced/CUSTOM_SCRIPT_DEVELOPMENT.md) | signing arbitrary locking scripts |
|
|
211
|
+
| [docs/preimage.md](docs/preimage.md) | BIP-143 preimage field layout |
|
|
212
|
+
| [docs/pushtx-key-insights.md](docs/pushtx-key-insights.md) | the nChain OP_PUSH_TX construction and its security claims |
|
|
213
|
+
| [docs/api/SCRIPTS.md](docs/api/SCRIPTS.md) | script API reference |
|
|
214
|
+
| [docs/migration/FROM_BSV_1_5_6.md](docs/migration/FROM_BSV_1_5_6.md) | migrating from classic `bsv` |
|
|
215
|
+
| [SECURITY.md](SECURITY.md) | reporting vulnerabilities |
|
|
216
|
+
| [CHANGELOG.md](CHANGELOG.md) | release history |
|
|
1073
217
|
|
|
1074
|
-
|
|
1075
|
-
- **[Examples Directory](https://github.com/codenlighten/smartledger-bsv/tree/main/examples)** — runnable code samples
|
|
1076
|
-
- **[Demos Directory](https://github.com/codenlighten/smartledger-bsv/tree/main/demos)** — interactive HTML & Node demos
|
|
1077
|
-
- **[Test Suite](https://github.com/codenlighten/smartledger-bsv/tree/main/test)** — covenant verification specs, CLI smoke, full mocha suite
|
|
218
|
+
## Verifying this library yourself
|
|
1078
219
|
|
|
1079
|
-
|
|
1080
|
-
|
|
220
|
+
Consensus behavior is pinned by vectors generated against the reference
|
|
221
|
+
implementation, not by this library's own opinion:
|
|
1081
222
|
|
|
1082
223
|
```bash
|
|
1083
|
-
#
|
|
1084
|
-
npm run
|
|
1085
|
-
npm run
|
|
1086
|
-
npm run demo:covenant # covenant builder example
|
|
224
|
+
npm test # unit + integration
|
|
225
|
+
npm run conformance # 452 cases against the reference corpus
|
|
226
|
+
npm run vectors:sv # SV consensus vector report
|
|
1087
227
|
```
|
|
1088
228
|
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
1. **Start** — [2-Minute Quick Start](#-2-minute-quick-start)
|
|
1092
|
-
2. **Practice** — [Examples Directory](https://github.com/codenlighten/smartledger-bsv/tree/main/examples)
|
|
1093
|
-
3. **Build** — [Custom Script Development](docs/advanced/CUSTOM_SCRIPT_DEVELOPMENT.md)
|
|
1094
|
-
4. **Advanced** — [Advanced Covenant Development](docs/advanced/ADVANCED_COVENANT_DEVELOPMENT.md)
|
|
1095
|
-
5. **Production** — [SECURITY.md](./SECURITY.md) + [v4.0.0 CHANGELOG](./CHANGELOG.md#400---2026-05-31) (mandatory read before mainnet credentials)
|
|
1096
|
-
|
|
1097
|
-
---
|
|
1098
|
-
|
|
1099
|
-
## 📄 **License**
|
|
229
|
+
## Contributing
|
|
1100
230
|
|
|
1101
|
-
|
|
231
|
+
Issues and pull requests: <https://github.com/codenlighten/smartledger-bsv>
|
|
1102
232
|
|
|
1103
|
-
|
|
233
|
+
Two rules matter more than the rest. Consensus changes need a conformance vector
|
|
234
|
+
in the same commit. Removing or breaking a public API needs a deprecation notice
|
|
235
|
+
that has shipped in an earlier minor — see [STABILITY.md](STABILITY.md).
|
|
1104
236
|
|
|
1105
|
-
|
|
1106
|
-
[github.com/codenlighten/smartledger-bsv](https://github.com/codenlighten/smartledger-bsv).
|
|
1107
|
-
For security vulnerabilities, follow the disclosure process in
|
|
1108
|
-
[SECURITY.md](./SECURITY.md) rather than opening a public issue.
|
|
237
|
+
## License
|
|
1109
238
|
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
- **GitHub**: [github.com/codenlighten/smartledger-bsv](https://github.com/codenlighten/smartledger-bsv)
|
|
1113
|
-
- **NPM (scoped)**: [@smartledger/bsv](https://www.npmjs.com/package/@smartledger/bsv)
|
|
1114
|
-
- **NPM (unscoped)**: [smartledger-bsv](https://www.npmjs.com/package/smartledger-bsv)
|
|
1115
|
-
- **Issues**: [GitHub Issues](https://github.com/codenlighten/smartledger-bsv/issues)
|
|
1116
|
-
- **Security**: [SECURITY.md](./SECURITY.md)
|
|
239
|
+
MIT
|
|
1117
240
|
|
|
1118
241
|
---
|
|
1119
242
|
|
|
1120
|
-
**SmartLedger-BSV
|
|
1121
|
-
|
|
1122
|
-
Built with ❤️ for the Bitcoin SV ecosystem • 16 Loading Options • Interpreter-Verified Covenants
|
|
243
|
+
**SmartLedger-BSV v9.1.0**
|