# 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).

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.