refactor: move WalletChangeset to wallet module
Consequently, remove the `WalletChangeset` dependency from `example_electrum` and `example_esplora` examples.
This commit is contained in:
parent
2392e50fd9
commit
68572bfd2e
@ -22,10 +22,10 @@ use alloc::{
|
|||||||
pub use bdk_chain::keychain::Balance;
|
pub use bdk_chain::keychain::Balance;
|
||||||
use bdk_chain::{
|
use bdk_chain::{
|
||||||
indexed_tx_graph,
|
indexed_tx_graph,
|
||||||
keychain::{KeychainTxOutIndex, WalletChangeSet},
|
keychain::{self, KeychainTxOutIndex},
|
||||||
local_chain::{self, CannotConnectError, CheckPoint, CheckPointIter, LocalChain},
|
local_chain::{self, CannotConnectError, CheckPoint, CheckPointIter, LocalChain},
|
||||||
tx_graph::{CanonicalTx, TxGraph},
|
tx_graph::{CanonicalTx, TxGraph},
|
||||||
Append, BlockId, ChainPosition, ConfirmationTime, ConfirmationTimeAnchor, FullTxOut,
|
Anchor, Append, BlockId, ChainPosition, ConfirmationTime, ConfirmationTimeAnchor, FullTxOut,
|
||||||
IndexedTxGraph, Persist, PersistBackend,
|
IndexedTxGraph, Persist, PersistBackend,
|
||||||
};
|
};
|
||||||
use bitcoin::consensus::encode::serialize;
|
use bitcoin::consensus::encode::serialize;
|
||||||
@ -124,6 +124,62 @@ impl<K, A> WalletUpdate<K, A> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A structure that records the corresponding changes as result of applying an [`WalletUpdate`].
|
||||||
|
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct WalletChangeSet<K, A> {
|
||||||
|
/// Changes to the [`LocalChain`].
|
||||||
|
///
|
||||||
|
/// [`LocalChain`]: local_chain::LocalChain
|
||||||
|
pub chain: local_chain::ChangeSet,
|
||||||
|
|
||||||
|
/// ChangeSet to [`IndexedTxGraph`].
|
||||||
|
///
|
||||||
|
/// [`IndexedTxGraph`]: bdk_chain::indexed_tx_graph::IndexedTxGraph
|
||||||
|
#[serde(bound(
|
||||||
|
deserialize = "K: Ord + serde::Deserialize<'de>, A: Ord + serde::Deserialize<'de>",
|
||||||
|
serialize = "K: Ord + serde::Serialize, A: Ord + serde::Serialize",
|
||||||
|
))]
|
||||||
|
pub index_tx_graph: indexed_tx_graph::ChangeSet<A, keychain::ChangeSet<K>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, A> Default for WalletChangeSet<K, A> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
chain: Default::default(),
|
||||||
|
index_tx_graph: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K: Ord, A: Anchor> Append for WalletChangeSet<K, A> {
|
||||||
|
fn append(&mut self, other: Self) {
|
||||||
|
Append::append(&mut self.chain, other.chain);
|
||||||
|
Append::append(&mut self.index_tx_graph, other.index_tx_graph);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
|
self.chain.is_empty() && self.index_tx_graph.is_empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, A> From<local_chain::ChangeSet> for WalletChangeSet<K, A> {
|
||||||
|
fn from(chain: local_chain::ChangeSet) -> Self {
|
||||||
|
Self {
|
||||||
|
chain,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, A> From<indexed_tx_graph::ChangeSet<A, keychain::ChangeSet<K>>> for WalletChangeSet<K, A> {
|
||||||
|
fn from(index_tx_graph: indexed_tx_graph::ChangeSet<A, keychain::ChangeSet<K>>) -> Self {
|
||||||
|
Self {
|
||||||
|
index_tx_graph,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The update to a [`Wallet`] used in [`Wallet::apply_update`]. This is usually returned from blockchain data sources.
|
/// The update to a [`Wallet`] used in [`Wallet::apply_update`]. This is usually returned from blockchain data sources.
|
||||||
pub type Update = WalletUpdate<KeychainKind, ConfirmationTimeAnchor>;
|
pub type Update = WalletUpdate<KeychainKind, ConfirmationTimeAnchor>;
|
||||||
|
|
||||||
@ -277,7 +333,7 @@ impl<D> Wallet<D> {
|
|||||||
|
|
||||||
let changeset = db.load_from_persistence().map_err(NewError::Persist)?;
|
let changeset = db.load_from_persistence().map_err(NewError::Persist)?;
|
||||||
chain.apply_changeset(&changeset.chain);
|
chain.apply_changeset(&changeset.chain);
|
||||||
indexed_graph.apply_changeset(changeset.indexed_tx_graph);
|
indexed_graph.apply_changeset(changeset.index_tx_graph);
|
||||||
|
|
||||||
let persist = Persist::new(db);
|
let persist = Persist::new(db);
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
//!
|
//!
|
||||||
//! [`SpkTxOutIndex`]: crate::SpkTxOutIndex
|
//! [`SpkTxOutIndex`]: crate::SpkTxOutIndex
|
||||||
|
|
||||||
use crate::{collections::BTreeMap, indexed_tx_graph, local_chain, Anchor, Append};
|
use crate::{collections::BTreeMap, Append};
|
||||||
|
|
||||||
#[cfg(feature = "miniscript")]
|
#[cfg(feature = "miniscript")]
|
||||||
mod txout_index;
|
mod txout_index;
|
||||||
@ -80,69 +80,6 @@ impl<K> AsRef<BTreeMap<K, u32>> for ChangeSet<K> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A structure that records the corresponding changes as result of applying an [`WalletUpdate`].
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
|
||||||
#[cfg_attr(
|
|
||||||
feature = "serde",
|
|
||||||
derive(serde::Deserialize, serde::Serialize),
|
|
||||||
serde(
|
|
||||||
crate = "serde_crate",
|
|
||||||
bound(
|
|
||||||
deserialize = "K: Ord + serde::Deserialize<'de>, A: Ord + serde::Deserialize<'de>",
|
|
||||||
serialize = "K: Ord + serde::Serialize, A: Ord + serde::Serialize",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)]
|
|
||||||
pub struct WalletChangeSet<K, A> {
|
|
||||||
/// Changes to the [`LocalChain`].
|
|
||||||
///
|
|
||||||
/// [`LocalChain`]: local_chain::LocalChain
|
|
||||||
pub chain: local_chain::ChangeSet,
|
|
||||||
|
|
||||||
/// ChangeSet to [`IndexedTxGraph`].
|
|
||||||
///
|
|
||||||
/// [`IndexedTxGraph`]: crate::indexed_tx_graph::IndexedTxGraph
|
|
||||||
pub indexed_tx_graph: indexed_tx_graph::ChangeSet<A, ChangeSet<K>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<K, A> Default for WalletChangeSet<K, A> {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
chain: Default::default(),
|
|
||||||
indexed_tx_graph: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<K: Ord, A: Anchor> Append for WalletChangeSet<K, A> {
|
|
||||||
fn append(&mut self, other: Self) {
|
|
||||||
Append::append(&mut self.chain, other.chain);
|
|
||||||
Append::append(&mut self.indexed_tx_graph, other.indexed_tx_graph);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_empty(&self) -> bool {
|
|
||||||
self.chain.is_empty() && self.indexed_tx_graph.is_empty()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<K, A> From<local_chain::ChangeSet> for WalletChangeSet<K, A> {
|
|
||||||
fn from(chain: local_chain::ChangeSet) -> Self {
|
|
||||||
Self {
|
|
||||||
chain,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<K, A> From<indexed_tx_graph::ChangeSet<A, ChangeSet<K>>> for WalletChangeSet<K, A> {
|
|
||||||
fn from(indexed_tx_graph: indexed_tx_graph::ChangeSet<A, ChangeSet<K>>) -> Self {
|
|
||||||
Self {
|
|
||||||
indexed_tx_graph,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Balance, differentiated into various categories.
|
/// Balance, differentiated into various categories.
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Default)]
|
#[derive(Debug, PartialEq, Eq, Clone, Default)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
|
@ -100,3 +100,11 @@ pub mod collections {
|
|||||||
|
|
||||||
/// How many confirmations are needed f or a coinbase output to be spent.
|
/// How many confirmations are needed f or a coinbase output to be spent.
|
||||||
pub const COINBASE_MATURITY: u32 = 100;
|
pub const COINBASE_MATURITY: u32 = 100;
|
||||||
|
|
||||||
|
impl<A, IA> From<indexed_tx_graph::ChangeSet<A, IA>>
|
||||||
|
for (local_chain::ChangeSet, indexed_tx_graph::ChangeSet<A, IA>)
|
||||||
|
{
|
||||||
|
fn from(indexed_changeset: indexed_tx_graph::ChangeSet<A, IA>) -> Self {
|
||||||
|
(local_chain::ChangeSet::default(), indexed_changeset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -7,7 +7,7 @@ use std::{
|
|||||||
use bdk_chain::{
|
use bdk_chain::{
|
||||||
bitcoin::{Address, Network, OutPoint, ScriptBuf, Txid},
|
bitcoin::{Address, Network, OutPoint, ScriptBuf, Txid},
|
||||||
indexed_tx_graph::{self, IndexedTxGraph},
|
indexed_tx_graph::{self, IndexedTxGraph},
|
||||||
keychain::WalletChangeSet,
|
keychain,
|
||||||
local_chain::{self, LocalChain},
|
local_chain::{self, LocalChain},
|
||||||
Append, ConfirmationHeightAnchor,
|
Append, ConfirmationHeightAnchor,
|
||||||
};
|
};
|
||||||
@ -60,7 +60,10 @@ pub struct ScanOptions {
|
|||||||
pub batch_size: usize,
|
pub batch_size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChangeSet = WalletChangeSet<Keychain, ConfirmationHeightAnchor>;
|
type ChangeSet = (
|
||||||
|
local_chain::ChangeSet,
|
||||||
|
indexed_tx_graph::ChangeSet<ConfirmationHeightAnchor, keychain::ChangeSet<Keychain>>,
|
||||||
|
);
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
let (args, keymap, index, db, init_changeset) =
|
let (args, keymap, index, db, init_changeset) =
|
||||||
@ -68,11 +71,11 @@ fn main() -> anyhow::Result<()> {
|
|||||||
|
|
||||||
let graph = Mutex::new({
|
let graph = Mutex::new({
|
||||||
let mut graph = IndexedTxGraph::new(index);
|
let mut graph = IndexedTxGraph::new(index);
|
||||||
graph.apply_changeset(init_changeset.indexed_tx_graph);
|
graph.apply_changeset(init_changeset.1);
|
||||||
graph
|
graph
|
||||||
});
|
});
|
||||||
|
|
||||||
let chain = Mutex::new(LocalChain::from_changeset(init_changeset.chain));
|
let chain = Mutex::new(LocalChain::from_changeset(init_changeset.0));
|
||||||
|
|
||||||
let electrum_url = match args.network {
|
let electrum_url = match args.network {
|
||||||
Network::Bitcoin => "ssl://electrum.blockstream.info:50002",
|
Network::Bitcoin => "ssl://electrum.blockstream.info:50002",
|
||||||
@ -293,10 +296,7 @@ fn main() -> anyhow::Result<()> {
|
|||||||
changeset
|
changeset
|
||||||
};
|
};
|
||||||
|
|
||||||
ChangeSet {
|
(chain, indexed_tx_graph)
|
||||||
indexed_tx_graph,
|
|
||||||
chain,
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut db = db.lock().unwrap();
|
let mut db = db.lock().unwrap();
|
||||||
|
@ -6,9 +6,9 @@ use std::{
|
|||||||
|
|
||||||
use bdk_chain::{
|
use bdk_chain::{
|
||||||
bitcoin::{Address, Network, OutPoint, ScriptBuf, Txid},
|
bitcoin::{Address, Network, OutPoint, ScriptBuf, Txid},
|
||||||
indexed_tx_graph::IndexedTxGraph,
|
indexed_tx_graph::{self, IndexedTxGraph},
|
||||||
keychain::WalletChangeSet,
|
keychain,
|
||||||
local_chain::{CheckPoint, LocalChain},
|
local_chain::{self, CheckPoint, LocalChain},
|
||||||
Append, ConfirmationTimeAnchor,
|
Append, ConfirmationTimeAnchor,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -23,6 +23,11 @@ use example_cli::{
|
|||||||
const DB_MAGIC: &[u8] = b"bdk_example_esplora";
|
const DB_MAGIC: &[u8] = b"bdk_example_esplora";
|
||||||
const DB_PATH: &str = ".bdk_esplora_example.db";
|
const DB_PATH: &str = ".bdk_esplora_example.db";
|
||||||
|
|
||||||
|
type ChangeSet = (
|
||||||
|
local_chain::ChangeSet,
|
||||||
|
indexed_tx_graph::ChangeSet<ConfirmationTimeAnchor, keychain::ChangeSet<Keychain>>,
|
||||||
|
);
|
||||||
|
|
||||||
#[derive(Subcommand, Debug, Clone)]
|
#[derive(Subcommand, Debug, Clone)]
|
||||||
enum EsploraCommands {
|
enum EsploraCommands {
|
||||||
/// Scans the addresses in the wallet using the esplora API.
|
/// Scans the addresses in the wallet using the esplora API.
|
||||||
@ -60,22 +65,22 @@ pub struct ScanOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
let (args, keymap, index, db, init_changeset) = example_cli::init::<
|
let (args, keymap, index, db, init_changeset) =
|
||||||
EsploraCommands,
|
example_cli::init::<EsploraCommands, ChangeSet>(DB_MAGIC, DB_PATH)?;
|
||||||
WalletChangeSet<Keychain, ConfirmationTimeAnchor>,
|
|
||||||
>(DB_MAGIC, DB_PATH)?;
|
let (init_chain_changeset, init_indexed_tx_graph_changeset) = init_changeset;
|
||||||
|
|
||||||
// Contruct `IndexedTxGraph` and `LocalChain` with our initial changeset. They are wrapped in
|
// Contruct `IndexedTxGraph` and `LocalChain` with our initial changeset. They are wrapped in
|
||||||
// `Mutex` to display how they can be used in a multithreaded context. Technically the mutexes
|
// `Mutex` to display how they can be used in a multithreaded context. Technically the mutexes
|
||||||
// aren't strictly needed here.
|
// aren't strictly needed here.
|
||||||
let graph = Mutex::new({
|
let graph = Mutex::new({
|
||||||
let mut graph = IndexedTxGraph::new(index);
|
let mut graph = IndexedTxGraph::new(index);
|
||||||
graph.apply_changeset(init_changeset.indexed_tx_graph);
|
graph.apply_changeset(init_indexed_tx_graph_changeset);
|
||||||
graph
|
graph
|
||||||
});
|
});
|
||||||
let chain = Mutex::new({
|
let chain = Mutex::new({
|
||||||
let mut chain = LocalChain::default();
|
let mut chain = LocalChain::default();
|
||||||
chain.apply_changeset(&init_changeset.chain);
|
chain.apply_changeset(&init_chain_changeset);
|
||||||
chain
|
chain
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -307,18 +312,17 @@ fn main() -> anyhow::Result<()> {
|
|||||||
println!("missing block heights: {:?}", missing_block_heights);
|
println!("missing block heights: {:?}", missing_block_heights);
|
||||||
|
|
||||||
// Here, we actually fetch the missing blocks and create a `local_chain::Update`.
|
// Here, we actually fetch the missing blocks and create a `local_chain::Update`.
|
||||||
let chain_update = client
|
let chain_changeset = {
|
||||||
.update_local_chain(tip, missing_block_heights)
|
let chain_update = client
|
||||||
.context("scanning for blocks")?;
|
.update_local_chain(tip, missing_block_heights)
|
||||||
|
.context("scanning for blocks")?;
|
||||||
println!("new tip: {}", chain_update.tip.height());
|
println!("new tip: {}", chain_update.tip.height());
|
||||||
|
chain.lock().unwrap().apply_update(chain_update)?
|
||||||
|
};
|
||||||
|
|
||||||
// We persist the changes
|
// We persist the changes
|
||||||
let mut db = db.lock().unwrap();
|
let mut db = db.lock().unwrap();
|
||||||
db.stage(WalletChangeSet {
|
db.stage((chain_changeset, indexed_tx_graph_changeset));
|
||||||
chain: chain.lock().unwrap().apply_update(chain_update)?,
|
|
||||||
indexed_tx_graph: indexed_tx_graph_changeset,
|
|
||||||
});
|
|
||||||
db.commit()?;
|
db.commit()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user