Implement linked-list LocalChain and update chain-src crates/examples

This commit changes the `LocalChain` implementation to have blocks
stored as a linked-list. This allows the data-src thread to hold a
shared ref to a single checkpoint and have access to the whole history
of checkpoints without cloning or keeping a lock on `LocalChain`.

The APIs of `bdk::Wallet`, `esplora` and `electrum` are also updated to
reflect these changes. Note that the `esplora` crate is rewritten to
anchor txs in the confirmation block (using the esplora API's tx status
block_hash). This guarantees 100% consistency between anchor blocks and
their transactions (instead of anchoring txs to the latest tip).
`ExploraExt` now has separate methods for updating the `TxGraph` and
`LocalChain`.

A new method `TxGraph::missing_blocks` is introduced for finding
"floating anchors" of a `TxGraph` update (given a chain).

Additional changes:

* `test_local_chain.rs` is refactored to make test cases easier to
  write. Additional tests are also added.
* Examples are updated.
* Fix `tempfile` dev dependency of `bdk_file_store` to work with MSRV

Co-authored-by: LLFourn <lloyd.fourn@gmail.com>
This commit is contained in:
志宇
2023-07-19 17:42:52 +08:00
parent f4d2a76661
commit eabeb6ccb1
18 changed files with 1551 additions and 904 deletions

View File

@@ -1,12 +1,13 @@
const DB_MAGIC: &str = "bdk_wallet_esplora_example";
const SEND_AMOUNT: u64 = 5000;
const STOP_GAP: usize = 50;
const PARALLEL_REQUESTS: usize = 5;
const SEND_AMOUNT: u64 = 1000;
const STOP_GAP: usize = 5;
const PARALLEL_REQUESTS: usize = 1;
use std::{io::Write, str::FromStr};
use bdk::{
bitcoin::{Address, Network},
chain::keychain::LocalUpdate,
wallet::AddressIndex,
SignOptions, Wallet,
};
@@ -36,7 +37,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let client =
esplora_client::Builder::new("https://blockstream.info/testnet/api").build_blocking()?;
let local_chain = wallet.checkpoints();
let prev_tip = wallet.latest_checkpoint();
let keychain_spks = wallet
.spks_of_all_keychains()
.into_iter()
@@ -52,17 +53,20 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
(k, k_spks)
})
.collect();
let update = client.scan(
local_chain,
keychain_spks,
None,
None,
STOP_GAP,
PARALLEL_REQUESTS,
)?;
println!();
let (update_graph, last_active_indices) =
client.update_tx_graph(keychain_spks, None, None, STOP_GAP, PARALLEL_REQUESTS)?;
let get_heights = wallet.tx_graph().missing_blocks(wallet.local_chain());
let chain_update = client.update_local_chain(prev_tip, get_heights)?;
let update = LocalUpdate {
keychain: last_active_indices,
graph: update_graph,
..LocalUpdate::new(chain_update)
};
wallet.apply_update(update)?;
wallet.commit()?;
println!();
let balance = wallet.get_balance();
println!("Wallet balance after syncing: {} sats", balance.total());