# Evan's `bdk_chain` Redesign Analysis and Proposal Consider this an extension of [bdk #895](https://github.com/bitcoindevkit/bdk/issues/895). ## Objectives * Ensure the redesign allows for better sync integration with LDK. According to @tnull ([on Discord](https://discord.com/channels/753336465005608961/999098651383189554/1087285168491995156)) the most difficult part is Esplora/Electrum sync due to the assumptions about the order of data that is passed on to LDK (refer to the [docs about Order of the `Confirm` trait](https://docs.rs/lightning/0.0.114/lightning/chain/trait.Confirm.html#order)). * Ensure the redesigned structures allow for an intuitive sync flow for Esplora/Electrum. * Ensure the redesign still allows for us to keep a copy of "blockchain checkpoint" data locally in a manner that is intuitive. ## How does BDK fit in with LDK? The diagram below is a subset of the LDK architecture (and the only portion that we should care about now). ![](https://i.imgur.com/W4bKzRM.png) The *Chain Monitor* implements the [`Confirm`](https://docs.rs/lightning/0.0.114/lightning/chain/trait.Confirm.html) and [`Listen`](https://docs.rs/lightning/0.0.114/lightning/chain/trait.Listen.html) traits which provides methods that *Chain Source* should invoke to notify *Chain Monitor* of chain data. * [`Confirm`](https://docs.rs/lightning/0.0.114/lightning/chain/trait.Confirm.html) is geared towards transaction-oriented APIs (esplora and electrum). * [`Listen`](https://docs.rs/lightning/0.0.114/lightning/chain/trait.Listen.html) is geared towards block-oriented APIs (CBF, Bitcoin Core Chain). *Chain source* is the component that may use BDK internally (whether it be `bdk_chain`, `bdk_esplora`, `bdk_electrum`, etc.). [`Filter`](https://docs.rs/lightning/0.0.114/lightning/chain/trait.Filter.html) is a trait that *Chain Source* should implement if it sources from a light client. This way, *Chain Monitor* can invoke `Filter` methods to inform *Chain Source* what data to filter for. ### Syncing from `bitcoind` RPC This should be straight-forward. We stream block events from `bitcoind` into both BDK's `bdk_chain` structures and LDK's `Listen` methods. ### Syncing from CBF (with Nakamoto) This is similar to `bitcoind` RPC, except we should "listen" for `Filter` invocations that we use to construct block filters that is pass on to the Nakamoto client. We can then pass filtered blocks into `Listen::filtered_block_connected`. It may make sense to use separate compact block filters for BDK vs LDK data. ### Syncing from Electrum/Esplora Looking at [`lightning_transaction_sync::esplora::EsploraSyncClient`](https://github.com/lightningdevkit/rust-lightning/blob/main/lightning-transaction-sync/src/esplora.rs), it will be ideal to have a version of this that also collects data for BDK in the same loop. Essentially, proper LDK and BDK integration does not rely on special features with `bdk_chain`. LDK already keeps note of txids and outpoints that it wants updates for. ## `LocalChainOracle` This is essentially a super-simplified version of the current `SparseChain` (or [`#895`'s](https://github.com/bitcoindevkit/bdk/issues/895) `SparseChain2` as mentioned in the work plan). The intention of this design is to ensure Esplora/Electrum sync works smoothly with the redesigned workflow. However, any data source can update this structure if the user intends on not depending on an external `ChainOracle`. ```rust struct LocalChainOracle { /* internal fields */ } impl ChainOracle for LocalChainOracle { /* todo */ } impl LocalChainOracle { } ``` ~~TODO: I'm just too tired to finish this. At least we know that the redesign will work fine with LDK.~~ I thought about it over night, we are reusing the `SparseChain` logic with checkpoints only. This is an ultimate simplification and good as it is as we do not need to check for conflicting transactions, or invalid "transaction movements". ## Syncing in detail ### Electrum: Full Scan 1. Collect all heights of `LocalChain`. Collect all `txid`s from `TxGraph`. ```rust pub fn scan(heights: BTreeSet<u32>, txids: HashSet<Txid>) -> ElectrumUpdate { todo!() } ``` 3. Get chain tip from Electrum. 4. Collect transactions into structure: ```rust struct ElectrumUpdate { /// Txids to confirmation height (if any). pub txs: HashMap<Txid, Option<u32>>, /// Used for updating `LocalChain`. /// /// Blocks with at least one relevant tx confirmed must be included here, unless if height is lower than `heights.last() - 10` and height is included in `heights`. pub blocks: BTreeMap<u32, BlockHash>, } ``` 5. Ensure chain tip still exists in best chain after `ElectrumUpdate` is finalized.