[bdk_chain_redesign] Revert some API changes
Methods of old structures that return transaction(s) no longer return `TxNode`, but `Transaction` as done previously. `TxInGraph` is renamed to `TxNode`, while the internal `TxNode` is renamed to `TxNodeInternal`.
This commit is contained in:
parent
8c906170c9
commit
a1172def7d
@ -23,9 +23,7 @@ pub use bdk_chain::keychain::Balance;
|
|||||||
use bdk_chain::{
|
use bdk_chain::{
|
||||||
chain_graph,
|
chain_graph,
|
||||||
keychain::{persist, KeychainChangeSet, KeychainScan, KeychainTracker},
|
keychain::{persist, KeychainChangeSet, KeychainScan, KeychainTracker},
|
||||||
sparse_chain,
|
sparse_chain, BlockId, ConfirmationTime,
|
||||||
tx_graph::TxInGraph,
|
|
||||||
BlockId, ConfirmationTime,
|
|
||||||
};
|
};
|
||||||
use bitcoin::consensus::encode::serialize;
|
use bitcoin::consensus::encode::serialize;
|
||||||
use bitcoin::secp256k1::Secp256k1;
|
use bitcoin::secp256k1::Secp256k1;
|
||||||
@ -455,11 +453,7 @@ impl<D> Wallet<D> {
|
|||||||
let fee = inputs.map(|inputs| inputs.saturating_sub(outputs));
|
let fee = inputs.map(|inputs| inputs.saturating_sub(outputs));
|
||||||
|
|
||||||
Some(TransactionDetails {
|
Some(TransactionDetails {
|
||||||
transaction: if include_raw {
|
transaction: if include_raw { Some(tx.clone()) } else { None },
|
||||||
Some(tx.tx.clone())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
},
|
|
||||||
txid,
|
txid,
|
||||||
received,
|
received,
|
||||||
sent,
|
sent,
|
||||||
@ -524,8 +518,7 @@ impl<D> Wallet<D> {
|
|||||||
/// unconfirmed transactions last.
|
/// unconfirmed transactions last.
|
||||||
pub fn transactions(
|
pub fn transactions(
|
||||||
&self,
|
&self,
|
||||||
) -> impl DoubleEndedIterator<Item = (ConfirmationTime, TxInGraph<'_, Transaction, ()>)> + '_
|
) -> impl DoubleEndedIterator<Item = (ConfirmationTime, &Transaction)> + '_ {
|
||||||
{
|
|
||||||
self.keychain_tracker
|
self.keychain_tracker
|
||||||
.chain_graph()
|
.chain_graph()
|
||||||
.transactions_in_chain()
|
.transactions_in_chain()
|
||||||
@ -1034,7 +1027,7 @@ impl<D> Wallet<D> {
|
|||||||
Some((ConfirmationTime::Confirmed { .. }, _tx)) => {
|
Some((ConfirmationTime::Confirmed { .. }, _tx)) => {
|
||||||
return Err(Error::TransactionConfirmed)
|
return Err(Error::TransactionConfirmed)
|
||||||
}
|
}
|
||||||
Some((_, tx)) => tx.tx.clone(),
|
Some((_, tx)) => tx.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if !tx
|
if !tx
|
||||||
@ -1092,7 +1085,7 @@ impl<D> Wallet<D> {
|
|||||||
outpoint: txin.previous_output,
|
outpoint: txin.previous_output,
|
||||||
psbt_input: Box::new(psbt::Input {
|
psbt_input: Box::new(psbt::Input {
|
||||||
witness_utxo: Some(txout.clone()),
|
witness_utxo: Some(txout.clone()),
|
||||||
non_witness_utxo: Some(prev_tx.tx.clone()),
|
non_witness_utxo: Some(prev_tx.clone()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
@ -1620,7 +1613,7 @@ impl<D> Wallet<D> {
|
|||||||
psbt_input.witness_utxo = Some(prev_tx.output[prev_output.vout as usize].clone());
|
psbt_input.witness_utxo = Some(prev_tx.output[prev_output.vout as usize].clone());
|
||||||
}
|
}
|
||||||
if !desc.is_taproot() && (!desc.is_witness() || !only_witness_utxo) {
|
if !desc.is_taproot() && (!desc.is_witness() || !only_witness_utxo) {
|
||||||
psbt_input.non_witness_utxo = Some(prev_tx.tx.clone());
|
psbt_input.non_witness_utxo = Some(prev_tx.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(psbt_input)
|
Ok(psbt_input)
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
collections::HashSet,
|
collections::HashSet,
|
||||||
sparse_chain::{self, ChainPosition, SparseChain},
|
sparse_chain::{self, ChainPosition, SparseChain},
|
||||||
tx_graph::{self, TxGraph, TxInGraph},
|
tx_graph::{self, TxGraph},
|
||||||
BlockId, ForEachTxOut, FullTxOut, TxHeight,
|
BlockId, ForEachTxOut, FullTxOut, TxHeight,
|
||||||
};
|
};
|
||||||
use alloc::{string::ToString, vec::Vec};
|
use alloc::{string::ToString, vec::Vec};
|
||||||
@ -84,11 +84,9 @@ where
|
|||||||
pub fn new(chain: SparseChain<P>, graph: TxGraph) -> Result<Self, NewError<P>> {
|
pub fn new(chain: SparseChain<P>, graph: TxGraph) -> Result<Self, NewError<P>> {
|
||||||
let mut missing = HashSet::default();
|
let mut missing = HashSet::default();
|
||||||
for (pos, txid) in chain.txids() {
|
for (pos, txid) in chain.txids() {
|
||||||
if let Some(graphed_tx) = graph.get_tx(*txid) {
|
if let Some(tx) = graph.get_tx(*txid) {
|
||||||
let conflict = graph
|
let conflict = graph
|
||||||
.walk_conflicts(graphed_tx.tx, |_, txid| {
|
.walk_conflicts(tx, |_, txid| Some((chain.tx_position(txid)?.clone(), txid)))
|
||||||
Some((chain.tx_position(txid)?.clone(), txid))
|
|
||||||
})
|
|
||||||
.next();
|
.next();
|
||||||
if let Some((conflict_pos, conflict)) = conflict {
|
if let Some((conflict_pos, conflict)) = conflict {
|
||||||
return Err(NewError::Conflict {
|
return Err(NewError::Conflict {
|
||||||
@ -145,7 +143,7 @@ where
|
|||||||
match self.chain.tx_position(*txid) {
|
match self.chain.tx_position(*txid) {
|
||||||
Some(original_pos) => {
|
Some(original_pos) => {
|
||||||
if original_pos != pos {
|
if original_pos != pos {
|
||||||
let graphed_tx = self
|
let tx = self
|
||||||
.graph
|
.graph
|
||||||
.get_tx(*txid)
|
.get_tx(*txid)
|
||||||
.expect("tx must exist as it is referenced in sparsechain")
|
.expect("tx must exist as it is referenced in sparsechain")
|
||||||
@ -153,7 +151,7 @@ where
|
|||||||
let _ = inflated_chain
|
let _ = inflated_chain
|
||||||
.insert_tx(*txid, pos.clone())
|
.insert_tx(*txid, pos.clone())
|
||||||
.expect("must insert since this was already in update");
|
.expect("must insert since this was already in update");
|
||||||
let _ = inflated_graph.insert_tx(graphed_tx.tx.clone());
|
let _ = inflated_graph.insert_tx(tx.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
@ -212,10 +210,10 @@ where
|
|||||||
///
|
///
|
||||||
/// This does not necessarily mean that it is *confirmed* in the blockchain; it might just be in
|
/// This does not necessarily mean that it is *confirmed* in the blockchain; it might just be in
|
||||||
/// the unconfirmed transaction list within the [`SparseChain`].
|
/// the unconfirmed transaction list within the [`SparseChain`].
|
||||||
pub fn get_tx_in_chain(&self, txid: Txid) -> Option<(&P, TxInGraph<'_, Transaction, ()>)> {
|
pub fn get_tx_in_chain(&self, txid: Txid) -> Option<(&P, &Transaction)> {
|
||||||
let position = self.chain.tx_position(txid)?;
|
let position = self.chain.tx_position(txid)?;
|
||||||
let graphed_tx = self.graph.get_tx(txid).expect("must exist");
|
let tx = self.graph.get_tx(txid).expect("must exist");
|
||||||
Some((position, graphed_tx))
|
Some((position, tx))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines the changes required to insert a transaction into the inner [`ChainGraph`] and
|
/// Determines the changes required to insert a transaction into the inner [`ChainGraph`] and
|
||||||
@ -348,7 +346,7 @@ where
|
|||||||
None => continue,
|
None => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut full_tx = self.graph.get_tx(txid).map(|tx| tx.tx);
|
let mut full_tx = self.graph.get_tx(txid);
|
||||||
|
|
||||||
if full_tx.is_none() {
|
if full_tx.is_none() {
|
||||||
full_tx = changeset.graph.tx.iter().find(|tx| tx.txid() == txid)
|
full_tx = changeset.graph.tx.iter().find(|tx| tx.txid() == txid)
|
||||||
@ -428,9 +426,7 @@ where
|
|||||||
|
|
||||||
/// Iterate over the full transactions and their position in the chain ordered by their position
|
/// Iterate over the full transactions and their position in the chain ordered by their position
|
||||||
/// in ascending order.
|
/// in ascending order.
|
||||||
pub fn transactions_in_chain(
|
pub fn transactions_in_chain(&self) -> impl DoubleEndedIterator<Item = (&P, &Transaction)> {
|
||||||
&self,
|
|
||||||
) -> impl DoubleEndedIterator<Item = (&P, TxInGraph<'_, Transaction, ()>)> {
|
|
||||||
self.chain
|
self.chain
|
||||||
.txids()
|
.txids()
|
||||||
.map(move |(pos, txid)| (pos, self.graph.get_tx(*txid).expect("must exist")))
|
.map(move |(pos, txid)| (pos, self.graph.get_tx(*txid).expect("must exist")))
|
||||||
|
@ -5,7 +5,7 @@ use bitcoin::{OutPoint, Transaction, TxOut};
|
|||||||
use crate::{
|
use crate::{
|
||||||
keychain::Balance,
|
keychain::Balance,
|
||||||
sparse_chain::ChainPosition,
|
sparse_chain::ChainPosition,
|
||||||
tx_graph::{Additions, TxGraph, TxInGraph},
|
tx_graph::{Additions, TxGraph, TxNode},
|
||||||
BlockAnchor, ChainOracle, FullTxOut, ObservedIn, TxIndex, TxIndexAdditions,
|
BlockAnchor, ChainOracle, FullTxOut, ObservedIn, TxIndex, TxIndexAdditions,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ pub struct TxInChain<'a, T, A> {
|
|||||||
/// Where the transaction is observed (in a block or in mempool).
|
/// Where the transaction is observed (in a block or in mempool).
|
||||||
pub observed_in: ObservedIn<&'a A>,
|
pub observed_in: ObservedIn<&'a A>,
|
||||||
/// The transaction with anchors and last seen timestamp.
|
/// The transaction with anchors and last seen timestamp.
|
||||||
pub tx: TxInGraph<'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.
|
/// An outwards-facing view of a relevant txout that is part of the *best chain*'s history.
|
||||||
|
@ -71,7 +71,7 @@ use core::{
|
|||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct TxGraph<A = ()> {
|
pub struct TxGraph<A = ()> {
|
||||||
// all transactions that the graph is aware of in format: `(tx_node, tx_anchors, tx_last_seen)`
|
// all transactions that the graph is aware of in format: `(tx_node, tx_anchors, tx_last_seen)`
|
||||||
txs: HashMap<Txid, (TxNode, BTreeSet<A>, u64)>,
|
txs: HashMap<Txid, (TxNodeInternal, BTreeSet<A>, u64)>,
|
||||||
spends: BTreeMap<OutPoint, HashSet<Txid>>,
|
spends: BTreeMap<OutPoint, HashSet<Txid>>,
|
||||||
anchors: BTreeSet<(A, Txid)>,
|
anchors: BTreeSet<(A, Txid)>,
|
||||||
|
|
||||||
@ -94,9 +94,9 @@ impl<A> Default for TxGraph<A> {
|
|||||||
// pub type InChainTx<'a, T, A> = (ObservedIn<&'a A>, TxInGraph<'a, T, A>);
|
// pub type InChainTx<'a, T, A> = (ObservedIn<&'a A>, TxInGraph<'a, T, A>);
|
||||||
// pub type InChainTxOut<'a, I, A> = (&'a I, FullTxOut<ObservedIn<&'a A>>);
|
// pub type InChainTxOut<'a, I, A> = (&'a I, FullTxOut<ObservedIn<&'a A>>);
|
||||||
|
|
||||||
/// An outward-facing view of a transaction that resides in a [`TxGraph`].
|
/// An outward-facing view of a transaction node that resides in a [`TxGraph`].
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct TxInGraph<'a, T, A> {
|
pub struct TxNode<'a, T, A> {
|
||||||
/// Txid of the transaction.
|
/// Txid of the transaction.
|
||||||
pub txid: Txid,
|
pub txid: Txid,
|
||||||
/// A partial or full representation of the transaction.
|
/// A partial or full representation of the transaction.
|
||||||
@ -107,7 +107,7 @@ pub struct TxInGraph<'a, T, A> {
|
|||||||
pub last_seen: u64,
|
pub last_seen: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T, A> Deref for TxInGraph<'a, T, A> {
|
impl<'a, T, A> Deref for TxNode<'a, T, A> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
@ -115,7 +115,7 @@ impl<'a, T, A> Deref for TxInGraph<'a, T, A> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, A> TxInGraph<'a, Transaction, A> {
|
impl<'a, A> TxNode<'a, Transaction, A> {
|
||||||
pub fn from_tx(tx: &'a Transaction, anchors: &'a BTreeSet<A>) -> Self {
|
pub fn from_tx(tx: &'a Transaction, anchors: &'a BTreeSet<A>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
txid: tx.txid(),
|
txid: tx.txid(),
|
||||||
@ -131,12 +131,12 @@ impl<'a, A> TxInGraph<'a, Transaction, A> {
|
|||||||
/// This can either be a whole transaction, or a partial transaction (where we only have select
|
/// This can either be a whole transaction, or a partial transaction (where we only have select
|
||||||
/// outputs).
|
/// outputs).
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
enum TxNode {
|
enum TxNodeInternal {
|
||||||
Whole(Transaction),
|
Whole(Transaction),
|
||||||
Partial(BTreeMap<u32, TxOut>),
|
Partial(BTreeMap<u32, TxOut>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for TxNode {
|
impl Default for TxNodeInternal {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::Partial(BTreeMap::new())
|
Self::Partial(BTreeMap::new())
|
||||||
}
|
}
|
||||||
@ -146,13 +146,13 @@ impl<A> TxGraph<A> {
|
|||||||
/// Iterate over all tx outputs known by [`TxGraph`].
|
/// Iterate over all tx outputs known by [`TxGraph`].
|
||||||
pub fn all_txouts(&self) -> impl Iterator<Item = (OutPoint, &TxOut)> {
|
pub fn all_txouts(&self) -> impl Iterator<Item = (OutPoint, &TxOut)> {
|
||||||
self.txs.iter().flat_map(|(txid, (tx, _, _))| match tx {
|
self.txs.iter().flat_map(|(txid, (tx, _, _))| match tx {
|
||||||
TxNode::Whole(tx) => tx
|
TxNodeInternal::Whole(tx) => tx
|
||||||
.output
|
.output
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(vout, txout)| (OutPoint::new(*txid, vout as _), txout))
|
.map(|(vout, txout)| (OutPoint::new(*txid, vout as _), txout))
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
TxNode::Partial(txouts) => txouts
|
TxNodeInternal::Partial(txouts) => txouts
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(vout, txout)| (OutPoint::new(*txid, *vout as _), txout))
|
.map(|(vout, txout)| (OutPoint::new(*txid, *vout as _), txout))
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
@ -160,17 +160,17 @@ impl<A> TxGraph<A> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over all full transactions in the graph.
|
/// Iterate over all full transactions in the graph.
|
||||||
pub fn full_transactions(&self) -> impl Iterator<Item = TxInGraph<'_, Transaction, A>> {
|
pub fn full_transactions(&self) -> impl Iterator<Item = TxNode<'_, Transaction, A>> {
|
||||||
self.txs
|
self.txs
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(&txid, (tx, anchors, last_seen))| match tx {
|
.filter_map(|(&txid, (tx, anchors, last_seen))| match tx {
|
||||||
TxNode::Whole(tx) => Some(TxInGraph {
|
TxNodeInternal::Whole(tx) => Some(TxNode {
|
||||||
txid,
|
txid,
|
||||||
tx,
|
tx,
|
||||||
anchors,
|
anchors,
|
||||||
last_seen: *last_seen,
|
last_seen: *last_seen,
|
||||||
}),
|
}),
|
||||||
TxNode::Partial(_) => None,
|
TxNodeInternal::Partial(_) => None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,9 +179,14 @@ impl<A> TxGraph<A> {
|
|||||||
/// Refer to [`get_txout`] for getting a specific [`TxOut`].
|
/// Refer to [`get_txout`] for getting a specific [`TxOut`].
|
||||||
///
|
///
|
||||||
/// [`get_txout`]: Self::get_txout
|
/// [`get_txout`]: Self::get_txout
|
||||||
pub fn get_tx(&self, txid: Txid) -> Option<TxInGraph<'_, Transaction, A>> {
|
pub fn get_tx(&self, txid: Txid) -> Option<&Transaction> {
|
||||||
|
self.get_tx_node(txid).map(|n| n.tx)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a transaction node by txid. This only returns `Some` for full transactions.
|
||||||
|
pub fn get_tx_node(&self, txid: Txid) -> Option<TxNode<'_, Transaction, A>> {
|
||||||
match &self.txs.get(&txid)? {
|
match &self.txs.get(&txid)? {
|
||||||
(TxNode::Whole(tx), anchors, last_seen) => Some(TxInGraph {
|
(TxNodeInternal::Whole(tx), anchors, last_seen) => Some(TxNode {
|
||||||
txid,
|
txid,
|
||||||
tx,
|
tx,
|
||||||
anchors,
|
anchors,
|
||||||
@ -194,21 +199,21 @@ impl<A> TxGraph<A> {
|
|||||||
/// Obtains a single tx output (if any) at the specified outpoint.
|
/// Obtains a single tx output (if any) at the specified outpoint.
|
||||||
pub fn get_txout(&self, outpoint: OutPoint) -> Option<&TxOut> {
|
pub fn get_txout(&self, outpoint: OutPoint) -> Option<&TxOut> {
|
||||||
match &self.txs.get(&outpoint.txid)?.0 {
|
match &self.txs.get(&outpoint.txid)?.0 {
|
||||||
TxNode::Whole(tx) => tx.output.get(outpoint.vout as usize),
|
TxNodeInternal::Whole(tx) => tx.output.get(outpoint.vout as usize),
|
||||||
TxNode::Partial(txouts) => txouts.get(&outpoint.vout),
|
TxNodeInternal::Partial(txouts) => txouts.get(&outpoint.vout),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a [`BTreeMap`] of vout to output of the provided `txid`.
|
/// Returns a [`BTreeMap`] of vout to output of the provided `txid`.
|
||||||
pub fn txouts(&self, txid: Txid) -> Option<BTreeMap<u32, &TxOut>> {
|
pub fn txouts(&self, txid: Txid) -> Option<BTreeMap<u32, &TxOut>> {
|
||||||
Some(match &self.txs.get(&txid)?.0 {
|
Some(match &self.txs.get(&txid)?.0 {
|
||||||
TxNode::Whole(tx) => tx
|
TxNodeInternal::Whole(tx) => tx
|
||||||
.output
|
.output
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(vout, txout)| (vout as u32, txout))
|
.map(|(vout, txout)| (vout as u32, txout))
|
||||||
.collect::<BTreeMap<_, _>>(),
|
.collect::<BTreeMap<_, _>>(),
|
||||||
TxNode::Partial(txouts) => txouts
|
TxNodeInternal::Partial(txouts) => txouts
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(vout, txout)| (*vout, txout))
|
.map(|(vout, txout)| (*vout, txout))
|
||||||
.collect::<BTreeMap<_, _>>(),
|
.collect::<BTreeMap<_, _>>(),
|
||||||
@ -276,12 +281,12 @@ impl<A> TxGraph<A> {
|
|||||||
/// Iterate over all partial transactions (outputs only) in the graph.
|
/// Iterate over all partial transactions (outputs only) in the graph.
|
||||||
pub fn partial_transactions(
|
pub fn partial_transactions(
|
||||||
&self,
|
&self,
|
||||||
) -> impl Iterator<Item = TxInGraph<'_, BTreeMap<u32, TxOut>, A>> {
|
) -> impl Iterator<Item = TxNode<'_, BTreeMap<u32, TxOut>, A>> {
|
||||||
self.txs
|
self.txs
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(&txid, (tx, anchors, last_seen))| match tx {
|
.filter_map(|(&txid, (tx, anchors, last_seen))| match tx {
|
||||||
TxNode::Whole(_) => None,
|
TxNodeInternal::Whole(_) => None,
|
||||||
TxNode::Partial(partial) => Some(TxInGraph {
|
TxNodeInternal::Partial(partial) => Some(TxNode {
|
||||||
txid,
|
txid,
|
||||||
tx: partial,
|
tx: partial,
|
||||||
anchors,
|
anchors,
|
||||||
@ -368,7 +373,7 @@ impl<A: Clone + Ord> TxGraph<A> {
|
|||||||
update.txs.insert(
|
update.txs.insert(
|
||||||
outpoint.txid,
|
outpoint.txid,
|
||||||
(
|
(
|
||||||
TxNode::Partial([(outpoint.vout, txout)].into()),
|
TxNodeInternal::Partial([(outpoint.vout, txout)].into()),
|
||||||
BTreeSet::new(),
|
BTreeSet::new(),
|
||||||
0,
|
0,
|
||||||
),
|
),
|
||||||
@ -394,7 +399,7 @@ impl<A: Clone + Ord> TxGraph<A> {
|
|||||||
let mut update = Self::default();
|
let mut update = Self::default();
|
||||||
update
|
update
|
||||||
.txs
|
.txs
|
||||||
.insert(tx.txid(), (TxNode::Whole(tx), BTreeSet::new(), 0));
|
.insert(tx.txid(), (TxNodeInternal::Whole(tx), BTreeSet::new(), 0));
|
||||||
self.determine_additions(&update)
|
self.determine_additions(&update)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -478,10 +483,10 @@ impl<A: Clone + Ord> TxGraph<A> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
match self.txs.get_mut(&txid) {
|
match self.txs.get_mut(&txid) {
|
||||||
Some((tx_node @ TxNode::Partial(_), _, _)) => {
|
Some((tx_node @ TxNodeInternal::Partial(_), _, _)) => {
|
||||||
*tx_node = TxNode::Whole(tx);
|
*tx_node = TxNodeInternal::Whole(tx);
|
||||||
}
|
}
|
||||||
Some((TxNode::Whole(tx), _, _)) => {
|
Some((TxNodeInternal::Whole(tx), _, _)) => {
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(
|
||||||
tx.txid(),
|
tx.txid(),
|
||||||
txid,
|
txid,
|
||||||
@ -490,7 +495,7 @@ impl<A: Clone + Ord> TxGraph<A> {
|
|||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
self.txs
|
self.txs
|
||||||
.insert(txid, (TxNode::Whole(tx), BTreeSet::new(), 0));
|
.insert(txid, (TxNodeInternal::Whole(tx), BTreeSet::new(), 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -502,8 +507,9 @@ impl<A: Clone + Ord> TxGraph<A> {
|
|||||||
.or_insert_with(Default::default);
|
.or_insert_with(Default::default);
|
||||||
|
|
||||||
match tx_entry {
|
match tx_entry {
|
||||||
(TxNode::Whole(_), _, _) => { /* do nothing since we already have full tx */ }
|
(TxNodeInternal::Whole(_), _, _) => { /* do nothing since we already have full tx */
|
||||||
(TxNode::Partial(txouts), _, _) => {
|
}
|
||||||
|
(TxNodeInternal::Partial(txouts), _, _) => {
|
||||||
txouts.insert(outpoint.vout, txout);
|
txouts.insert(outpoint.vout, txout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -533,11 +539,11 @@ impl<A: Clone + Ord> TxGraph<A> {
|
|||||||
|
|
||||||
for (&txid, (update_tx_node, _, update_last_seen)) in &update.txs {
|
for (&txid, (update_tx_node, _, update_last_seen)) in &update.txs {
|
||||||
let prev_last_seen: u64 = match (self.txs.get(&txid), update_tx_node) {
|
let prev_last_seen: u64 = match (self.txs.get(&txid), update_tx_node) {
|
||||||
(None, TxNode::Whole(update_tx)) => {
|
(None, TxNodeInternal::Whole(update_tx)) => {
|
||||||
additions.tx.insert(update_tx.clone());
|
additions.tx.insert(update_tx.clone());
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
(None, TxNode::Partial(update_txos)) => {
|
(None, TxNodeInternal::Partial(update_txos)) => {
|
||||||
additions.txout.extend(
|
additions.txout.extend(
|
||||||
update_txos
|
update_txos
|
||||||
.iter()
|
.iter()
|
||||||
@ -545,12 +551,18 @@ impl<A: Clone + Ord> TxGraph<A> {
|
|||||||
);
|
);
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
(Some((TxNode::Whole(_), _, last_seen)), _) => *last_seen,
|
(Some((TxNodeInternal::Whole(_), _, last_seen)), _) => *last_seen,
|
||||||
(Some((TxNode::Partial(_), _, last_seen)), TxNode::Whole(update_tx)) => {
|
(
|
||||||
|
Some((TxNodeInternal::Partial(_), _, last_seen)),
|
||||||
|
TxNodeInternal::Whole(update_tx),
|
||||||
|
) => {
|
||||||
additions.tx.insert(update_tx.clone());
|
additions.tx.insert(update_tx.clone());
|
||||||
*last_seen
|
*last_seen
|
||||||
}
|
}
|
||||||
(Some((TxNode::Partial(txos), _, last_seen)), TxNode::Partial(update_txos)) => {
|
(
|
||||||
|
Some((TxNodeInternal::Partial(txos), _, last_seen)),
|
||||||
|
TxNodeInternal::Partial(update_txos),
|
||||||
|
) => {
|
||||||
additions.txout.extend(
|
additions.txout.extend(
|
||||||
update_txos
|
update_txos
|
||||||
.iter()
|
.iter()
|
||||||
@ -608,8 +620,8 @@ impl<A: BlockAnchor> TxGraph<A> {
|
|||||||
// The tx is not anchored to a block which is in the best chain, let's check whether we can
|
// The tx is not anchored to a block which is in the best chain, let's check whether we can
|
||||||
// ignore it by checking conflicts!
|
// ignore it by checking conflicts!
|
||||||
let tx = match tx_node {
|
let tx = match tx_node {
|
||||||
TxNode::Whole(tx) => tx,
|
TxNodeInternal::Whole(tx) => tx,
|
||||||
TxNode::Partial(_) => {
|
TxNodeInternal::Partial(_) => {
|
||||||
// [TODO] Unfortunately, we can't iterate over conflicts of partial txs right now!
|
// [TODO] Unfortunately, we can't iterate over conflicts of partial txs right now!
|
||||||
// [TODO] So we just assume the partial tx does not exist in the best chain :/
|
// [TODO] So we just assume the partial tx does not exist in the best chain :/
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
@ -618,7 +630,7 @@ impl<A: BlockAnchor> TxGraph<A> {
|
|||||||
|
|
||||||
// [TODO] Is this logic correct? I do not think so, but it should be good enough for now!
|
// [TODO] Is this logic correct? I do not think so, but it should be good enough for now!
|
||||||
let mut latest_last_seen = 0_u64;
|
let mut latest_last_seen = 0_u64;
|
||||||
for conflicting_tx in self.walk_conflicts(tx, |_, txid| self.get_tx(txid)) {
|
for conflicting_tx in self.walk_conflicts(tx, |_, txid| self.get_tx_node(txid)) {
|
||||||
for block_id in conflicting_tx.anchors.iter().map(A::anchor_block) {
|
for block_id in conflicting_tx.anchors.iter().map(A::anchor_block) {
|
||||||
if chain.is_block_in_best_chain(block_id)? {
|
if chain.is_block_in_best_chain(block_id)? {
|
||||||
// conflicting tx is in best chain, so the current tx cannot be in best chain!
|
// conflicting tx is in best chain, so the current tx cannot be in best chain!
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
use std::collections::BTreeSet;
|
|
||||||
|
|
||||||
use bdk_chain::{
|
use bdk_chain::{
|
||||||
chain_graph::*,
|
chain_graph::*,
|
||||||
collections::HashSet,
|
collections::HashSet,
|
||||||
sparse_chain,
|
sparse_chain,
|
||||||
tx_graph::{self, TxGraph, TxInGraph},
|
tx_graph::{self, TxGraph},
|
||||||
BlockId, TxHeight,
|
BlockId, TxHeight,
|
||||||
};
|
};
|
||||||
use bitcoin::{OutPoint, PackedLockTime, Script, Sequence, Transaction, TxIn, TxOut, Witness};
|
use bitcoin::{OutPoint, PackedLockTime, Script, Sequence, Transaction, TxIn, TxOut, Witness};
|
||||||
@ -367,15 +365,7 @@ fn test_get_tx_in_chain() {
|
|||||||
let _ = cg.insert_tx(tx.clone(), TxHeight::Unconfirmed).unwrap();
|
let _ = cg.insert_tx(tx.clone(), TxHeight::Unconfirmed).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cg.get_tx_in_chain(tx.txid()),
|
cg.get_tx_in_chain(tx.txid()),
|
||||||
Some((
|
Some((&TxHeight::Unconfirmed, &tx,))
|
||||||
&TxHeight::Unconfirmed,
|
|
||||||
TxInGraph {
|
|
||||||
txid: tx.txid(),
|
|
||||||
tx: &tx,
|
|
||||||
anchors: &BTreeSet::new(),
|
|
||||||
last_seen: 0
|
|
||||||
}
|
|
||||||
))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,18 +397,9 @@ fn test_iterate_transactions() {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
cg.transactions_in_chain().collect::<Vec<_>>(),
|
cg.transactions_in_chain().collect::<Vec<_>>(),
|
||||||
vec![
|
vec![
|
||||||
(
|
(&TxHeight::Confirmed(0), &txs[2],),
|
||||||
&TxHeight::Confirmed(0),
|
(&TxHeight::Confirmed(1), &txs[0],),
|
||||||
TxInGraph::from_tx(&txs[2], &BTreeSet::new())
|
(&TxHeight::Unconfirmed, &txs[1],),
|
||||||
),
|
|
||||||
(
|
|
||||||
&TxHeight::Confirmed(1),
|
|
||||||
TxInGraph::from_tx(&txs[0], &BTreeSet::new())
|
|
||||||
),
|
|
||||||
(
|
|
||||||
&TxHeight::Unconfirmed,
|
|
||||||
TxInGraph::from_tx(&txs[1], &BTreeSet::new())
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#![cfg(feature = "miniscript")]
|
#![cfg(feature = "miniscript")]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod common;
|
mod common;
|
||||||
use std::collections::BTreeSet;
|
|
||||||
|
|
||||||
use bdk_chain::{
|
use bdk_chain::{
|
||||||
keychain::{Balance, KeychainTracker},
|
keychain::{Balance, KeychainTracker},
|
||||||
@ -9,7 +8,6 @@ use bdk_chain::{
|
|||||||
bitcoin::{secp256k1::Secp256k1, OutPoint, PackedLockTime, Transaction, TxOut},
|
bitcoin::{secp256k1::Secp256k1, OutPoint, PackedLockTime, Transaction, TxOut},
|
||||||
Descriptor,
|
Descriptor,
|
||||||
},
|
},
|
||||||
tx_graph::TxInGraph,
|
|
||||||
BlockId, ConfirmationTime, TxHeight,
|
BlockId, ConfirmationTime, TxHeight,
|
||||||
};
|
};
|
||||||
use bitcoin::TxIn;
|
use bitcoin::TxIn;
|
||||||
@ -43,10 +41,7 @@ fn test_insert_tx() {
|
|||||||
.chain_graph()
|
.chain_graph()
|
||||||
.transactions_in_chain()
|
.transactions_in_chain()
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
vec![(
|
vec![(&ConfirmationTime::Unconfirmed, &tx,)]
|
||||||
&ConfirmationTime::Unconfirmed,
|
|
||||||
TxInGraph::from_tx(&tx, &BTreeSet::new())
|
|
||||||
)]
|
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -2,12 +2,9 @@
|
|||||||
mod common;
|
mod common;
|
||||||
use bdk_chain::{
|
use bdk_chain::{
|
||||||
collections::*,
|
collections::*,
|
||||||
tx_graph::{Additions, TxGraph, TxInGraph},
|
tx_graph::{Additions, TxGraph},
|
||||||
BlockId,
|
|
||||||
};
|
|
||||||
use bitcoin::{
|
|
||||||
hashes::Hash, BlockHash, OutPoint, PackedLockTime, Script, Transaction, TxIn, TxOut, Txid,
|
|
||||||
};
|
};
|
||||||
|
use bitcoin::{hashes::Hash, OutPoint, PackedLockTime, Script, Transaction, TxIn, TxOut, Txid};
|
||||||
use core::iter;
|
use core::iter;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -38,7 +35,7 @@ fn insert_txouts() {
|
|||||||
)];
|
)];
|
||||||
|
|
||||||
let mut graph = {
|
let mut graph = {
|
||||||
let mut graph = TxGraph::<(u32, BlockHash)>::default();
|
let mut graph = TxGraph::<()>::default();
|
||||||
for (outpoint, txout) in &original_ops {
|
for (outpoint, txout) in &original_ops {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
graph.insert_txout(*outpoint, txout.clone()),
|
graph.insert_txout(*outpoint, txout.clone()),
|
||||||
@ -94,7 +91,7 @@ fn insert_tx_graph_doesnt_count_coinbase_as_spent() {
|
|||||||
output: vec![],
|
output: vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut graph = TxGraph::<(u32, BlockHash)>::default();
|
let mut graph = TxGraph::<()>::default();
|
||||||
let _ = graph.insert_tx(tx);
|
let _ = graph.insert_tx(tx);
|
||||||
assert!(graph.outspends(OutPoint::null()).is_empty());
|
assert!(graph.outspends(OutPoint::null()).is_empty());
|
||||||
assert!(graph.tx_outspends(Txid::all_zeros()).next().is_none());
|
assert!(graph.tx_outspends(Txid::all_zeros()).next().is_none());
|
||||||
@ -124,8 +121,8 @@ fn insert_tx_graph_keeps_track_of_spend() {
|
|||||||
output: vec![],
|
output: vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut graph1 = TxGraph::<(u32, BlockHash)>::default();
|
let mut graph1 = TxGraph::<()>::default();
|
||||||
let mut graph2 = TxGraph::<(u32, BlockHash)>::default();
|
let mut graph2 = TxGraph::<()>::default();
|
||||||
|
|
||||||
// insert in different order
|
// insert in different order
|
||||||
let _ = graph1.insert_tx(tx1.clone());
|
let _ = graph1.insert_tx(tx1.clone());
|
||||||
@ -153,17 +150,14 @@ fn insert_tx_can_retrieve_full_tx_from_graph() {
|
|||||||
output: vec![TxOut::default()],
|
output: vec![TxOut::default()],
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut graph = TxGraph::<BlockId>::default();
|
let mut graph = TxGraph::<()>::default();
|
||||||
let _ = graph.insert_tx(tx.clone());
|
let _ = graph.insert_tx(tx.clone());
|
||||||
assert_eq!(
|
assert_eq!(graph.get_tx(tx.txid()), Some(&tx));
|
||||||
graph.get_tx(tx.txid()),
|
|
||||||
Some(TxInGraph::from_tx(&tx, &BTreeSet::new()))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn insert_tx_displaces_txouts() {
|
fn insert_tx_displaces_txouts() {
|
||||||
let mut tx_graph = TxGraph::<(u32, BlockHash)>::default();
|
let mut tx_graph = TxGraph::<()>::default();
|
||||||
let tx = Transaction {
|
let tx = Transaction {
|
||||||
version: 0x01,
|
version: 0x01,
|
||||||
lock_time: PackedLockTime(0),
|
lock_time: PackedLockTime(0),
|
||||||
@ -219,7 +213,7 @@ fn insert_tx_displaces_txouts() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn insert_txout_does_not_displace_tx() {
|
fn insert_txout_does_not_displace_tx() {
|
||||||
let mut tx_graph = TxGraph::<(u32, BlockHash)>::default();
|
let mut tx_graph = TxGraph::<()>::default();
|
||||||
let tx = Transaction {
|
let tx = Transaction {
|
||||||
version: 0x01,
|
version: 0x01,
|
||||||
lock_time: PackedLockTime(0),
|
lock_time: PackedLockTime(0),
|
||||||
@ -275,7 +269,7 @@ fn insert_txout_does_not_displace_tx() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_calculate_fee() {
|
fn test_calculate_fee() {
|
||||||
let mut graph = TxGraph::<(u32, BlockHash)>::default();
|
let mut graph = TxGraph::<()>::default();
|
||||||
let intx1 = Transaction {
|
let intx1 = Transaction {
|
||||||
version: 0x01,
|
version: 0x01,
|
||||||
lock_time: PackedLockTime(0),
|
lock_time: PackedLockTime(0),
|
||||||
@ -369,7 +363,7 @@ fn test_calculate_fee_on_coinbase() {
|
|||||||
output: vec![TxOut::default()],
|
output: vec![TxOut::default()],
|
||||||
};
|
};
|
||||||
|
|
||||||
let graph = TxGraph::<(u32, BlockHash)>::default();
|
let graph = TxGraph::<()>::default();
|
||||||
|
|
||||||
assert_eq!(graph.calculate_fee(&tx), Some(0));
|
assert_eq!(graph.calculate_fee(&tx), Some(0));
|
||||||
}
|
}
|
||||||
@ -411,7 +405,7 @@ fn test_conflicting_descendants() {
|
|||||||
let txid_a = tx_a.txid();
|
let txid_a = tx_a.txid();
|
||||||
let txid_b = tx_b.txid();
|
let txid_b = tx_b.txid();
|
||||||
|
|
||||||
let mut graph = TxGraph::<(u32, BlockHash)>::default();
|
let mut graph = TxGraph::<()>::default();
|
||||||
let _ = graph.insert_tx(tx_a);
|
let _ = graph.insert_tx(tx_a);
|
||||||
let _ = graph.insert_tx(tx_b);
|
let _ = graph.insert_tx(tx_b);
|
||||||
|
|
||||||
@ -487,7 +481,7 @@ fn test_descendants_no_repeat() {
|
|||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let mut graph = TxGraph::<(u32, BlockHash)>::default();
|
let mut graph = TxGraph::<()>::default();
|
||||||
let mut expected_txids = BTreeSet::new();
|
let mut expected_txids = BTreeSet::new();
|
||||||
|
|
||||||
// these are NOT descendants of `tx_a`
|
// these are NOT descendants of `tx_a`
|
||||||
|
Loading…
x
Reference in New Issue
Block a user