bsv-sdk 0.8.2 → 0.9.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.
data/CHANGELOG.md DELETED
@@ -1,717 +0,0 @@
1
- # Changelog
2
-
3
- All notable changes to this project will be documented in this file.
4
-
5
- This repository ships two gems with independent versioning:
6
-
7
- - **`bsv-sdk`** — the declarative SDK (primitives, script, transaction, etc.)
8
- - **`bsv-wallet`** — the BRC-100 wallet interface gem (depends on `bsv-sdk`)
9
-
10
- The two gems may release on different schedules. Section headers identify
11
- which gem(s) released, e.g.:
12
-
13
- - `## sdk-0.7.0 / wallet-0.3.0 — 2026-04-06` — both gems released together
14
- - `## sdk-0.6.1 — 2026-04-05` — sdk-only release
15
- - `## wallet-0.3.3 — 2026-04-06` — wallet-only release
16
-
17
- Every bullet is prefixed with `[sdk]` or `[wallet]` to disambiguate which gem
18
- the change belongs to, regardless of which header it sits under.
19
-
20
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
21
- and each gem adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
22
- independently.
23
-
24
- ## sdk-0.8.2 / wallet-0.3.4 — 2026-04-08
25
-
26
- Paired security patch release. Three P0 findings from the
27
- [2026-04-08 cross-SDK compliance review](.architecture/reviews/20260408-cross-sdk-compliance-review.md)
28
- plus follow-up hardening from the PR review pass. Must be installed
29
- together — the `bsv-wallet` gemspec now pins its `bsv-sdk` dependency
30
- to `>= 0.8.2, < 1.0` to enforce the paired upgrade and prevent a stale
31
- pair where one gem has its fixes and the other doesn't.
32
-
33
- Two GitHub Security Advisories accompany this release (draft until
34
- CVE IDs return from MITRE):
35
-
36
- - [GHSA-hc36-c89j-5f4j](.security/advisories/2026-0001-acquire-certificate-signature-bypass.md) — F8.15 / F8.16 partial — `acquire_certificate` persists unverified certifier signatures (CWE-347, CVSS 8.1 HIGH)
37
- - [GHSA-9hfr-gw99-8rhx](.security/advisories/2026-0002-arc-broadcaster-failure-statuses.md) — F5.13 — ARC broadcaster treats failure statuses as success (CWE-754, CVSS 7.5 HIGH)
38
-
39
- ### Security
40
-
41
- - [wallet] **`acquire_certificate` now verifies certifier signatures** before
42
- persisting (BRC-52). Both the `'direct'` and `'issuance'` acquisition
43
- paths previously wrote user-supplied `signature:` values to storage
44
- without any verification — a caller could forge a certificate that
45
- `list_certificates` / `prove_certificate` would later treat as
46
- authentic. This was a credential forgery primitive masquerading as
47
- an API finding. The new `BSV::Wallet::CertificateSignature` module
48
- builds the canonical BRC-52 preimage (matching the TS reference
49
- `Certificate#toBinary(false)` byte-for-byte) and delegates to
50
- `ProtoWallet#verify_signature`. Invalid certificates raise
51
- `BSV::Wallet::CertificateSignature::InvalidError` and are not
52
- persisted. Closes F8.15 (and the verification aspect of F8.16).
53
-
54
- - [sdk] **`VarInt.encode` now rejects negative integers** and values
55
- above 2^64 − 1. Previously `VarInt.encode(-1)` fell into the single-
56
- byte branch and emitted `0xFF` (the marker for a 9-byte encoding),
57
- silently corrupting the transaction stream with no exception raised.
58
- The docstring already required a non-negative integer; the
59
- implementation did not enforce it. Closes F1.3.
60
-
61
- - [sdk] **ARC broadcaster recognises the full failure status set**. The
62
- previous `REJECTED_STATUSES` contained only `REJECTED` and
63
- `DOUBLE_SPEND_ATTEMPTED`; responses with txStatus `INVALID`,
64
- `MALFORMED`, `MINED_IN_STALE_BLOCK`, or any `ORPHAN`-containing
65
- `txStatus` / `extraInfo` were silently treated as successful
66
- broadcasts. Callers relying on `broadcast()` to signal failure would
67
- trust transactions that were never actually accepted by the network.
68
- The new failure set matches the TypeScript reference broadcaster
69
- exactly, and case-insensitive matching defends against ARC's
70
- documented history of emitting values outside its own OpenAPI enum
71
- (TS issue #105). Malformed 2xx responses without a `txid` field
72
- also raise, closing the same silent-success class for shape
73
- corruption. Closes F5.13.
74
-
75
- ### Changed
76
-
77
- - [sdk] **ARC broadcaster HTTP wire format** brought into line with the
78
- TypeScript reference:
79
- - Content-Type is now `application/json` (was `application/octet-stream`)
80
- - Body is `{"rawTx": hex}` — Extended Format (BRC-30) hex when every
81
- input has `source_satoshis` / `source_locking_script` populated
82
- (so ARC can validate sighashes without fetching parents), falling
83
- back to plain raw-tx hex otherwise
84
- - New `XDeployment-ID` header (default: `bsv-ruby-sdk-<random hex>`,
85
- overridable via `deployment_id:` constructor kwarg)
86
- - New optional `X-CallbackUrl` and `X-CallbackToken` constructor
87
- kwargs for ARC status callbacks
88
-
89
- - [wallet] **`bsv-wallet.gemspec` bsv-sdk dependency pinned** to
90
- `>= 0.8.2, < 1.0`. The previous `~> 0.4` constraint was stale (wallet
91
- hasn't been tested against bsv-sdk 0.4.x in months) and would have
92
- let a user install `bsv-wallet 0.3.4` against an old `bsv-sdk` that
93
- was missing F1.3 and F5.13. Technically breaking — any consumer
94
- pinned to `bsv-sdk < 0.8.2` must upgrade — but un-breaking in
95
- practice: it forces users to the known-good pair rather than a
96
- silently-broken combination.
97
-
98
- ### Internal
99
-
100
- - [sdk] `lib/bsv/network/**/*` added to `Metrics/ClassLength` and
101
- `Metrics/ParameterLists` RuboCop exclusion lists to match the
102
- existing treatment of `lib/bsv/wallet_interface/**/*`. ARC is
103
- HTTP-client boilerplate in the same shape.
104
- - [wallet] `lib/bsv/wallet_interface/**/*` added to the
105
- `Metrics/ModuleLength` exclusion list (was previously only excluded
106
- from `Metrics/ClassLength`). The new `CertificateSignature` module
107
- triggered the discrepancy.
108
- - [sdk, wallet] Review-feedback hardening bundled into the same PR to
109
- keep the security-patch window small: case-insensitive ARC failure
110
- matching, `Base64.strict_decode64` on BRC-52 preimage fields,
111
- `EncodingError` rescue in `CertificateSignature.verify!`, rejection
112
- of mixed string / symbol duplicate field names, malformed 2xx
113
- rejection in ARC, and even-length guard on hex signatures.
114
-
115
- ### Migration notes
116
-
117
- - **Existing `bsv-wallet` users** pinned to `bsv-sdk ~> 0.4` will need
118
- to relax their constraint or upgrade. Anything installed before
119
- `bsv-wallet 0.3.4` is vulnerable to the F8.15 certificate forgery
120
- primitive.
121
- - **Callers passing negative integers to `VarInt.encode`** (unlikely —
122
- the docstring already disallowed it) will now get an `ArgumentError`
123
- instead of silent corruption. Fix: pass non-negative values.
124
- - **Callers relying on ARC broadcaster silently succeeding for INVALID
125
- / MALFORMED / MINED_IN_STALE_BLOCK / ORPHAN responses** will now see
126
- `BroadcastError` raised. Fix: handle the error — the previous
127
- behaviour was objectively wrong and any downstream logic that
128
- tolerated it was silently corrupt.
129
- - **Callers of `acquire_certificate` with a fake or untrusted
130
- `signature:` field** will now see
131
- `BSV::Wallet::CertificateSignature::InvalidError`. Fix: ensure the
132
- certificate has been properly signed by the declared certifier.
133
-
134
- ### Test suite
135
-
136
- - 3112 examples, 0 failures (up from 3080 on 0.8.1)
137
- - 16 new regression tests for F1.3, F5.13, and F8.15
138
- - 16 further regression tests for the review-feedback hardening
139
- - Ruby 2.7 — 3.4 matrix green
140
- - CodeQL clean; RuboCop clean across 266 files
141
-
142
- ## sdk-0.8.1 — 2026-04-08
143
-
144
- ### Fixed
145
-
146
- - [sdk] **`Transaction#to_beef` strips phantom `txid: true` leaves** —
147
- when a proof loaded from a shared `LocalProofStore` carries txid flags
148
- for transactions that are not part of the bundle being constructed,
149
- `to_beef` now rebuilds each per-block BUMP from only the bundle's own
150
- txids instead of propagating the phantoms into the serialised output.
151
- ARC previously rejected such BEEFs with misleading parser errors,
152
- blocking any wallet workflow that received a BEEF via
153
- `internalize_action` and then spent the internalised UTXOs.
154
- Closes #302.
155
-
156
- ### Added
157
-
158
- - [sdk] **`MerklePath#extract(txid_hashes)`** — returns a new trimmed
159
- compound path covering only the requested txids, reconstructing the
160
- minimum set of sibling hashes at each tree level. Raises
161
- `ArgumentError` on empty input, unknown txid, or root mismatch.
162
- Ported from the TypeScript SDK. Used internally by
163
- `Transaction#to_beef` and available for direct use.
164
- - [sdk] **`MerklePath#trim`** — removes internal nodes not required by
165
- level-zero txid leaves. Called implicitly by `#combine` and `#extract`
166
- and rarely needs to be invoked directly. Ported from the TypeScript
167
- SDK.
168
- - [sdk] **`MerklePath#initialize_copy`** — `.dup` now produces a new
169
- MerklePath whose outer and level arrays are independent of the
170
- source, so the copy can be freely mutated via `#combine`, `#trim`,
171
- or `#extract` without affecting the original. `PathElement`s
172
- remain immutable and are shared between source and copy.
173
-
174
- ### Changed
175
-
176
- - [sdk] **`MerklePath#combine`** now calls `#trim` at the end so merged
177
- paths stay minimal across repeated merges, matching the TypeScript
178
- SDK. Combined paths are strictly smaller than before — external
179
- callers that inspected `mp.path` after `#combine` may see fewer
180
- nodes, though every txid leaf's merkle proof is preserved.
181
- - [sdk] **`MerklePath#combine`** also preserves `txid: true` flags when
182
- the incoming leaf is flagged and the existing leaf at the same offset
183
- isn't, so merging an ancestor's single-leaf proof into a compound
184
- that already contains the same offset as a sibling no longer loses
185
- the txid flag.
186
- - [sdk] **`Transaction#to_beef`** now raises `ArgumentError` if an
187
- ancestor's merkle path doesn't actually contain that transaction's
188
- txid, or if the rebuilt BUMP's root doesn't match the source root.
189
- Previously such corrupt proof data would silently emit a broken BEEF.
190
- Callers relying on `to_beef` not raising on valid data are
191
- unaffected; the new exception only triggers on corrupt proof stores.
192
-
193
- ### Internal
194
-
195
- - [sdk] **`Beef#merge_transaction`** indirectly benefits from the
196
- tighter `#combine` + `#trim` behaviour: compound BUMPs no longer
197
- accumulate dead sibling hashes across repeated merges.
198
- - [sdk] On the real-world `#302` regression fixture, the cleaned BUMP
199
- shrinks from 2476 B to 1300 B (47% reduction) as a side effect of
200
- `#extract` removing intermediate siblings that are no longer needed
201
- once phantom leaves are gone.
202
-
203
- ## sdk-0.8.0 — 2026-04-08
204
-
205
- ### Added
206
-
207
- - [sdk] **`MerklePath.from_tsc`** — convert WhatsOnChain TSC merkle proofs
208
- (the flat leaf-to-root sibling list returned by
209
- `/tx/{txid}/proof/tsc`) into BRC-74 BUMP format. Verified end-to-end
210
- against a real mainnet vector (block 612251). Closes #280.
211
- - [sdk] **`Beef#version=`** writer — promoted from internal
212
- `instance_variable_set` to a proper accessor.
213
-
214
- ### Changed
215
-
216
- - [sdk] **`Beef#to_binary` rewrite** — serialises BUMPs from the canonical
217
- `@bumps` array and uses `beef_tx.bump_index` as the on-wire reference,
218
- instead of walking each transaction's `merkle_path` via object identity.
219
- Fixes duplicate-BUMP serialisation for same-block ancestors that
220
- previously caused ARC `468 BEEF invalid` rejections. Matches the TS and
221
- Go reference SDKs. Closes #288.
222
- - [sdk] **`Beef#to_hex`** preserves the bundle's `@version` so a BEEF
223
- parsed from V2 round-trips to V2 hex (and V1 to V1) instead of always
224
- silently downgrading to V1. The original docstring already claimed
225
- "V2 hex string" — this fix matches the original intent. Closes #292.
226
- - [sdk] **`Beef#initialize`** default `version:` parameter changed from
227
- `BEEF_V2` to `BEEF_V1` to match `to_binary`'s default. Every existing
228
- `Beef.new + to_hex` caller continues to emit V1 (preserving every
229
- existing observable behaviour). Closes #292.
230
- - [sdk] **`bsv-sdk` gem packaging** — explicit module list in
231
- `bsv-sdk.gemspec` excludes `bsv-attest` and `bsv-wallet` code. Reduces
232
- `bsv-sdk` from 144 files to 98 (24% smaller); no overlap with the
233
- sibling gems except `LICENSE`.
234
- - [sdk] `Transaction#to_beef` docstring corrected from "BEEF V2 binary
235
- bundle" to "BEEF V1 binary bundle (BRC-62)" to match what the method
236
- actually emits.
237
-
238
- ### Fixed
239
-
240
- - [sdk] **`Beef#to_binary`** raises `ArgumentError` upfront when V1
241
- (BRC-62) is requested for a bundle containing `FORMAT_TXID_ONLY`
242
- entries, instead of crashing deep inside `write_v1_tx` with
243
- `NoMethodError`. V2 (BRC-96) supports TXID-only and is unaffected. The
244
- error message points the caller at `version: BEEF_V2`. Closes #290.
245
- - [sdk] **`Beef#merge`** raises `ArgumentError` on inconsistent
246
- `bump_index` from the source bundle (when the source has a transaction
247
- pointing at a `bump_index` that doesn't exist in the source's
248
- `@bumps`), instead of silently propagating a stale index that could
249
- attach the wrong merkle path to a transaction in the merged bundle.
250
- Closes #291.
251
- - [sdk] **`Beef::BeefTx#initialize`** validates that
252
- `FORMAT_RAW_TX_AND_BUMP` requires a non-nil `bump_index`, failing fast
253
- in the constructor instead of crashing later in `VarInt.encode(nil)`.
254
- - [sdk] **`Beef#merge_raw_tx`** bounds-checks the `bump_index` parameter
255
- and raises `ArgumentError` if out of range, instead of silently writing
256
- an invalid index that downstream parsers would misinterpret.
257
-
258
- ### Internal
259
-
260
- - [sdk] CI is now green: 73 pre-existing RuboCop offenses across
261
- `spec/conformance/openssl_shim_compliance/` resolved. Closes #293.
262
- - [sdk] OpenSSL EC shim conformance suite is now skipped on Ruby 2.7,
263
- where stock `OpenSSL::PKey::EC::Point#add` is unavailable. The shim
264
- itself still has direct unit-test coverage on every supported Ruby.
265
-
266
- ## wallet-0.3.3 — 2026-04-06
267
-
268
- ### Fixed
269
-
270
- - [wallet] `finalize_action` now stores the spending transaction so subsequent
271
- `internalize_action` / proof resolution flows can find it. Previously the
272
- wallet remembered the inputs and outputs but not the finalised tx itself.
273
-
274
- ## wallet-0.3.2 — 2026-04-06
275
-
276
- ### Fixed
277
-
278
- - [wallet] `internalize_action` now stores **all** transactions from the
279
- incoming BEEF, not just the proven ones. Unproven ancestors are needed for
280
- later BEEF reconstruction in `create_action` → `to_beef`.
281
-
282
- ## wallet-0.3.1 — 2026-04-06
283
-
284
- ### Fixed
285
-
286
- - [wallet] `internalize_action` now stores the subject transaction hex (not
287
- just its proof and outputs), so the wallet can rebuild BEEF for spends of
288
- the inbound outputs without re-fetching the tx.
289
-
290
- ## sdk-0.7.0 / wallet-0.3.0 — 2026-04-06
291
-
292
- ### Added
293
-
294
- - [wallet] **Pluggable proof store** for merkle proof persistence. The wallet
295
- is now a lightweight SPV node: `internalize_action` extracts and stores
296
- merkle proofs from incoming BEEF; `create_action` reattaches them to
297
- produce valid BEEF with BUMPs for ARC broadcast.
298
- - `ProofStore` interface with `store_proof` / `resolve_proof`.
299
- - `LocalProofStore` default implementation using `StorageAdapter`.
300
- - `WalletClient` accepts injectable `proof_store:` parameter.
301
- - Transaction caching (`store_transaction` / `find_transaction`) for
302
- ancestry reconstruction.
303
- - [wallet] `StorageAdapter` gains `store_proof`, `find_proof`,
304
- `store_transaction`, `find_transaction` methods, implemented in both
305
- `MemoryStore` and `FileStore`.
306
-
307
- ### Changed
308
-
309
- - [sdk] `Beef#to_binary` now defaults to BEEF V1 (BRC-62) format, matching
310
- the TS reference SDK's `Transaction#toBEEF()`. ARC's parser does not
311
- support V2. Pass `version: BEEF_V2` for BRC-96 format. Atomic BEEF (BRC-95)
312
- inner envelope remains V2 per spec.
313
-
314
- ### Fixed
315
-
316
- - [wallet] `wire_source_from_storage` resolves merkle proofs via proof store
317
- so `to_beef` produces valid BEEF that ARC accepts. Previously, BEEF
318
- contained source transactions without proofs, causing ARC 463/468
319
- rejections.
320
-
321
- ## wallet-0.2.2 — 2026-04-06
322
-
323
- ### Fixed
324
-
325
- - [wallet] `to_beef` now includes source transactions in the BEEF output, not
326
- just the subject transaction. Without ancestors, ARC could not validate the
327
- spend graph.
328
-
329
- ## sdk-0.6.2 / wallet-0.2.1 — 2026-04-06
330
-
331
- ### Added
332
-
333
- - [wallet] `WalletClient#create_action` now accepts `UnlockingScriptTemplate`
334
- objects (e.g. `P2PKH`) as input unlocking scripts, enabling template-based
335
- signing without BEEF.
336
- - [wallet] `wire_source_from_storage` fallback populates `source_satoshis`
337
- and `source_locking_script` from wallet storage when BEEF is absent or
338
- incomplete, enabling BIP-143 sighash computation for wallet-tracked
339
- outputs.
340
- - [wallet] `finalize_action` resolves template inputs via `sign_all` before
341
- serialisation.
342
- - [wallet] `MemoryStore#filter_outputs` supports outpoint filtering for
343
- efficient single-output lookups.
344
-
345
- The sdk gem was re-released alongside this wallet change with no
346
- behavioural changes of its own.
347
-
348
- ## sdk-0.6.1 — 2026-04-05
349
-
350
- ### Fixed
351
-
352
- - [sdk] Use internal byte order for Atomic BEEF subject txid lookup, fixing
353
- serialisation of transactions loaded from Atomic BEEF format.
354
-
355
- ## sdk-0.6.0 — 2026-04-04
356
-
357
- ### Added
358
-
359
- #### Primitives
360
-
361
- - [sdk] **Pure Ruby secp256k1** — native Ruby implementation of secp256k1
362
- elliptic curve operations, ported from the TypeScript reference SDK.
363
- Replaces OpenSSL's EC point arithmetic with an OpenSSL compatibility shim
364
- — zero consumer code changes required. See
365
- [docs/about/secp256k1.md](docs/about/secp256k1.md).
366
- - Field arithmetic (modular multiplication, inversion, square root) over
367
- the secp256k1 prime.
368
- - Jacobian coordinate point operations (addition, doubling, scalar
369
- multiplication).
370
- - Windowed-NAF (w=5) scalar multiplication with precomputed table caching.
371
- - SEC 1 point serialisation (compressed and uncompressed).
372
- - 126 byte-for-byte compliance specs against real OpenSSL.
373
- - 24 process-isolated integration tests (separate Ruby processes, MD5
374
- file comparison).
375
-
376
- #### Registry
377
-
378
- - [sdk] **Registry client** — `BSV::Registry` module for on-chain definition
379
- management.
380
- - `Client` — register, resolve, list, revoke, and update definitions for
381
- protocols, baskets, and certificate types via PushDrop tokens on the
382
- overlay network.
383
- - Per-type overlay topics (`tm_basketmap`, `tm_protomap`, `tm_certmap`)
384
- and lookup services matching TS and Go SDKs.
385
- - Types: `BasketDefinitionData`, `ProtocolDefinitionData`,
386
- `CertificateDefinitionData`, `CertificateFieldDescriptor`,
387
- `RegisteredDefinition`.
388
- - Ownership verification before revocation. BEEF Array/String
389
- normalisation for wire format compatibility.
390
-
391
- ### Changed
392
-
393
- - [sdk] OpenSSL usage reduced — OpenSSL now used only for hashing
394
- (SHA/RIPEMD), HMAC, PBKDF2, AES, and constant-time comparison. Elliptic
395
- curve operations are pure Ruby.
396
-
397
- ## sdk-0.5.0 — 2026-04-04
398
-
399
- ### Added
400
-
401
- #### Overlay
402
-
403
- - [sdk] **SHIP/SLAP overlay services** — `BSV::Overlay` module for
404
- topic-based transaction broadcasting and service discovery.
405
- - `TopicBroadcaster` (aliased as `SHIPBroadcaster`) — broadcasts tagged
406
- BEEF to topic-interested hosts with configurable acknowledgement modes
407
- (all/any/specific hosts) and STEAK response parsing.
408
- - `LookupResolver` — discovers competent hosts via SLAP trackers, queries
409
- in parallel, aggregates and deduplicates results. TTL-based host
410
- caching.
411
- - `HostReputationTracker` — EWMA latency scoring with exponential
412
- backoff, DNS error escalation, thread-safe. Optional persistence via
413
- injectable store adapter.
414
- - `AdminTokenTemplate` — decode/lock/unlock for SHIP/SLAP advertisement
415
- PushDrop tokens with BRC-42 wallet key derivation.
416
- - Abstract base classes (`LookupFacilitator`, `BroadcastFacilitator`)
417
- with default HTTPS implementations — all dependencies injectable via
418
- constructor.
419
- - SSRF protection for SLAP-discovered domains (private/loopback IP
420
- rejection).
421
-
422
- #### Identity
423
-
424
- - [sdk] **Identity client** — `BSV::Identity` module for certificate-based
425
- identity resolution and publication.
426
- - `Client` — resolve identities by key or attributes, publicly reveal
427
- certificate fields on-chain, revoke revelations. All overlay
428
- dependencies injectable.
429
- - `IdentityParser` — converts identity certificates to
430
- `DisplayableIdentity`, handling all 9 known types (xCert, discordCert,
431
- phoneCert, emailCert, identiCert, registrant, coolCert, anyone, self)
432
- plus generic field-name heuristic fallback.
433
- - Types: `DisplayableIdentity`, `IdentityCertificate`, `CertifierInfo`,
434
- `ClientOptions` with cross-SDK constant alignment.
435
- - Certificate verifier injectable with safe-by-default (raises
436
- `NotImplementedError`).
437
-
438
- #### Script
439
-
440
- - [sdk] **PushDropTemplate** — reusable wallet-aware PushDrop template with
441
- BRC-42 key derivation, optional ECDSA field signing, and P2PKH
442
- lock/unlock. Used by Identity client, reusable for ContactsManager and
443
- other PushDrop-based features.
444
-
445
- ### Fixed
446
-
447
- - [sdk] `ProtoWallet` parameter name mismatch: `_originator:` →
448
- `originator:` to match the `WalletInterface` contract.
449
-
450
- ## sdk-0.4.0 / wallet-0.2.0 — 2026-04-01
451
-
452
- ### Added
453
-
454
- #### Primitives
455
-
456
- - [sdk] **Bitcore ECIES** — `ECIES.bitcore_encrypt` /
457
- `ECIES.bitcore_decrypt`. AES-256-CBC with random IV, SHA-512(X-coordinate)
458
- key derivation. Matches ts-sdk and go-sdk Bitcore variants.
459
-
460
- #### Transaction
461
-
462
- - [sdk] **`LivePolicy.default`** — one-line convenience for live fee queries
463
- via GorillaPool ARC with 5-minute cache and 100 sat/kB fallback. (The
464
- underlying `LivePolicy` fee model itself shipped in sdk-0.3.2.)
465
-
466
- #### Wallet
467
-
468
- - [wallet] **FileStore** — JSON file-backed persistent storage, now the
469
- default for `WalletClient`. Data survives process restarts. `MemoryStore`
470
- becomes explicit opt-in for tests.
471
- - [wallet] **File permissions** — directory created with 0700, files with
472
- 0600. Warns via Logger on startup if permissions are too open.
473
-
474
- ### Changed
475
-
476
- - [sdk] **Default fee rate**: `SatoshisPerKilobyte` default changed from 50
477
- to 100 sat/kB (matches ts-sdk LivePolicy fallback).
478
-
479
- ## sdk-0.3.2 / wallet-0.1.2 — 2026-03-30
480
-
481
- ### Added
482
-
483
- #### Script
484
-
485
- - [sdk] **OP_CAT template** — OP_CAT concatenation script template with
486
- lock/unlock constructors.
487
-
488
- #### Transaction
489
-
490
- - [sdk] **LivePolicy fee model** — fetches policy from ARC `/v1/policy`
491
- endpoint. (The convenience constructor `LivePolicy.default` was added
492
- in sdk-0.4.0.)
493
-
494
- #### Wallet
495
-
496
- - [wallet] **BRC-31 Auth/Peer** — mutual authentication with nonce-based
497
- challenges, ECDSA signatures, and session management.
498
- - [wallet] **BRC-100 wire protocol** — binary ABI serialisation for all 28
499
- BRC-100 methods (call codes 1-28, VarInt encoding).
500
- - [wallet] **Certificate issuance** — `acquire_certificate` with
501
- `'issuance'` protocol (POST to certifier URL).
502
-
503
- ### Fixed
504
-
505
- - [sdk] PUSHDATA1/2/4 bounds check (silent data corruption on truncated
506
- scripts).
507
- - [sdk] Extended key path validation (reject non-numeric indices).
508
- - [wallet] Subject and certifier pinned in certificate issuance response
509
- (not overridable by remote certifier).
510
- - [wallet] Wire reader negative `privileged_reason` length crash.
511
-
512
- This was the first formal `bsv-wallet` gem release tag. Wallet code that
513
- landed in master before this date (notably the BRC-100 identity certificate
514
- methods and the BRC-100 blockchain-data / authentication methods committed
515
- during the sdk-0.3.1 window) is part of this gem's initial released state.
516
-
517
- ## sdk-0.3.1 — 2026-03-27
518
-
519
- ### Added
520
-
521
- #### Network
522
-
523
- - [sdk] **`ARC#broadcast` `wait_for:` parameter** — sets the `X-WaitFor`
524
- header (RECEIVED, STORED, ANNOUNCED_TO_NETWORK, SEEN_ON_NETWORK, MINED)
525
- so callers can choose how long ARC blocks before responding.
526
-
527
- ## sdk-0.3.0 — 2026-03-27
528
-
529
- ### Added
530
-
531
- #### Primitives
532
-
533
- - [sdk] **SymmetricKey** — AES-256-GCM encryption/decryption with 32-byte
534
- IV (cross-SDK compatible). Construct from random, ECDH, or raw bytes.
535
- - [sdk] **BRC-77 SignedMessage** — authenticated message signing and
536
- verification using BRC-42 derived keys. Supports targeted (specific
537
- verifier) and "anyone" modes.
538
- - [sdk] **BRC-78 EncryptedMessage** — end-to-end encrypted messaging using
539
- ECDH-derived symmetric keys.
540
- - [sdk] **Schnorr ZKP (BRC-94)** — zero-knowledge proof of ECDH shared
541
- secret knowledge. `Schnorr.generate_proof` / `Schnorr.verify_proof`.
542
- - [sdk] **Shamir's Secret Sharing** — split private keys into threshold
543
- shares (`PrivateKey#to_key_shares`) with Lagrange interpolation
544
- reconstruction. Backup format with integrity check.
545
-
546
- #### Script
547
-
548
- - [sdk] **PushDrop template** — data carrier with P2PK spending.
549
- `Script.pushdrop_lock` / `Script.pushdrop_unlock` with field extraction.
550
- - [sdk] **RPuzzle template** — R-puzzle hash-based spending with 6 hash
551
- type variants (raw, SHA1, SHA256, RIPEMD160, HASH160, HASH256).
552
-
553
- #### Transaction
554
-
555
- - [sdk] **Benford's law change distribution** — privacy-preserving change
556
- output splitting using Benford's first-digit distribution.
557
-
558
- ### Fixed
559
-
560
- - [sdk] Empty plaintext/ciphertext handling on older OpenSSL versions.
561
- - [sdk] PushDrop detection for minimally-encoded fields.
562
-
563
- ### Changed
564
-
565
- - [sdk] `Transaction#fee` change distribution uses Benford's law (was equal
566
- split).
567
- - [sdk] `LineLength` raised to 150.
568
-
569
- ## sdk-0.2.1 — 2026-03-07
570
-
571
- ### Fixed
572
-
573
- - [sdk] Truncated `OP_PUSHDATA1`/`2`/`4` scripts now raise `ArgumentError`
574
- instead of crashing with `TypeError`.
575
- - [sdk] `Transaction#to_beef` uses `merge_bump` to correctly handle
576
- multiple ancestors at the same block height.
577
- - [sdk] `PrivateKey#derive_child` uses `BN.mod_add` instead of Integer
578
- roundtrip for modular addition.
579
- - [sdk] Fixed txid byte-order documentation (display order, not internal
580
- order).
581
-
582
- ### Testing
583
-
584
- - [sdk] FORKID enforcement spec verifying interpreter rejects signatures
585
- without SIGHASH_FORKID.
586
- - [sdk] ExtendedKey fingerprint chain integrity across 3-generation
587
- derivation.
588
- - [sdk] Mnemonic entropy round-trip across all 5 valid entropy lengths.
589
- - [sdk] BEEF spec for multiple ancestors at the same block height.
590
-
591
- ## sdk-0.2.0 — 2026-03-07
592
-
593
- ### Added
594
-
595
- #### Primitives
596
-
597
- - [sdk] ECDH shared secret derivation
598
- (`PrivateKey#derive_shared_secret`, `PublicKey#derive_shared_secret`).
599
- - [sdk] BRC-42 key derivation (`PrivateKey#derive_child`,
600
- `PublicKey#derive_child`) with official spec test vectors.
601
-
602
- #### Transaction
603
-
604
- - [sdk] Chain tracker interface (`ChainTracker` base class) with
605
- WhatsOnChain implementation.
606
- - [sdk] Fee model interface (`FeeModel` base class) with
607
- `SatoshisPerKilobyte` implementation.
608
- - [sdk] `Transaction#fee` with change output distribution across multiple
609
- change outputs.
610
- - [sdk] `Transaction#verify` for full SPV verification (merkle path,
611
- script execution, recursive ancestry).
612
- - [sdk] `TransactionOutput#change` flag for identifying change outputs.
613
- - [sdk] `MerklePath#verify` for SPV chain tracker integration.
614
- - [sdk] BEEF completion: `Beef#merge`, `Beef#valid?`, lookup methods
615
- (`find_bump`, `find_transaction_for_signing`).
616
- - [sdk] `Transaction#to_beef` / `Transaction.from_beef` convenience
617
- methods.
618
- - [sdk] Extended Format (EF) transaction serialisation (`to_ef`,
619
- `to_ef_hex`, `from_ef`, `from_ef_hex`).
620
- - [sdk] `VerificationError` with typed error codes for SPV verification
621
- failures.
622
-
623
- ### Changed
624
-
625
- - [sdk] ECIES refactored to use `PrivateKey#derive_shared_secret`
626
- internally (no API change).
627
- - [sdk] `Transaction#estimated_size` made public for fee model access.
628
-
629
- ### Fixed
630
-
631
- - [sdk] Nil `source_satoshis` now raises instead of silently coercing to
632
- zero in fee distribution and verification.
633
- - [sdk] Script chunk round-trips preserve original push encoding.
634
- - [sdk] `OP_RETURN` inside conditionals correctly checked for conditional
635
- balance.
636
- - [sdk] Point x-coordinate extraction preserves leading zeros via octet
637
- string.
638
- - [sdk] `Integer#nobits?` replaced with Ruby 2.7-compatible bitwise check.
639
- - [sdk] Defensive parsing with descriptive errors for truncated binary
640
- input.
641
-
642
- ### Testing
643
-
644
- - [sdk] BRC-42 conformance specs with 9 official specification test
645
- vectors.
646
- - [sdk] ECDH conformance specs (commutativity, cross-method, pinned
647
- known-key vector).
648
- - [sdk] SPV verification conformance specs (merkle path, script execution,
649
- ancestry).
650
- - [sdk] Fee model conformance specs (formula validation, default rate,
651
- change distribution).
652
- - [sdk] Chain tracker conformance specs.
653
- - [sdk] BEEF cross-SDK conformance vectors.
654
- - [sdk] Schnorr (BRC-94) cross-SDK interoperability vectors.
655
- - [sdk] 6 exact-match RFC 6979 vectors from Trezor/CoreBitcoin.
656
- - [sdk] VarInt boundary tests at size-prefix transitions.
657
- - [sdk] Script vectors converted to tracked known-failures system.
658
-
659
- ## sdk-0.1.0 — 2026-02-14
660
-
661
- Initial release of the BSV Ruby SDK.
662
-
663
- ### Added
664
-
665
- #### Primitives
666
-
667
- - [sdk] secp256k1 elliptic curve operations (point arithmetic, scalar
668
- multiplication).
669
- - [sdk] ECDSA signing and verification with RFC 6979 deterministic nonces.
670
- - [sdk] Public and private key handling (WIF import/export,
671
- compressed/uncompressed formats).
672
- - [sdk] Base58Check encoding and decoding.
673
- - [sdk] Hash functions: SHA-256, RIPEMD-160, Hash160 (SHA-256 +
674
- RIPEMD-160), SHA-512, HMAC.
675
- - [sdk] BIP-32 hierarchical deterministic key derivation (extended keys,
676
- hardened/normal child paths).
677
- - [sdk] BIP-39 mnemonic phrase generation and seed derivation.
678
- - [sdk] ECIES encryption and decryption (BIE1 format).
679
- - [sdk] Bitcoin Signed Message (BSM) signing and verification.
680
-
681
- #### Script
682
-
683
- - [sdk] Opcode constants (full set).
684
- - [sdk] Script chunk representation and parsing.
685
- - [sdk] Script serialisation and deserialisation.
686
- - [sdk] Script templates: P2PKH, P2PK, P2MS (multisig), OP_RETURN data.
687
- - [sdk] Script type detection (including read-only recognition of P2SH and
688
- other legacy types).
689
- - [sdk] Script builder API for programmatic construction.
690
- - [sdk] Script interpreter with stack operations, arithmetic, crypto, flow
691
- control, splice, and bitwise ops.
692
-
693
- #### Transaction
694
-
695
- - [sdk] Transaction construction and serialisation (raw format).
696
- - [sdk] BIP-143 sighash computation (all hash types with FORKID).
697
- - [sdk] Transaction signing with configurable sighash flags.
698
- - [sdk] BEEF serialisation (BRC-95/BRC-96).
699
- - [sdk] Merkle path representation and verification.
700
- - [sdk] Fee estimation.
701
- - [sdk] Script verification during signing.
702
- - [sdk] Unlocking script templates for common script types.
703
-
704
- #### Network
705
-
706
- - [sdk] ARC broadcaster for transaction submission.
707
- - [sdk] WhatsOnChain chain data provider.
708
- - [sdk] Basic wallet functionality.
709
-
710
- #### Testing
711
-
712
- - [sdk] Cross-SDK test vectors from Go, TypeScript, and Python reference
713
- implementations.
714
- - [sdk] NIST and RFC hash function test vectors.
715
- - [sdk] Bitcoin Core script interpreter test suite.
716
- - [sdk] Protocol conformance specs for opcodes, sighash flags, and
717
- transaction templates.