bsv-wallet 0.10.0 → 0.100.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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -486
  3. data/LICENSE +23 -80
  4. data/lib/bsv/network/chain_tracker.rb +80 -0
  5. data/lib/bsv/network/services.rb +311 -0
  6. data/lib/bsv/wallet/cli.rb +174 -0
  7. data/lib/bsv/wallet/daemon.rb +94 -0
  8. data/lib/bsv/wallet/engine.rb +1663 -0
  9. data/lib/bsv/wallet/errors.rb +44 -0
  10. data/lib/bsv/wallet/fetchable.rb +47 -0
  11. data/lib/bsv/wallet/interface/broadcast_queue.rb +55 -21
  12. data/lib/bsv/wallet/interface/proof_store.rb +35 -7
  13. data/lib/bsv/wallet/interface/store.rb +201 -66
  14. data/lib/bsv/wallet/interface/utxo_pool.rb +66 -12
  15. data/lib/bsv/wallet/interface.rb +4 -5
  16. data/lib/bsv/wallet/key_deriver.rb +492 -0
  17. data/lib/bsv/wallet/pushable.rb +45 -0
  18. data/lib/bsv/wallet/version.rb +1 -1
  19. data/lib/bsv/wallet.rb +32 -34
  20. metadata +16 -64
  21. data/lib/bsv/wallet/broadcast_queue/inline.rb +0 -202
  22. data/lib/bsv/wallet/broadcast_queue.rb +0 -28
  23. data/lib/bsv/wallet/client/brc100/authentication.rb +0 -28
  24. data/lib/bsv/wallet/client/brc100/crypto.rb +0 -314
  25. data/lib/bsv/wallet/client/brc100/identity.rb +0 -239
  26. data/lib/bsv/wallet/client/brc100/network.rb +0 -52
  27. data/lib/bsv/wallet/client/brc100/transaction.rb +0 -968
  28. data/lib/bsv/wallet/client/certificate_signature.rb +0 -212
  29. data/lib/bsv/wallet/client/change_generator.rb +0 -192
  30. data/lib/bsv/wallet/client/coin_selector.rb +0 -132
  31. data/lib/bsv/wallet/client/fee_estimator.rb +0 -140
  32. data/lib/bsv/wallet/client/fee_model.rb +0 -13
  33. data/lib/bsv/wallet/client/key_deriver.rb +0 -146
  34. data/lib/bsv/wallet/client/validators.rb +0 -206
  35. data/lib/bsv/wallet/client.rb +0 -181
  36. data/lib/bsv/wallet/errors/insufficient_funds_error.rb +0 -15
  37. data/lib/bsv/wallet/errors/invalid_hmac_error.rb +0 -11
  38. data/lib/bsv/wallet/errors/invalid_parameter_error.rb +0 -14
  39. data/lib/bsv/wallet/errors/invalid_signature_error.rb +0 -11
  40. data/lib/bsv/wallet/errors/pool_depleted_error.rb +0 -12
  41. data/lib/bsv/wallet/errors/unsupported_action_error.rb +0 -11
  42. data/lib/bsv/wallet/errors/wallet_error.rb +0 -14
  43. data/lib/bsv/wallet/interface/brc100.rb +0 -153
  44. data/lib/bsv/wallet/proof_store/local_proof_store.rb +0 -42
  45. data/lib/bsv/wallet/store/file.rb +0 -279
  46. data/lib/bsv/wallet/store/memory.rb +0 -382
  47. data/lib/bsv/wallet/store.rb +0 -11
  48. data/lib/bsv/wallet/substrates/http_wallet_json.rb +0 -268
  49. data/lib/bsv/wallet/substrates/http_wallet_wire.rb +0 -85
  50. data/lib/bsv/wallet/substrates/wallet_wire_transceiver.rb +0 -168
  51. data/lib/bsv/wallet/substrates.rb +0 -16
  52. data/lib/bsv/wallet/utxo_pool/local_pool.rb +0 -172
  53. data/lib/bsv/wallet/utxo_pool/replenishment_worker.rb +0 -183
  54. data/lib/bsv/wallet/wire/reader.rb +0 -238
  55. data/lib/bsv/wallet/wire/serializer.rb +0 -1993
  56. data/lib/bsv/wallet/wire/writer.rb +0 -214
  57. data/lib/bsv/wallet/wire.rb +0 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c9ebc3008fda1b4430f4e813abd4d9e4e87329a6845b247adab0d967b2c4fe5a
4
- data.tar.gz: b05c60a9f6d73e85c2bd0d179abe77e9d80018112336ce20b92782fc35b91b6e
3
+ metadata.gz: 72c932682aed184499474a9973fe1127e43ca0e8cdda64546af2bea1976b6b6c
4
+ data.tar.gz: e7165b0bd2df8c93649020a815bd0f154cb4bedcc19828aa8fd0b2449b082eab
5
5
  SHA512:
