[bdk_chain_redesign] Simplify TxIndex
This commit is contained in:
parent
a1172def7d
commit
a63ffe9739
@ -1,12 +1,12 @@
|
|||||||
use core::convert::Infallible;
|
use core::{convert::Infallible, ops::AddAssign};
|
||||||
|
|
||||||
use bitcoin::{OutPoint, Transaction, TxOut};
|
use bitcoin::{OutPoint, Script, Transaction, TxOut};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
keychain::Balance,
|
keychain::Balance,
|
||||||
sparse_chain::ChainPosition,
|
sparse_chain::ChainPosition,
|
||||||
tx_graph::{Additions, TxGraph, TxNode},
|
tx_graph::{Additions, TxGraph, TxNode},
|
||||||
BlockAnchor, ChainOracle, FullTxOut, ObservedIn, TxIndex, TxIndexAdditions,
|
BlockAnchor, ChainOracle, FullTxOut, ObservedIn, TxIndex,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// An outwards-facing view of a transaction that is part of the *best chain*'s history.
|
/// An outwards-facing view of a transaction that is part of the *best chain*'s history.
|
||||||
@ -18,46 +18,37 @@ pub struct TxInChain<'a, T, A> {
|
|||||||
pub tx: TxNode<'a, T, A>,
|
pub tx: TxNode<'a, T, A>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An outwards-facing view of a relevant txout that is part of the *best chain*'s history.
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
|
||||||
pub struct TxOutInChain<'a, I, A> {
|
|
||||||
/// The custom index of the txout's script pubkey.
|
|
||||||
pub spk_index: &'a I,
|
|
||||||
/// The full txout.
|
|
||||||
pub txout: FullTxOut<ObservedIn<&'a A>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A structure that represents changes to an [`IndexedTxGraph`].
|
/// A structure that represents changes to an [`IndexedTxGraph`].
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub struct IndexedAdditions<A, D> {
|
pub struct IndexedAdditions<A, IA> {
|
||||||
/// [`TxGraph`] additions.
|
/// [`TxGraph`] additions.
|
||||||
pub graph_additions: Additions<A>,
|
pub graph_additions: Additions<A>,
|
||||||
/// [`TxIndex`] additions.
|
/// [`TxIndex`] additions.
|
||||||
pub index_delta: D,
|
pub index_additions: IA,
|
||||||
/// Last block height witnessed (if any).
|
/// Last block height witnessed (if any).
|
||||||
pub last_height: Option<u32>,
|
pub last_height: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, D: Default> Default for IndexedAdditions<A, D> {
|
impl<A, IA: Default> Default for IndexedAdditions<A, IA> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
graph_additions: Default::default(),
|
graph_additions: Default::default(),
|
||||||
index_delta: Default::default(),
|
index_additions: Default::default(),
|
||||||
last_height: None,
|
last_height: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A: BlockAnchor, D: TxIndexAdditions> TxIndexAdditions for IndexedAdditions<A, D> {
|
impl<A: BlockAnchor, IA: AddAssign> AddAssign for IndexedAdditions<A, IA> {
|
||||||
fn append_additions(&mut self, other: Self) {
|
fn add_assign(&mut self, rhs: Self) {
|
||||||
let Self {
|
let Self {
|
||||||
graph_additions,
|
graph_additions,
|
||||||
index_delta,
|
index_additions: index_delta,
|
||||||
last_height,
|
last_height,
|
||||||
} = other;
|
} = rhs;
|
||||||
self.graph_additions.append(graph_additions);
|
self.graph_additions.append(graph_additions);
|
||||||
self.index_delta.append_additions(index_delta);
|
self.index_additions += index_delta;
|
||||||
if self.last_height < last_height {
|
if self.last_height < last_height {
|
||||||
let last_height =
|
let last_height =
|
||||||
last_height.expect("must exist as it is larger than self.last_height");
|
last_height.expect("must exist as it is larger than self.last_height");
|
||||||
@ -102,11 +93,11 @@ impl<A: BlockAnchor, I: TxIndex> IndexedTxGraph<A, I> {
|
|||||||
pub fn apply_additions(&mut self, additions: IndexedAdditions<A, I::Additions>) {
|
pub fn apply_additions(&mut self, additions: IndexedAdditions<A, I::Additions>) {
|
||||||
let IndexedAdditions {
|
let IndexedAdditions {
|
||||||
graph_additions,
|
graph_additions,
|
||||||
index_delta,
|
index_additions,
|
||||||
last_height,
|
last_height,
|
||||||
} = additions;
|
} = additions;
|
||||||
|
|
||||||
self.index.apply_additions(index_delta);
|
self.index.apply_additions(index_additions);
|
||||||
|
|
||||||
for tx in &graph_additions.tx {
|
for tx in &graph_additions.tx {
|
||||||
self.index.index_tx(tx);
|
self.index.index_tx(tx);
|
||||||
@ -122,16 +113,23 @@ impl<A: BlockAnchor, I: TxIndex> IndexedTxGraph<A, I> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert a block height that the chain source has scanned up to.
|
fn insert_height_internal(&mut self, tip: u32) -> Option<u32> {
|
||||||
pub fn insert_height(&mut self, tip: u32) -> IndexedAdditions<A, I::Additions> {
|
|
||||||
if self.last_height < tip {
|
if self.last_height < tip {
|
||||||
self.last_height = tip;
|
self.last_height = tip;
|
||||||
IndexedAdditions {
|
Some(tip)
|
||||||
last_height: Some(tip),
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
IndexedAdditions::default()
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Insert a block height that the chain source has scanned up to.
|
||||||
|
pub fn insert_height(&mut self, tip: u32) -> IndexedAdditions<A, I::Additions>
|
||||||
|
where
|
||||||
|
I::Additions: Default,
|
||||||
|
{
|
||||||
|
IndexedAdditions {
|
||||||
|
last_height: self.insert_height_internal(tip),
|
||||||
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,12 +140,12 @@ impl<A: BlockAnchor, I: TxIndex> IndexedTxGraph<A, I> {
|
|||||||
txout: &TxOut,
|
txout: &TxOut,
|
||||||
observation: ObservedIn<A>,
|
observation: ObservedIn<A>,
|
||||||
) -> IndexedAdditions<A, I::Additions> {
|
) -> IndexedAdditions<A, I::Additions> {
|
||||||
let mut additions = match &observation {
|
let last_height = match &observation {
|
||||||
ObservedIn::Block(anchor) => self.insert_height(anchor.anchor_block().height),
|
ObservedIn::Block(anchor) => self.insert_height_internal(anchor.anchor_block().height),
|
||||||
ObservedIn::Mempool(_) => IndexedAdditions::default(),
|
ObservedIn::Mempool(_) => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
additions.append_additions(IndexedAdditions {
|
IndexedAdditions {
|
||||||
graph_additions: {
|
graph_additions: {
|
||||||
let mut graph_additions = self.graph.insert_txout(outpoint, txout.clone());
|
let mut graph_additions = self.graph.insert_txout(outpoint, txout.clone());
|
||||||
graph_additions.append(match observation {
|
graph_additions.append(match observation {
|
||||||
@ -158,11 +156,9 @@ impl<A: BlockAnchor, I: TxIndex> IndexedTxGraph<A, I> {
|
|||||||
});
|
});
|
||||||
graph_additions
|
graph_additions
|
||||||
},
|
},
|
||||||
index_delta: <I as TxIndex>::index_txout(&mut self.index, outpoint, txout),
|
index_additions: <I as TxIndex>::index_txout(&mut self.index, outpoint, txout),
|
||||||
last_height: None,
|
last_height,
|
||||||
});
|
}
|
||||||
|
|
||||||
additions
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_tx(
|
pub fn insert_tx(
|
||||||
@ -172,12 +168,12 @@ impl<A: BlockAnchor, I: TxIndex> IndexedTxGraph<A, I> {
|
|||||||
) -> IndexedAdditions<A, I::Additions> {
|
) -> IndexedAdditions<A, I::Additions> {
|
||||||
let txid = tx.txid();
|
let txid = tx.txid();
|
||||||
|
|
||||||
let mut additions = match &observation {
|
let last_height = match &observation {
|
||||||
ObservedIn::Block(anchor) => self.insert_height(anchor.anchor_block().height),
|
ObservedIn::Block(anchor) => self.insert_height_internal(anchor.anchor_block().height),
|
||||||
ObservedIn::Mempool(_) => IndexedAdditions::default(),
|
ObservedIn::Mempool(_) => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
additions.append_additions(IndexedAdditions {
|
IndexedAdditions {
|
||||||
graph_additions: {
|
graph_additions: {
|
||||||
let mut graph_additions = self.graph.insert_tx(tx.clone());
|
let mut graph_additions = self.graph.insert_tx(tx.clone());
|
||||||
graph_additions.append(match observation {
|
graph_additions.append(match observation {
|
||||||
@ -186,11 +182,9 @@ impl<A: BlockAnchor, I: TxIndex> IndexedTxGraph<A, I> {
|
|||||||
});
|
});
|
||||||
graph_additions
|
graph_additions
|
||||||
},
|
},
|
||||||
index_delta: <I as TxIndex>::index_tx(&mut self.index, tx),
|
index_additions: <I as TxIndex>::index_tx(&mut self.index, tx),
|
||||||
last_height: None,
|
last_height,
|
||||||
});
|
}
|
||||||
|
|
||||||
additions
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn filter_and_insert_txs<'t, T>(
|
pub fn filter_and_insert_txs<'t, T>(
|
||||||
@ -200,6 +194,7 @@ impl<A: BlockAnchor, I: TxIndex> IndexedTxGraph<A, I> {
|
|||||||
) -> IndexedAdditions<A, I::Additions>
|
) -> IndexedAdditions<A, I::Additions>
|
||||||
where
|
where
|
||||||
T: Iterator<Item = &'t Transaction>,
|
T: Iterator<Item = &'t Transaction>,
|
||||||
|
I::Additions: Default + AddAssign,
|
||||||
{
|
{
|
||||||
txs.filter_map(|tx| {
|
txs.filter_map(|tx| {
|
||||||
if self.index.is_tx_relevant(tx) {
|
if self.index.is_tx_relevant(tx) {
|
||||||
@ -209,7 +204,7 @@ impl<A: BlockAnchor, I: TxIndex> IndexedTxGraph<A, I> {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.fold(IndexedAdditions::default(), |mut acc, other| {
|
.fold(IndexedAdditions::default(), |mut acc, other| {
|
||||||
acc.append_additions(other);
|
acc += other;
|
||||||
acc
|
acc
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -252,50 +247,47 @@ impl<A: BlockAnchor, I: TxIndex> IndexedTxGraph<A, I> {
|
|||||||
pub fn try_list_chain_txouts<'a, C>(
|
pub fn try_list_chain_txouts<'a, C>(
|
||||||
&'a self,
|
&'a self,
|
||||||
chain: C,
|
chain: C,
|
||||||
) -> impl Iterator<Item = Result<TxOutInChain<'a, I::SpkIndex, A>, C::Error>>
|
) -> impl Iterator<Item = Result<FullTxOut<ObservedIn<A>>, C::Error>> + 'a
|
||||||
where
|
where
|
||||||
C: ChainOracle + 'a,
|
C: ChainOracle + 'a,
|
||||||
ObservedIn<A>: ChainPosition,
|
ObservedIn<A>: ChainPosition,
|
||||||
{
|
{
|
||||||
self.index.relevant_txouts().iter().filter_map(
|
self.graph
|
||||||
move |(op, (spk_i, txout))| -> Option<Result<_, C::Error>> {
|
.all_txouts()
|
||||||
|
.filter(|(_, txo)| self.index.is_spk_owned(&txo.script_pubkey))
|
||||||
|
.filter_map(move |(op, txout)| -> Option<Result<_, C::Error>> {
|
||||||
let graph_tx = self.graph.get_tx(op.txid)?;
|
let graph_tx = self.graph.get_tx(op.txid)?;
|
||||||
|
|
||||||
let is_on_coinbase = graph_tx.is_coin_base();
|
let is_on_coinbase = graph_tx.is_coin_base();
|
||||||
|
|
||||||
let chain_position = match self.graph.try_get_chain_position(&chain, op.txid) {
|
let chain_position = match self.graph.try_get_chain_position(&chain, op.txid) {
|
||||||
Ok(Some(observed_at)) => observed_at,
|
Ok(Some(observed_at)) => observed_at.into_owned(),
|
||||||
Ok(None) => return None,
|
Ok(None) => return None,
|
||||||
Err(err) => return Some(Err(err)),
|
Err(err) => return Some(Err(err)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let spent_by = match self.graph.try_get_spend_in_chain(&chain, *op) {
|
let spent_by = match self.graph.try_get_spend_in_chain(&chain, op) {
|
||||||
Ok(spent_by) => spent_by,
|
Ok(Some((obs, txid))) => Some((obs.into_owned(), txid)),
|
||||||
|
Ok(None) => None,
|
||||||
Err(err) => return Some(Err(err)),
|
Err(err) => return Some(Err(err)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let full_txout = FullTxOut {
|
let full_txout = FullTxOut {
|
||||||
outpoint: *op,
|
outpoint: op,
|
||||||
txout: txout.clone(),
|
txout: txout.clone(),
|
||||||
chain_position,
|
chain_position,
|
||||||
spent_by,
|
spent_by,
|
||||||
is_on_coinbase,
|
is_on_coinbase,
|
||||||
};
|
};
|
||||||
|
|
||||||
let txout_in_chain = TxOutInChain {
|
Some(Ok(full_txout))
|
||||||
spk_index: spk_i,
|
})
|
||||||
txout: full_txout,
|
|
||||||
};
|
|
||||||
|
|
||||||
Some(Ok(txout_in_chain))
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_chain_txouts<'a, C>(
|
pub fn list_chain_txouts<'a, C>(
|
||||||
&'a self,
|
&'a self,
|
||||||
chain: C,
|
chain: C,
|
||||||
) -> impl Iterator<Item = TxOutInChain<'a, I::SpkIndex, A>>
|
) -> impl Iterator<Item = FullTxOut<ObservedIn<A>>> + 'a
|
||||||
where
|
where
|
||||||
C: ChainOracle<Error = Infallible> + 'a,
|
C: ChainOracle<Error = Infallible> + 'a,
|
||||||
ObservedIn<A>: ChainPosition,
|
ObservedIn<A>: ChainPosition,
|
||||||
@ -308,19 +300,19 @@ impl<A: BlockAnchor, I: TxIndex> IndexedTxGraph<A, I> {
|
|||||||
pub fn try_list_chain_utxos<'a, C>(
|
pub fn try_list_chain_utxos<'a, C>(
|
||||||
&'a self,
|
&'a self,
|
||||||
chain: C,
|
chain: C,
|
||||||
) -> impl Iterator<Item = Result<TxOutInChain<'a, I::SpkIndex, A>, C::Error>>
|
) -> impl Iterator<Item = Result<FullTxOut<ObservedIn<A>>, C::Error>> + 'a
|
||||||
where
|
where
|
||||||
C: ChainOracle + 'a,
|
C: ChainOracle + 'a,
|
||||||
ObservedIn<A>: ChainPosition,
|
ObservedIn<A>: ChainPosition,
|
||||||
{
|
{
|
||||||
self.try_list_chain_txouts(chain)
|
self.try_list_chain_txouts(chain)
|
||||||
.filter(|r| !matches!(r, Ok(txo) if txo.txout.spent_by.is_none()))
|
.filter(|r| !matches!(r, Ok(txo) if txo.spent_by.is_none()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_chain_utxos<'a, C>(
|
pub fn list_chain_utxos<'a, C>(
|
||||||
&'a self,
|
&'a self,
|
||||||
chain: C,
|
chain: C,
|
||||||
) -> impl Iterator<Item = TxOutInChain<'a, I::SpkIndex, A>>
|
) -> impl Iterator<Item = FullTxOut<ObservedIn<A>>> + 'a
|
||||||
where
|
where
|
||||||
C: ChainOracle<Error = Infallible> + 'a,
|
C: ChainOracle<Error = Infallible> + 'a,
|
||||||
ObservedIn<A>: ChainPosition,
|
ObservedIn<A>: ChainPosition,
|
||||||
@ -338,7 +330,7 @@ impl<A: BlockAnchor, I: TxIndex> IndexedTxGraph<A, I> {
|
|||||||
where
|
where
|
||||||
C: ChainOracle,
|
C: ChainOracle,
|
||||||
ObservedIn<A>: ChainPosition + Clone,
|
ObservedIn<A>: ChainPosition + Clone,
|
||||||
F: FnMut(&I::SpkIndex) -> bool,
|
F: FnMut(&Script) -> bool,
|
||||||
{
|
{
|
||||||
let mut immature = 0;
|
let mut immature = 0;
|
||||||
let mut trusted_pending = 0;
|
let mut trusted_pending = 0;
|
||||||
@ -346,8 +338,7 @@ impl<A: BlockAnchor, I: TxIndex> IndexedTxGraph<A, I> {
|
|||||||
let mut confirmed = 0;
|
let mut confirmed = 0;
|
||||||
|
|
||||||
for res in self.try_list_chain_txouts(&chain) {
|
for res in self.try_list_chain_txouts(&chain) {
|
||||||
let TxOutInChain { spk_index, txout } = res?;
|
let txout = res?;
|
||||||
let txout = txout.into_owned();
|
|
||||||
|
|
||||||
match &txout.chain_position {
|
match &txout.chain_position {
|
||||||
ObservedIn::Block(_) => {
|
ObservedIn::Block(_) => {
|
||||||
@ -360,7 +351,7 @@ impl<A: BlockAnchor, I: TxIndex> IndexedTxGraph<A, I> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ObservedIn::Mempool(_) => {
|
ObservedIn::Mempool(_) => {
|
||||||
if should_trust(spk_index) {
|
if should_trust(&txout.txout.script_pubkey) {
|
||||||
trusted_pending += txout.txout.value;
|
trusted_pending += txout.txout.value;
|
||||||
} else {
|
} else {
|
||||||
untrusted_pending += txout.txout.value;
|
untrusted_pending += txout.txout.value;
|
||||||
@ -381,7 +372,7 @@ impl<A: BlockAnchor, I: TxIndex> IndexedTxGraph<A, I> {
|
|||||||
where
|
where
|
||||||
C: ChainOracle<Error = Infallible>,
|
C: ChainOracle<Error = Infallible>,
|
||||||
ObservedIn<A>: ChainPosition + Clone,
|
ObservedIn<A>: ChainPosition + Clone,
|
||||||
F: FnMut(&I::SpkIndex) -> bool,
|
F: FnMut(&Script) -> bool,
|
||||||
{
|
{
|
||||||
self.try_balance(chain, tip, should_trust)
|
self.try_balance(chain, tip, should_trust)
|
||||||
.expect("error is infallible")
|
.expect("error is infallible")
|
||||||
@ -393,8 +384,8 @@ impl<A: BlockAnchor, I: TxIndex> IndexedTxGraph<A, I> {
|
|||||||
ObservedIn<A>: ChainPosition + Clone,
|
ObservedIn<A>: ChainPosition + Clone,
|
||||||
{
|
{
|
||||||
let mut sum = 0;
|
let mut sum = 0;
|
||||||
for res in self.try_list_chain_txouts(chain) {
|
for txo_res in self.try_list_chain_txouts(chain) {
|
||||||
let txo = res?.txout.into_owned();
|
let txo = txo_res?;
|
||||||
if txo.is_spendable_at(height) {
|
if txo.is_spendable_at(height) {
|
||||||
sum += txo.txout.value;
|
sum += txo.txout.value;
|
||||||
}
|
}
|
||||||
|
@ -14,12 +14,14 @@
|
|||||||
//! [`KeychainChangeSet`]s.
|
//! [`KeychainChangeSet`]s.
|
||||||
//!
|
//!
|
||||||
//! [`SpkTxOutIndex`]: crate::SpkTxOutIndex
|
//! [`SpkTxOutIndex`]: crate::SpkTxOutIndex
|
||||||
|
use core::ops::AddAssign;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
chain_graph::{self, ChainGraph},
|
chain_graph::{self, ChainGraph},
|
||||||
collections::BTreeMap,
|
collections::BTreeMap,
|
||||||
sparse_chain::ChainPosition,
|
sparse_chain::ChainPosition,
|
||||||
tx_graph::TxGraph,
|
tx_graph::TxGraph,
|
||||||
ForEachTxOut, TxIndexAdditions,
|
ForEachTxOut,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "miniscript")]
|
#[cfg(feature = "miniscript")]
|
||||||
@ -85,9 +87,9 @@ impl<K: Ord> DerivationAdditions<K> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K: Ord> TxIndexAdditions for DerivationAdditions<K> {
|
impl<K: Ord> AddAssign for DerivationAdditions<K> {
|
||||||
fn append_additions(&mut self, other: Self) {
|
fn add_assign(&mut self, rhs: Self) {
|
||||||
self.append(other)
|
self.append(rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,8 +91,6 @@ impl<K> Deref for KeychainTxOutIndex<K> {
|
|||||||
impl<K: Clone + Ord + Debug + 'static> TxIndex for KeychainTxOutIndex<K> {
|
impl<K: Clone + Ord + Debug + 'static> TxIndex for KeychainTxOutIndex<K> {
|
||||||
type Additions = DerivationAdditions<K>;
|
type Additions = DerivationAdditions<K>;
|
||||||
|
|
||||||
type SpkIndex = (K, u32);
|
|
||||||
|
|
||||||
fn index_txout(&mut self, outpoint: OutPoint, txout: &TxOut) -> Self::Additions {
|
fn index_txout(&mut self, outpoint: OutPoint, txout: &TxOut) -> Self::Additions {
|
||||||
self.scan_txout(outpoint, txout)
|
self.scan_txout(outpoint, txout)
|
||||||
}
|
}
|
||||||
@ -109,8 +107,8 @@ impl<K: Clone + Ord + Debug + 'static> TxIndex for KeychainTxOutIndex<K> {
|
|||||||
self.is_relevant(tx)
|
self.is_relevant(tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn relevant_txouts(&self) -> &BTreeMap<OutPoint, (Self::SpkIndex, TxOut)> {
|
fn is_spk_owned(&self, spk: &Script) -> bool {
|
||||||
self.inner.relevant_txouts()
|
self.index_of_spk(spk).is_some()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,19 +53,16 @@ impl<I> Default for SpkTxOutIndex<I> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<I: Clone + Ord + 'static> TxIndex for SpkTxOutIndex<I> {
|
impl<I: Clone + Ord + 'static> TxIndex for SpkTxOutIndex<I> {
|
||||||
type Additions = BTreeSet<I>;
|
type Additions = ();
|
||||||
|
|
||||||
type SpkIndex = I;
|
|
||||||
|
|
||||||
fn index_txout(&mut self, outpoint: OutPoint, txout: &TxOut) -> Self::Additions {
|
fn index_txout(&mut self, outpoint: OutPoint, txout: &TxOut) -> Self::Additions {
|
||||||
self.scan_txout(outpoint, txout)
|
self.scan_txout(outpoint, txout);
|
||||||
.cloned()
|
Default::default()
|
||||||
.into_iter()
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn index_tx(&mut self, tx: &Transaction) -> Self::Additions {
|
fn index_tx(&mut self, tx: &Transaction) -> Self::Additions {
|
||||||
self.scan(tx)
|
self.scan(tx);
|
||||||
|
Default::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_additions(&mut self, _additions: Self::Additions) {
|
fn apply_additions(&mut self, _additions: Self::Additions) {
|
||||||
@ -76,8 +73,8 @@ impl<I: Clone + Ord + 'static> TxIndex for SpkTxOutIndex<I> {
|
|||||||
self.is_relevant(tx)
|
self.is_relevant(tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn relevant_txouts(&self) -> &BTreeMap<OutPoint, (Self::SpkIndex, TxOut)> {
|
fn is_spk_owned(&self, spk: &Script) -> bool {
|
||||||
&self.txouts
|
self.index_of_spk(spk).is_some()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use alloc::collections::{BTreeMap, BTreeSet};
|
use bitcoin::{Block, BlockHash, OutPoint, Script, Transaction, TxOut};
|
||||||
use bitcoin::{Block, BlockHash, OutPoint, Transaction, TxOut};
|
|
||||||
|
|
||||||
use crate::BlockId;
|
use crate::BlockId;
|
||||||
|
|
||||||
@ -89,41 +88,16 @@ impl<C: ChainOracle> ChainOracle for &C {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents changes to a [`TxIndex`] implementation.
|
|
||||||
pub trait TxIndexAdditions: Default {
|
|
||||||
/// Append `other` on top of `self`.
|
|
||||||
fn append_additions(&mut self, other: Self);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I: Ord> TxIndexAdditions for BTreeSet<I> {
|
|
||||||
fn append_additions(&mut self, mut other: Self) {
|
|
||||||
self.append(&mut other);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents an index of transaction data.
|
/// Represents an index of transaction data.
|
||||||
pub trait TxIndex {
|
pub trait TxIndex {
|
||||||
/// The resultant "additions" when new transaction data is indexed.
|
/// The resultant "additions" when new transaction data is indexed.
|
||||||
type Additions: TxIndexAdditions;
|
type Additions;
|
||||||
|
|
||||||
type SpkIndex: Ord;
|
|
||||||
|
|
||||||
/// Scan and index the given `outpoint` and `txout`.
|
/// Scan and index the given `outpoint` and `txout`.
|
||||||
fn index_txout(&mut self, outpoint: OutPoint, txout: &TxOut) -> Self::Additions;
|
fn index_txout(&mut self, outpoint: OutPoint, txout: &TxOut) -> Self::Additions;
|
||||||
|
|
||||||
/// Scan and index the given transaction.
|
/// Scan and index the given transaction.
|
||||||
fn index_tx(&mut self, tx: &Transaction) -> Self::Additions {
|
fn index_tx(&mut self, tx: &Transaction) -> Self::Additions;
|
||||||
let txid = tx.txid();
|
|
||||||
tx.output
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(vout, txout)| self.index_txout(OutPoint::new(txid, vout as _), txout))
|
|
||||||
.reduce(|mut acc, other| {
|
|
||||||
acc.append_additions(other);
|
|
||||||
acc
|
|
||||||
})
|
|
||||||
.unwrap_or_default()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Apply additions to itself.
|
/// Apply additions to itself.
|
||||||
fn apply_additions(&mut self, additions: Self::Additions);
|
fn apply_additions(&mut self, additions: Self::Additions);
|
||||||
@ -132,6 +106,6 @@ pub trait TxIndex {
|
|||||||
/// spends an already-indexed outpoint that we have previously indexed.
|
/// spends an already-indexed outpoint that we have previously indexed.
|
||||||
fn is_tx_relevant(&self, tx: &Transaction) -> bool;
|
fn is_tx_relevant(&self, tx: &Transaction) -> bool;
|
||||||
|
|
||||||
/// Lists all relevant txouts known by the index.
|
/// Returns whether the script pubkey is owned by us.
|
||||||
fn relevant_txouts(&self) -> &BTreeMap<OutPoint, (Self::SpkIndex, TxOut)>;
|
fn is_spk_owned(&self, spk: &Script) -> bool;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user