All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Optional SPV / transaction verification on submit —
OverlayEngine(..., verify_tx=...)runs an injected(tx) -> bool(sync or async) before admittance; returning False rejects withSPVVerificationError. The canonical use is BRC-9 SPV:verify_tx=lambda tx: tx.verify(tracker)with aChainTracker(e.g. headers.peck.to-backed) to check merkle proofs against block headers. Defaults to off (trust the BEEF — what a mempool/zero-conf overlay wants); deliberately never defaults to the SDK's WhatsOnChain tracker. bsv_brc.brc052re-exports the BRC-42/43 key helpers it composes (public_key_from_private,shared_secret,derive_symmetric_key,derive_signing_key,invoice_number), so a BRC-52 issuer has one import surface (unblocks dropping the legacybrc52-pythonfork).- Overlay CLIENT (
bsv_brc.overlay.OverlayClient) — the consumer side, defaulting tooverlay.peck.to.submit(beef, topics)(JSONx-topicsarray + octet-stream BEEF) returns a parsed STEAK with.admittedand an opt-inNoAdmissionError(the silent 200-but-rejected trap);lookup(service, query)parses the BEEF-backed output-list (beef as byte-array or base64, txid from the AtomicBEEF prefix);state()/topic_state()readGET /state; andverify_state(topic, outpoints)checks the node's published state root against a localstate_root(). Pure I/O-free builders/parsers (build_submit_headers,parse_steak,parse_lookup_answer,parse_state) are exposed for async apps to wire into their own HTTP client; the bundled client is stdlib-urllibonly (no new deps) and takes afetchoverride for testing/httpx. Verified live against overlay.peck.to. Closes the gap where every Python service hand-rolled its own overlay consumer.
- Overlay node — be the server, not just a client (
bsv-sdkships only the overlay client side):- BRC-22 (
bsv_brc.brc22) —TopicManager(define which outputs your topic admits),TopicEngine(parse BEEF, run each hosted manager, return the topic-keyed STEAK map), andadapters.asgiwith a mountableSubmitASGIAppplus a redirect-freemake_submit_route. - BRC-24 (
bsv_brc.brc24) —LookupService(the read side: index admitted outputs, answer queries),OutputRef, and a binary output-list serializer matching the format py-sdk'sLookupResolverintends to read (py-sdk 2.0.0b1's parser has aread_var_intvsread_var_int_numbug — filed-worthy — so the included round-trip test decodes with the corrected reader). bsv_brc.overlay—OverlayEnginecomposes topic managers + lookup services + anOverlayStorageinto one submit/lookup engine with admit/spend event dispatch;create_overlay_appexposes/submit+/lookupas a Starlette app.- Production-ready node:
SqliteOverlayStorage(persistent, alongside the in-memory reference) and BEEF-backed answers — a client that sendsAccept: application/jsonto/lookupgets each output's full BEEF (base64) and can reconstruct the transaction without a second fetch; the default binary answer stays py-sdk compatible. Added an[overlay]extra. - Admittance/answer types (
AdmittanceInstructions,TaggedBEEF,LookupQuestion,LookupAnswer) are reused frombsv.overlay_tools, not redefined. - BRC-87 (
bsv_brc.brc87) —validate_topic_name/validate_service_name(+is_valid_*andvalidate_overlay_name) enforce thetm_/ls_master rules so a bad name fails fast instead of silently failing to interoperate. - Per-topic state root (
bsv_brc.overlay.topic_root+OverlayEngine.topic_root/topic_roots) — the canonical peck-social-overlay root over a topic's live (unspent) outpoint set:sha256of the deduped, lexicographically-sorted"<txid>:<vout>"strings joined by newlines (empty set →sha256("")). Verified to matchoverlay.peck.to'sGET /statestateRootexactly (the empty-set valuee3b0c442…is asserted against the live overlay in the test suite), so a bsv-brc node and the live peck overlay agree on a topic's root for the same UTXO set.create_overlay_appnow also servesGET /state({"status","topics":[{"topic","count","stateRoot"}]}) — the same verifiable contractoverlay.peck.toexposes (make_state_route,OverlayEngine.topic_state/topic_states).
- BRC-22 (
- Filed-ready bug reports for two
bsv-sdk(py-sdk) defects found while building on it, indocs/upstream/— both confirmed present in the latest PyPI2.1.3andmasterHEAD (not just our pinned beta):LookupResolver._parse_binary_responseusesread_var_int(bytes) where it needsread_var_int_num(int), crashing on any binary output-list answer; andProtoWallet.internalize_actionparses AtomicBEEF as a raw transaction, risking a corrupt broadcast. - Integration layer (
bsv_brc.integration) —build_brc_appstacks BRC-103/104 auth under BRC-105 payments in the correct order;make_internalize_verifier/build_internalize_argsprovide the BRC-29 derivation prefix/suffix →wallet.internalize_actionmapping (the hardest hand-rolled step) as a ready callback;PathPricing,get_identityandget_paymentare small request-side ergonomics. - BRC-104 ASGI adapter released —
bsv_brc.brc104.adapters.asgi(AuthMiddleware) wrappingbsv.auth.Peerfor Starlette/FastAPI/ FastHTML, built in 0.2.x but previously unreleased, now ships. py.typedmarker so downstream type-checkers see the library's hints.- Top-level re-exports +
__all__onbsv_brc; integration helpers are lazily exposed soimport bsv_brcstill works without thestarletteextra. examples/full_app.py— a fake-free server stacking auth + payments + a BRC-22 topic.examples/social_feed.py— a complete ~150-line social overlay node (tm_poststopic +ls_postsfeed + an HTML/feed): the seed of an open-source peck.to built entirely on this library.
- Interop:
/submitnow accepts theX-Topicsformat py-sdk'sTopicBroadcasteractually sends — a comma-separated string — as well as a JSON array. Previously every real py-sdk submission was rejected. - Correctness: a coin a transaction spends on-chain is now always
marked spent and fires
output_spent, even when the topic manager lists it incoins_to_retain(retention is a history concern, not liveness; matches canonical @bsv/overlay). Fixes stale state lingering in current-state feeds. - Concurrency:
OverlayEngine.submitserializes its check-then-act under anasyncio.Lock(an async topic manager could otherwise let two concurrent submits double-spend a coin);SqliteOverlayStoragereads now take the write lock (lock-free reads on the shared connection raced); the BEEF-backed lookupresolveruns off the event loop viaasyncio.to_thread. - Safety: request bodies are capped (default 32 MiB, configurable;
413 on overflow) instead of buffering unboundedly;
/submitand/lookupno longer reflect internal exception text to clients (logged server-side);X-Topicsis capped at 64 topics and the unknown-topic error no longer echoes the requested list;serialize_output_listrejects non-32-byte txids instead of silently corrupting the stream. - Docs:
build_brc_app's defaultStaticPricing(0)clarified (no payment ≠ open access — auth still required);make_internalize_verifierdocuments that the wallet must accept AtomicBEEF (the bsv-sdk 2.0.0b1ProtoWalletdoes not — tracked upstream).
- Still deferred: the BRC-35 Global KVStore client (its PushDrop field
layout can't be verified —
overlay.peck.todoesn't hosttm_kvstore); on-chain anchoring of the topic state root + GASP peer sync (the root format itself is now verified, but anchoring/sync are a larger piece); the binary lookup-answer's trailing BEEF (BEEF ships via the JSON path). SHIP/SLAP (BRC-88) is intentionally not pursued — overlay.social federates via state roots + GASP, not SHIP/SLAP. - Out of scope and documented as such: BRC-101 (aspirational, no normative behavior), BRC-108 (no Mandala/BRC-92/107 token base in either package), BRC-116 (needs an external sCrypt/scrypt-ord toolchain).
- Bumped the
bsv-sdkfloor from the pre-release2.0.0b1to the latest stable2.1.3. Full suite stays green. (Note: the two upstream py-sdk bugs indocs/upstream/persist at 2.1.3 / HEAD, so this bump is unrelated to them.)
- Pivoted
bsv-brcfrom a parallel BRC-103/104 implementation to a set of framework adapters around the officialbsv.authmodule shipped inbsv-sdk==2.0.0b1. The previously bundledbsv_brc.brc103.*andbsv_brc.brc104.core.preimagemodules duplicated functionality that already exists upstream and have been removed. bsv-sdkminimum bumped to2.0.0b1(pre-release). Install withpip install --pre bsv-brcor pin explicitly.- Added
typing_extensionsas a direct dependency to work around a missing transitive declaration inbsv-sdk==2.0.0b1.
bsv_brc.brc103package (usebsv.authfrombsv-sdkdirectly).bsv_brc.brc104.core.preimage(usebsv.auth.clients.auth_fetch.AuthFetch/ the bsv.auth response serializer).bsv_brc.brc104.core.headersis retained for adapter use.- Tests covering the removed modules.
- BRC-52, BRC-94 and BRC-105 are unchanged and remain the unique value
of this package alongside the upcoming ASGI/WSGI adapters for
bsv.auth. - Wire-format audit against
bsv.authfound one divergence inherited frompy-middleware: response preimage must include theauthorizationheader. This will be addressed in the new adapter layer rather than in the deletedpreimage.py.
- Migrated cryptographic primitives from
coincurve+ecdsato the officialbsv-sdk(py-sdk). This consolidates the secp256k1, signing, and key derivation surface onto the upstream BSV Python SDK and removes a layer of dependencies.
- GitHub Actions CI workflow running the test suite on Python 3.10–3.13.
- Updated
CLAUDE.mdto reflect the new dependency surface.
- Initial release.
bsv_brc.brc052— BRC-42/43/52/53: identity certificates, ECDH key derivation, AES-256-GCM encryption, certificate signing and issuance.bsv_brc.brc094— BRC-94: Schnorr proof of ECDH shared secrets, counterparty linkage.bsv_brc.brc105— BRC-105: HTTP 402 micropayment middleware (Starlette) and client.bsv_brc.crypto— shared BRC-42 / BRC-43 key derivation primitives.- 63 tests covering all three BRC modules.