6
- metadata.gz: f1d6d32a26a674919fb659da57e6305b641dacbeb51eb0582af92f6e60396a73eed9ff373c48a90f95a4d5e1f86cefe9e10d69e71da515b8e08fc383fb8dc872
7
- data.tar.gz: 36e41e56f39d3b6ee945605a2ce831a2a220975f92458dfe081b627dc6ce9419f1a8fc69735fc6bec18cbb6e09bf5c55bf387b43ac09416c49d1af166785458c
6
+ metadata.gz: 52d5a757e7bf565d0c1189c9d2bf328e2773b8f27f45f1bcdce285e9051014a5948aa6625db80170b1542a924b75eb0cf0be4db983dc5364054fe1a4a85c5038
7
+ data.tar.gz: 72b403928501959aa29e843a3d2d500eab980b56b156bd44453c767458d915631c52e6d81802133cc2894349979dafefc9c3756b533cec05777f4b400bad9e78
data/CHANGELOG.md CHANGED
@@ -1,494 +1,26 @@
1
- # Changelog — bsv-wallet
1
+ # Changelog
2
2
 
3
- All notable changes to the `bsv-wallet` gem are documented here.
3
+ ## [0.100.0] - 2026-05-13
4
4
 
5
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
6
- and this gem adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
-
8
- ## 0.10.0 — 2026-04-21
9
-
10
- ### Added
11
- - BRC-100 abstract contract modules and `Client` with composition architecture
12
- - UTXO pool system: `UTXOPool` interface, `LocalPool` implementation, `ReplenishmentWorker`, and `utxo_pool` factory on Client
13
- - BRC-122 two-zone basket validation
14
- - `update_output_basket` on Store interface
15
-
16
- ### Changed
17
- - `ProtoWallet` and `WalletClient` deleted, replaced with `Client` using concern modules (`Transaction`, `Crypto`, `Identity`, `Network`, `Authentication`)
18
- - File paths renamed from `wallet_interface` to `wallet`
19
- - `Store` and `BroadcastQueue` collaborators namespaced under `Client`
20
- - Contracts moved under `Interface` namespace
21
- - Legacy `ChainProvider` classes removed
22
-
23
- ### Fixed
24
- - `internalize_payment` and `internalize_basket` now set `state: :spendable` explicitly on stored outputs
25
- - Derivation metadata now persisted in `store_tracked_outputs`
26
- - Cold start normalisation and eager validation fixes
27
- - SimpleCov coverage gate now requires `COVERAGE=true` explicitly
28
-
29
- ## 0.9.1 — 2026-04-16
30
-
31
- ### Changed
32
-
33
- - Raised `bsv-sdk` dependency floor to `>= 0.12.1` to pick up BEEF ancestry correctness fixes ([bsv-sdk#467](https://github.com/sgbett/bsv-ruby-sdk/issues/467), [bsv-sdk#468](https://github.com/sgbett/bsv-ruby-sdk/issues/468), HLR #466). Consumer impact: recently-received UTXOs that previously could not be re-broadcast now can — the wallet's `create_action` flow relies on `Transaction.from_beef` producing fully-wired ancestry, which the old SDK didn't do.
34
-
35
- ### Fixed
36
-
37
- - Removed redundant `store_transaction` call in `internalize_action` — `store_proofs_from_beef` already persists every transaction in the BEEF bundle, so the subject tx was being written twice. No behaviour change; minor cleanup. (#469)
38
-
39
- **Related:** [wallet-toolbox#149](https://github.com/bsv-blockchain/wallet-toolbox/issues/149) — same architectural gap reported upstream.
40
-
41
- ## 0.9.0 — 2026-04-16
42
-
43
- ### Changed — **Breaking**
44
-
45
- #### Action status taxonomy aligned with BRC-100 reference SDK (HLR #455)
46
-
47
- This release realigns the action status values with the wallet-toolbox reference
48
- implementation. The meaning of `'completed'` has changed — **consumers must
49
- update any code that checks for `'completed'` as the post-broadcast success
50
- state**.
51
-
52
- | Status | Old meaning | New meaning |
53
- |--------|-------------|-------------|
54
- | `'nosend'` | No change | Transaction built but not broadcast (`no_send: true`) |
55
- | `'sending'` | No change | Async queue accepted; worker has not yet attempted broadcast |
56
- | `'unproven'` | *(new)* | Broadcast succeeded; awaiting merkle proof |
57
- | `'completed'` | Broadcast succeeded | **Merkle proof received and stored** |
58
- | `'failed'` | No change | Broadcast rejected or transaction invalid |
59
-
60
- **Migration:**
61
-
62
- - Code querying `list_actions(status: 'completed')` will return fewer results
63
- until a proof-watcher is implemented (out of scope for this release). To find
64
- successfully-broadcast actions that have not yet received a proof, query
65
- `status: 'unproven'` instead.
66
- - `create_action` and `sign_action` now raise `BSV::Wallet::WalletError` when
67
- no broadcaster is configured and `options: { no_send: true }` is not set.
68
- Previously these calls succeeded silently. To resolve: pass
69
- `broadcaster: BSV::Network::ARC.default` to `WalletClient.new`, or pass
70
- `options: { no_send: true }` to `create_action` to build without
71
- broadcasting.
72
- - `internalize_action` now sets status to `'completed'` only when the supplied
73
- BEEF contains a merkle proof for the subject transaction. Plain BEEF (raw
74
- transaction, no BUMP) results in status `'unproven'`.
75
- - Wallets configured with a `SolidQueueAdapter` satisfy the broadcaster
76
- requirement if the adapter carries an embedded `broadcaster:` — the
77
- `WalletClient` itself does not need one.
78
-
79
- **Related upstream incidents:** x402-rack #148, x402-rack #158, x402-doom #196.
80
- **Tracking issue:** #455.
81
-
82
- ## 0.8.0 — 2026-04-15
5
+ First release of the Ruby BRC-100 wallet — ground-up implementation.
83
6
 
84
7
  ### Added
85
- - BRC-100 substrates: `HTTPWalletJSON` for JSON-over-HTTP, `HTTPWalletWire`
86
- for binary transport, and `WalletWireTransceiver` Interface adapter (#449–#451)
87
- - `WalletClient` accepts `substrate:` constructor param for remote wallet
88
- delegation all Interface methods delegate to the substrate when set (#452)
89
- - `list_actions` and `list_outputs` honour `include_labels`, `include_inputs`,
90
- and `include_outputs` flags (#448)
91
- - `acquire_certificate` uses `AuthFetch` for BRC-104 authenticated certificate
92
- issuance (#453)
93
-
94
- ### Fixed
95
- - `prove_certificate` now uses correct protocol ID (`'certificate field encryption'`)
96
- and key ID format (`"#{serial_number} #{field_name}"`) matching TS/Go SDKs
97
- previously incompatible cross-SDK (#424)
98
- - Code review findings addressed for substrates and include flags
8
+ - **BRC-100 Engine** — full transaction lifecycle: createAction, signAction, internalizeAction, abortAction, listActions, listOutputs, relinquishOutput
9
+ - **Key derivation** — BRC-42 ECDH key derivation, BRC-43 symmetric encryption, HMAC, ECDSA sign/verify
10
+ - **Certificates** BRC-52 identity certificates with field-level encryption and selective revelation
11
+ - **Auto-funded transactions** UTXO selection, fee estimation, change outputs with split-eagerness
12
+ - **SPV verification** — incoming BEEF validated via SDK `Transaction#verify` with chain tracker
13
+ - **BSV::Network::ChainTracker** write-through block header cache (DB + network services)
14
+ - **BSV::Network::Services** porcelain routing layer with fallback, rate limiting, response normalization
15
+ - **Pushable/Fetchable modules** — entity-driven network interaction for broadcast and proof lifecycle
16
+ - **Daemon** — background polling loop driving push!/fetch! on unresolved entities
17
+ - **UTXOPool** — sizing strategy with limp mode safety threshold
18
+ - **Porcelain CLI** bin/create, bin/receive, bin/import, bin/send_payment
19
+ - **wtxid/dtxid convention** binary wire-order internally, display hex at boundaries
99
20
 
100
- ### Changed
101
- - `BSV::WalletInterface` module removed — `VERSION` now lives in `BSV::Wallet::VERSION`
102
- where all other wallet constants already reside
103
-
104
- ## 0.7.0 — 2026-04-12
21
+ ## [0.1.0] - 2026-04-24
105
22
 
106
23
  ### Added
107
- - Pluggable `BroadcastQueue` interface module — duck-typed, follows the `StorageAdapter` pattern
108
- - `InlineQueue` synchronous default adapter — consolidates broadcast and no-broadcaster paths
109
- - `WalletClient` accepts `broadcast_queue:` constructor parameter (auto-creates `InlineQueue` when not provided)
110
- - `BroadcastQueue.status_for_error` shared helper for consistent broadcast error mapping
111
- - Integration specs for broadcast/rollback flows (20 specs)
112
- - MemoryStore production warning — logs to stderr when `RACK_ENV`/`RAILS_ENV` is `production` or `staging`
113
-
114
- ### Fixed
115
- - TOCTOU window on change outputs — stored as `:pending` directly, eliminating race with concurrent `auto_fund`
116
- - Broadcast promotion failure no longer deletes confirmed on-chain outputs — only broadcast failure triggers rollback
117
-
118
- ### Changed
119
- - `accept_delayed_broadcast: true` no longer logs "not yet implemented" warning — handled by the queue adapter
120
- - MemoryStore demoted to test/development only (production use triggers a suppressible warning)
121
-
122
- ## 0.6.0 — 2026-04-12
123
-
124
- ### Added
125
- - Broadcast-before-promote semantics for `create_action` — transactions are
126
- broadcast via a configurable `broadcaster:` before promoting state, with
127
- automatic rollback on failure to prevent phantom UTXOs (#369, #371)
128
- - `send_with` for batched broadcast of previously `no_send` transactions,
129
- with per-transaction rollback on failure (#373)
130
- - `accept_delayed_broadcast` option accepted as a stub (defaults to `false`;
131
- background broadcasting deferred to a follow-up) (#374)
132
- - `delete_action` and `update_action_status` on `StorageAdapter`, implemented
133
- in MemoryStore, FileStore, and PostgresStore (#370)
134
- - Broadcast results mapped to `ReviewActionResultStatus` (`success`,
135
- `doubleSpend`, `invalidTx`, `serviceError`) and returned in the result
136
- hash (#372)
137
-
138
- ### Fixed
139
- - EF version marker overhead corrected from 2 to 6 bytes in fee estimation
140
- - Fee estimation now includes EF overhead for ARC compatibility
141
- - `FeeEstimator` default raised from 1 sat/kB to 100 sat/kB
142
- - `internalize_payment` now stores outputs in the default basket
143
- - `derivation_type` comparison uses string comparison for JSON round-trip
144
- safety (#367)
145
-
146
- ### Changed
147
- - Extracted `DEFAULT_SATS_PER_KB` constant for fee estimation
148
- - Specs reorganised into per-gem directories (#363)
149
-
150
- ## 0.5.1 — 2026-04-11
151
-
152
- ### Fixed
153
-
154
- - **Auto-fund coin selection and change use default basket** (#344):
155
- coin selection and change generation now correctly target the `default`
156
- basket, matching TS SDK behaviour. Previously, auto-funded transactions
157
- could select UTXOs from or generate change into the wrong basket.
158
- - **Normalise protocol name in KeyDeriver** (#262, #263): `compute_invoice_number`
159
- now applies `.downcase.strip` to the protocol name before building the
160
- invoice string, matching TS and Go SDK behaviour. Mixed-case or
161
- whitespace-padded protocol names previously derived different keys.
162
-
163
- ### Changed
164
-
165
- - **SDK dependency floor raised** to `bsv-sdk >= 0.10.0` (from 0.9.0)
166
- to pick up the KeyDeriver normalisation fix in the SDK layer.
167
-
168
- ---
169
-
170
- ## 0.5.0 — 2026-04-11
171
-
172
- Native UTXO management, coin selection, and automatic change handling.
173
- The wallet can now fund transactions end-to-end without an external
174
- wallet server — `create_action` with outputs but no inputs triggers
175
- automatic UTXO selection, fee estimation, and change generation.
176
-
177
- ### Added
178
-
179
- - **UTXO management pipeline** (#264, #265–#272): complete transaction-
180
- funding pipeline with `CoinSelector` (exact-match, smallest-sufficient,
181
- largest-first strategies), `ChangeGenerator` (BRC-29 multi-output change
182
- with dust consolidation, randomised splits, pool-health-aware output
183
- caps), and `FeeEstimator` (size-based sats/kB with ceil rounding).
184
- - **`WhatsOnChainProvider`**: chain UTXO discovery via the WhatsOnChain API,
185
- implementing `sync_utxos` for on-chain balance loading.
186
- - **StorageAdapter extensions**: 6 new interface methods —
187
- `update_output_state`, `lock_utxos`, `find_spendable_outputs`,
188
- `release_stale_pending!`, `store_setting`, `find_setting`. All default
189
- to `NotImplementedError`; `MemoryStore` and `FileStore` implement them.
190
- - **Atomic UTXO locking**: `lock_utxos` checks and marks outputs as
191
- `:pending` within a single mutex hold, closing the TOCTOU race where two
192
- threads could select the same UTXO.
193
- - **Pending state management**: outputs transition through `:spendable` →
194
- `:pending` → `:spent`, with timestamps and caller references for stale
195
- lock recovery.
196
- - **Auto-funding in `create_action`**: when given outputs without inputs,
197
- the wallet selects UTXOs, estimates fees, generates change outputs, and
198
- locks inputs automatically.
199
- - **`set_wallet_change_params`**: configures target UTXO count and value
200
- for the change pool.
201
-
202
- ### Fixed
203
-
204
- - **Identity UTXO filter alignment**: `sync_utxos` stores
205
- `derivation_type: :identity` but auto-fund filtered on a field that was
206
- never set. Fixed the filter and added a signing branch that uses
207
- `root_key` directly for identity UTXOs.
208
- - **`tx_pos` bounds validation in `sync_utxos`**: untrusted WhatsOnChain
209
- API responses with negative or out-of-bounds `tx_pos` could exploit
210
- Ruby's negative array indexing or raise `NoMethodError` on nil. Now
211
- validates before use.
212
- - **Stale pending recovery rate-limited**: `release_stale_pending!` now
213
- skips if invoked within 30 seconds, preventing O(n) output scans on
214
- every `create_action` call.
215
- - **`no_send` change outputs stored as `:pending`**, matching the TS SDK
216
- where `noSend` outputs have `spendable: false`. Prevents them from
217
- being auto-selected by concurrent `create_action` calls.
218
- - **`abort_action` cleans up change outputs** created by the aborted
219
- transaction, matching TS SDK behaviour.
220
- - **Nil state guard**: `effective_state` handles `state: nil` (from NULL
221
- DB column) without raising `NoMethodError`.
222
- - **`change_params` wiring**: stored change params and pool size are now
223
- wired into `converge_change` so `set_wallet_change_params` actually
224
- affects auto-fund output count.
225
-
226
- ### Changed
227
-
228
- - **`FeeModel` consolidated into `FeeEstimator`**: `FeeModel` is now a
229
- backward-compatible alias for `FeeEstimator`, which is the canonical
230
- implementation with dust floor, varint handling, and extra-bytes
231
- support.
232
- - **`BRC29_PROTOCOL_ID` constant** replaces hardcoded protocol ID in
233
- `internalize_payment`.
234
-
235
- ## 0.4.0 — 2026-04-10
236
-
237
- ### Added
238
-
239
- - **Protocol-ID normalisation** (F8.7): `Validators.validate_protocol_id!` now
240
- strips and downcases the name before applying rules, so `' MyProtocol '` and
241
- `'myprotocol'` are treated identically and cannot silently fork to different
242
- key-derivation paths.
243
- - **Permission-rule constants** (F8.8): Reserved prefix/suffix strings are now
244
- named constants on `BSV::Wallet::Validators` (`RESERVED_PROTOCOL_PREFIXES`,
245
- `RESERVED_PROTOCOL_SUFFIX`, `RESERVED_BASKET_PREFIXES`, `RESERVED_BASKET_SUFFIX`,
246
- `RESERVED_BASKET_NAME`), making them discoverable and documentable.
247
- - **BEEF verification in `internalize_action`** (F8.14): The BEEF bundle is now
248
- verified via `Beef#verify` before any outputs are stored. If the bundle is
249
- structurally invalid, a `WalletError` is raised rather than storing unverified
250
- data. When the chain provider supports `valid_root_for_height?`, full SPV
251
- verification is performed.
252
- - **Depth cap and cycle detection in `wire_source_tx_ancestors`** (F8.18):
253
- Recursion is now bounded by `WalletClient::ANCESTOR_DEPTH_CAP` (64 levels)
254
- and a visited-txid `Set`, preventing stack overflow on deep or cyclic
255
- transaction ancestry chains.
256
-
257
- ### Changed
258
-
259
- - **`ProtoWallet#create_signature` default counterparty** (P305.1): The default
260
- value for `counterparty` has changed from `'self'` to `'anyone'`, matching the
261
- behaviour of `ts-sdk`'s `ProtoWallet.createSignature`. Callers that rely on
262
- the `'self'` derivation path when omitting `counterparty:` must now pass
263
- `counterparty: 'self'` explicitly.
264
-
265
- ### Migration notes
266
-
267
- **P305.1 — `create_signature` counterparty default change (breaking)**
268
-
269
- Previously, calling `wallet.create_signature({ protocol_id: ..., key_id: ...,
270
- data: ... })` without a `counterparty:` key would derive using `'self'`. It now
271
- derives using `'anyone'`. This changes the resulting private key and therefore
272
- the signature. If your application omits `counterparty:`, add
273
- `counterparty: 'self'` to preserve the old behaviour.
274
-
275
- **F8.14 — BEEF verification now mandatory in `internalize_action`**
276
-
277
- Calls to `internalize_action` that previously succeeded with a malformed or
278
- unverifiable BEEF will now raise `BSV::Wallet::WalletError`. In practice this
279
- only affects callers passing synthetic or hand-crafted BEEF bytes; legitimate
280
- BEEF produced by `create_action` or broadcast round-trips will continue to work.
281
-
282
- ### Added
283
-
284
- - **Shared conformance suite** for `StorageAdapter`
285
- implementations at `spec/support/shared_examples_for_storage_adapter.rb`.
286
- `MemoryStore` and `FileStore` now both drive their behavioural
287
- tests through `it_behaves_like 'a storage adapter'`, and the
288
- extraction backfilled previously-missing coverage (certificate
289
- `:attributes` filter, `count_certificates`, proof and transaction
290
- round-trip, pagination ordering).
291
-
292
- ## 0.3.4 — 2026-04-08
293
-
294
- Paired security patch release. Three P0 findings from the
295
- [2026-04-08 cross-SDK compliance review](.architecture/reviews/20260408-cross-sdk-compliance-review.md)
296
- plus follow-up hardening from the PR review pass. Must be installed
297
- together — the `bsv-wallet` gemspec now pins its `bsv-sdk` dependency
298
- to `>= 0.8.2, < 1.0` to enforce the paired upgrade and prevent a stale
299
- pair where one gem has its fixes and the other doesn't.
300
-
301
- Two GitHub Security Advisories accompany this release (draft until
302
- CVE IDs return from MITRE):
303
-
304
-
305
- ### Security
306
-
307
- - **`acquire_certificate` now verifies certifier signatures** before
308
- persisting (BRC-52). Both the `'direct'` and `'issuance'` acquisition
309
- paths previously wrote user-supplied `signature:` values to storage
310
- without any verification — a caller could forge a certificate that
311
- `list_certificates` / `prove_certificate` would later treat as
312
- authentic. This was a credential forgery primitive masquerading as
313
- an API finding. The new `BSV::Wallet::CertificateSignature` module
314
- builds the canonical BRC-52 preimage (matching the TS reference
315
- `Certificate#toBinary(false)` byte-for-byte) and delegates to
316
- `ProtoWallet#verify_signature`. Invalid certificates raise
317
- `BSV::Wallet::CertificateSignature::InvalidError` and are not
318
- persisted. Closes F8.15 (and the verification aspect of F8.16).
319
-
320
-
321
-
322
- ### Changed
323
-
324
- - **`bsv-wallet.gemspec` bsv-sdk dependency pinned** to
325
- `>= 0.8.2, < 1.0`. The previous `~> 0.4` constraint was stale (wallet
326
- hasn't been tested against bsv-sdk 0.4.x in months) and would have
327
- let a user install `bsv-wallet 0.3.4` against an old `bsv-sdk` that
328
- was missing F1.3 and F5.13. Technically breaking — any consumer
329
- pinned to `bsv-sdk < 0.8.2` must upgrade — but un-breaking in
330
- practice: it forces users to the known-good pair rather than a
331
- silently-broken combination.
332
-
333
- ### Internal
334
-
335
- - `lib/bsv/wallet_interface/**/*` added to the
336
- `Metrics/ModuleLength` exclusion list (was previously only excluded
337
- from `Metrics/ClassLength`). The new `CertificateSignature` module
338
- triggered the discrepancy.
339
- - Review-feedback hardening bundled into the same PR to
340
- keep the security-patch window small: case-insensitive ARC failure
341
- matching, `Base64.strict_decode64` on BRC-52 preimage fields,
342
- `EncodingError` rescue in `CertificateSignature.verify!`, rejection
343
- of mixed string / symbol duplicate field names, malformed 2xx
344
- rejection in ARC, and even-length guard on hex signatures.
345
-
346
- ### Migration notes
347
-
348
- - **Existing `bsv-wallet` users** pinned to `bsv-sdk ~> 0.4` will need
349
- to relax their constraint or upgrade. Anything installed before
350
- `bsv-wallet 0.3.4` is vulnerable to the F8.15 certificate forgery
351
- primitive.
352
- - **Callers passing negative integers to `VarInt.encode`** (unlikely —
353
- the docstring already disallowed it) will now get an `ArgumentError`
354
- instead of silent corruption. Fix: pass non-negative values.
355
- - **Callers relying on ARC broadcaster silently succeeding for INVALID
356
- / MALFORMED / MINED_IN_STALE_BLOCK / ORPHAN responses** will now see
357
- `BroadcastError` raised. Fix: handle the error — the previous
358
- behaviour was objectively wrong and any downstream logic that
359
- tolerated it was silently corrupt.
360
- - **Callers of `acquire_certificate` with a fake or untrusted
361
- `signature:` field** will now see
362
- `BSV::Wallet::CertificateSignature::InvalidError`. Fix: ensure the
363
- certificate has been properly signed by the declared certifier.
364
-
365
- ### Test suite
366
-
367
- - 3112 examples, 0 failures (up from 3080 on 0.8.1)
368
- - 16 new regression tests for F1.3, F5.13, and F8.15
369
- - 16 further regression tests for the review-feedback hardening
370
- - Ruby 2.7 — 3.4 matrix green
371
- - CodeQL clean; RuboCop clean across 266 files
372
-
373
- ## 0.3.3 — 2026-04-06
374
-
375
- ### Fixed
376
-
377
- - `finalize_action` now stores the spending transaction so subsequent
378
- `internalize_action` / proof resolution flows can find it. Previously the
379
- wallet remembered the inputs and outputs but not the finalised tx itself.
380
-
381
- ## 0.3.2 — 2026-04-06
382
-
383
- ### Fixed
384
-
385
- - `internalize_action` now stores **all** transactions from the
386
- incoming BEEF, not just the proven ones. Unproven ancestors are needed for
387
- later BEEF reconstruction in `create_action` → `to_beef`.
388
-
389
- ## 0.3.1 — 2026-04-06
390
-
391
- ### Fixed
392
-
393
- - `internalize_action` now stores the subject transaction hex (not
394
- just its proof and outputs), so the wallet can rebuild BEEF for spends of
395
- the inbound outputs without re-fetching the tx.
396
-
397
- ## 0.3.0 — 2026-04-06
398
-
399
- ### Added
400
-
401
- - **Pluggable proof store** for merkle proof persistence. The wallet
402
- is now a lightweight SPV node: `internalize_action` extracts and stores
403
- merkle proofs from incoming BEEF; `create_action` reattaches them to
404
- produce valid BEEF with BUMPs for ARC broadcast.
405
- - `ProofStore` interface with `store_proof` / `resolve_proof`.
406
- - `LocalProofStore` default implementation using `StorageAdapter`.
407
- - `WalletClient` accepts injectable `proof_store:` parameter.
408
- - Transaction caching (`store_transaction` / `find_transaction`) for
409
- ancestry reconstruction.
410
- - `StorageAdapter` gains `store_proof`, `find_proof`,
411
- `store_transaction`, `find_transaction` methods, implemented in both
412
- `MemoryStore` and `FileStore`.
413
-
414
- ### Fixed
415
-
416
- - `wire_source_from_storage` resolves merkle proofs via proof store
417
- so `to_beef` produces valid BEEF that ARC accepts. Previously, BEEF
418
- contained source transactions without proofs, causing ARC 463/468
419
- rejections.
420
-
421
- ## 0.2.2 — 2026-04-06
422
-
423
- ### Fixed
424
-
425
- - `to_beef` now includes source transactions in the BEEF output, not
426
- just the subject transaction. Without ancestors, ARC could not validate the
427
- spend graph.
428
-
429
- ## 0.2.1 — 2026-04-06
430
-
431
- ### Added
432
-
433
- - `WalletClient#create_action` now accepts `UnlockingScriptTemplate`
434
- objects (e.g. `P2PKH`) as input unlocking scripts, enabling template-based
435
- signing without BEEF.
436
- - `wire_source_from_storage` fallback populates `source_satoshis`
437
- and `source_locking_script` from wallet storage when BEEF is absent or
438
- incomplete, enabling BIP-143 sighash computation for wallet-tracked
439
- outputs.
440
- - `finalize_action` resolves template inputs via `sign_all` before
441
- serialisation.
442
- - `MemoryStore#filter_outputs` supports outpoint filtering for
443
- efficient single-output lookups.
444
-
445
- The sdk gem was re-released alongside this wallet change with no
446
- behavioural changes of its own.
447
-
448
- ## 0.2.0 — 2026-04-01
449
-
450
- ### Added
451
-
452
- #### Primitives
453
-
454
-
455
- #### Transaction
456
-
457
-
458
- #### Wallet
459
-
460
- - **FileStore** — JSON file-backed persistent storage, now the
461
- default for `WalletClient`. Data survives process restarts. `MemoryStore`
462
- becomes explicit opt-in for tests.
463
- - **File permissions** — directory created with 0700, files with
464
- 0600. Warns via Logger on startup if permissions are too open.
465
-
466
- ## 0.1.2 — 2026-03-30
467
-
468
- ### Added
469
-
470
- #### Script
471
-
472
-
473
- #### Transaction
474
-
475
-
476
- #### Wallet
477
-
478
- - **BRC-31 Auth/Peer** — mutual authentication with nonce-based
479
- challenges, ECDSA signatures, and session management.
480
- - **BRC-100 wire protocol** — binary ABI serialisation for all 28
481
- BRC-100 methods (call codes 1-28, VarInt encoding).
482
- - **Certificate issuance** — `acquire_certificate` with
483
- `'issuance'` protocol (POST to certifier URL).
484
-
485
- ### Fixed
486
-
487
- - Subject and certifier pinned in certificate issuance response
488
- (not overridable by remote certifier).
489
- - Wire reader negative `privileged_reason` length crash.
490
24
 
491
- This was the first formal `bsv-wallet` gem release tag. Wallet code that
492
- landed in master before this date (notably the BRC-100 identity certificate
493
- methods and the BRC-100 blockchain-data / authentication methods committed
494
- during the sdk-0.3.1 window) is part of this gem's initial released state.
25
+ - BRC-100 wallet interface module (`BSV::Wallet`)
26
+ - Gem scaffolding
data/LICENSE CHANGED
@@ -1,86 +1,29 @@
1
- Open BSV License Version 5 – granted by BSV Association, Grafenauweg 6, 6300
2
- Zug, Switzerland (CHE-427.008.338) ("Licensor"), to you as a user (henceforth
3
- "You", "User" or "Licensee").
1
+ Open BSV License
4
2
 
5
- For the purposes of this license, the definitions below have the following
6
- meanings:
3
+ Copyright (c) 2026 Simon Bettison
7
4
 
8
- "Bitcoin Protocol" means the protocol implementation, cryptographic rules,
9
- network protocols, and consensus mechanisms in the Bitcoin White Paper as
10
- described here https://protocol.bsvblockchain.org.
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
11
 
12
- "Bitcoin White Paper" means the paper entitled 'Bitcoin: A Peer-to-Peer
13
- Electronic Cash System' published by 'Satoshi Nakamoto' in October 2008.
12
+ 1. The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
14
 
15
- "BSV Blockchains" means:
16
- (a) the Bitcoin blockchain containing block height #556767 with the hash
17
- "000000000000000001d956714215d96ffc00e0afda4cd0a96c96f8d802b1662b" and
18
- that contains the longest honest persistent chain of blocks which has been
19
- produced in a manner which is consistent with the rules set forth in the
20
- Network Access Rules; and
21
- (b) the test blockchains that contain the longest honest persistent chains of
22
- blocks which has been produced in a manner which is consistent with the
23
- rules set forth in the Network Access Rules.
24
-
25
- "Network Access Rules" or "Rules" means the set of rules regulating the
26
- relationship between BSV Association and the nodes on BSV based on the Bitcoin
27
- Protocol rules and those set out in the Bitcoin White Paper, and available here
28
- https://bsvblockchain.org/network-access-rules.
29
-
30
- "Software" means the software the subject of this licence, including any/all
31
- intellectual property rights therein and associated documentation files.
32
-
33
- BSV Association grants permission, free of charge and on a non-exclusive and
34
- revocable basis, to any person obtaining a copy of the Software to deal in the
35
- Software without restriction, including without limitation the rights to use,
36
- copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
37
- Software, and to permit persons to whom the Software is furnished to do so,
38
- subject to and conditioned upon the following conditions:
39
-
40
- 1 - The text "© BSV Association," and this license shall be included in all
41
- copies or substantial portions of the Software.
42
- 2 - The Software, and any software that is derived from the Software or parts
43
- thereof, must only be used on the BSV Blockchains.
44
-
45
- For the avoidance of doubt, this license is granted subject to and conditioned
46
- upon your compliance with these terms only. In the event of non-compliance, the
47
- license shall extinguish and you can be enjoined from violating BSV's
48
- intellectual property rights (incl. damages and similar related claims).
49
-
50
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
51
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES REGARDING ENTITLEMENT,
52
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
53
- EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS THEREOF BE LIABLE FOR ANY CLAIM,
54
- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
55
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
56
- DEALINGS IN THE SOFTWARE.
57
-
58
-
59
- Version 0.1.1 of the Bitcoin SV software, and prior versions of software upon
60
- which it was based, were licensed under the MIT License, which is included below.
61
-
62
- The MIT License (MIT)
63
-
64
- Copyright (c) 2009-2010 Satoshi Nakamoto
65
- Copyright (c) 2009-2015 Bitcoin Developers
66
- Copyright (c) 2009-2017 The Bitcoin Core developers
67
- Copyright (c) 2017 The Bitcoin ABC developers
68
- Copyright (c) 2018 Bitcoin Association for BSV
69
- Copyright (c) 2023 BSV Association
70
-
71
- Permission is hereby granted, free of charge, to any person obtaining a copy of
72
- this software and associated documentation files (the "Software"), to deal in
73
- the Software without restriction, including without limitation the rights to
74
- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
75
- the Software, and to permit persons to whom the Software is furnished to do so,
76
- subject to the following conditions:
77
-
78
- The above copyright notice and this permission notice shall be included in all
79
- copies or substantial portions of the Software.
15
+ 2. The Software, and any software that is derived from the Software or parts
16
+ thereof, can only be used on the Bitcoin SV blockchains. The Bitcoin SV
17
+ blockchains are defined, for purposes of this license, as the Bitcoin
18
+ blockchain containing block combinator
19
+ 000000000000000001d956714215d96ffc00e0afda4cd0a96c96f8d802b1662b and the
20
+ test combinator
21
+ 00000000a6e140e27e4eb65e3cb4e4e07b1a0e3964b396c97a4b36e4ac06eb54.
80
22
 
81
23
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
82
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
83
- FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
84
- COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
85
- IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
86
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29
+ THE SOFTWARE.