From: merge-script Date: Wed, 11 Nov 2026 00:56:29 +0000 (+1100) Subject: Merge bitcoindevkit/bdk#2232: feat(core): allow serialization of SyncResponse and... X-Git-Url: http://internal-gitweb-vhost/-script/src/example_cli/scripts/encode/Bip39Exception.AmbiguousLanguages.html?a=commitdiff_plain;ds=sidebyside;p=bdk Merge bitcoindevkit/bdk#2232: feat(core): allow serialization of SyncResponse and FullScanResponse 56d92eb79461925f2983983806f57f4532926363 feat(core): allow serialization of SyncResponse and FullScanResponse (Claude) Pull request description: ### Description Adds `serde::Serialize` / `serde::Deserialize` for `SyncResponse` and `FullScanResponse` (under the `serde` feature). This enables offline workflows: an online device syncs or scans, serializes the response, and hands it to a device without internet access, which deserializes and applies it on its own. This is the goal of #1954, implemented without recursion. Both responses are made of a `TxUpdate` and an `Option` (plus `last_active_indices` for `FullScanResponse`), so those gain serde support too: - `TxUpdate`: a plain derive. Its fields are flat collections, so there is nothing self-referential to recurse over. `serde(default)` lets a newer reader accept data from an older writer that lacks a later-added field. - `CheckPoint`: implemented by hand. It is a reference-counted linked list, so a derived impl would recurse once per checkpoint and overflow the stack on long chains, the same hazard that forced the hand-written `Drop` (#1634). - Serialize walks the chain with `CheckPoint::iter()` and emits a flat, tip-first sequence of `(height, data)` pairs. - Deserialize rebuilds it with `CheckPoint::from_blocks(..)`, which re-derives the `skip`/`index` topology and rejects blocks that aren't in ascending height order (or, for data with a `prev_blockhash` such as `Header`, aren't linked). ### Notes to the reviewers - Alternative to #1954, addressing the "serializing `CheckPoint`s is a bit odd since it is a linked list" concern raised there: the list is flattened and rebuilt, so neither direction recurses. - Why responses rather than `ChangeSet`s (the route discussed on #1954 and bitcoindevkit/bdk_wallet#231): a `ChangeSet` only applies if both sides start from the same state, while a response is self-contained. - `checkpoint_serde_is_not_recursive` round-trips a 10,240-checkpoint chain on a 32 KiB thread stack, like `checkpoint_drop_is_not_recursive`. A recursive impl would overflow it. - `checkpoint_serde_rejects_unlinked_headers` covers the deserialize error path with `Header` data. - `serde_json` is added only as a dev-dependency of `bdk_core`, for the tests. ### Changelog notice - Added `serde::Serialize` and `serde::Deserialize` implementations for `SyncResponse`, `FullScanResponse`, `TxUpdate` and `CheckPoint` (under the `serde` feature). `CheckPoint` is (de)serialized iteratively as a flat list of `(height, data)` blocks. ### Checklists #### All Submissions: * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md) #### New Features: * [x] I've added tests for the new feature * [x] I've added docs for the new feature --- _Generated by [Claude Code](https://claude.ai/code/session_014BXMFRQP8qoGBghJcWzakG)_ ACKs for top commit: evanlinjin: self-ACK 56d92eb79461925f2983983806f57f4532926363 Tree-SHA512: fff75a10cd7a12ec7308699e674a03cba257e633b0feb1c58ccf42f04fb683dbfb17db0af0fae433272241e51d1d2e88f101059053bb74f59222edc10d615069 --- 7cbb3633a4a8418d71e85995d6577d31ca564b73