]> Untitled Git - bdk/commitdiff
feat(esplora): always fetch prevouts
author志宇 <hello@evanlinjin.me>
Tue, 2 Jul 2024 03:53:54 +0000 (03:53 +0000)
committer志宇 <hello@evanlinjin.me>
Wed, 14 Aug 2024 08:16:57 +0000 (08:16 +0000)
Prevouts are needed to calculate fees for transactions. They are
introduced as floating txouts in the update `TxGraph`. A helper method
`insert_prevouts` is added to insert the floating txouts using the
`Vin`s returned from Esplora.

Also replaced `anchor_from_status` with `insert_anchor_from_status` as
we always insert the anchor into the update `TxGraph` after getting it.

Also removed `bitcoin` dependency as `bdk_chain` already depends on
`bitcoin` (and it's re-exported).

crates/esplora/Cargo.toml
crates/esplora/src/async_ext.rs
crates/esplora/src/blocking_ext.rs
crates/esplora/src/lib.rs

index 149bce9bf59975e718df115e13e78c8386b9a099..9148a0f86f48ea4efad56cdce5c78297b7d48cb3 100644 (file)
@@ -16,8 +16,6 @@ bdk_chain = { path = "../chain", version = "0.17.0", default-features = false }
 esplora-client = { version = "0.9.0", default-features = false }
 async-trait = { version = "0.1.66", optional = true }
 futures = { version = "0.3.26", optional = true }
-
-bitcoin = { version = "0.32.0", optional = true, default-features = false }
 miniscript = { version = "12.0.0", optional = true, default-features = false }
 
 [dev-dependencies]
index 139180b0e0242a938086da20e7450ffd74391732..fed6dd526a89a786d808bb9888e0f61193479489 100644 (file)
@@ -4,16 +4,16 @@ use std::usize;
 use async_trait::async_trait;
 use bdk_chain::spk_client::{FullScanRequest, FullScanResult, SyncRequest, SyncResult};
 use bdk_chain::{
-    bitcoin::{BlockHash, OutPoint, ScriptBuf, TxOut, Txid},
+    bitcoin::{BlockHash, OutPoint, ScriptBuf, Txid},
     collections::BTreeMap,
     local_chain::CheckPoint,
     BlockId, ConfirmationBlockTime, TxGraph,
 };
 use bdk_chain::{Anchor, Indexed};
-use esplora_client::{Amount, Tx, TxStatus};
+use esplora_client::{Tx, TxStatus};
 use futures::{stream::FuturesOrdered, TryStreamExt};
 
-use crate::anchor_from_status;
+use crate::{insert_anchor_from_status, insert_prevouts};
 
 /// [`esplora_client::Error`]
 type Error = Box<esplora_client::Error>;
@@ -230,27 +230,8 @@ impl EsploraAsyncExt for esplora_client::AsyncClient {
                 }
                 for tx in txs {
                     let _ = tx_graph.insert_tx(tx.to_tx());
-                    if let Some(anchor) = anchor_from_status(&tx.status) {
-                        let _ = tx_graph.insert_anchor(tx.txid, anchor);
-                    }
-
-                    let previous_outputs = tx.vin.iter().filter_map(|vin| {
-                        let prevout = vin.prevout.as_ref()?;
-                        Some((
-                            OutPoint {
-                                txid: vin.txid,
-                                vout: vin.vout,
-                            },
-                            TxOut {
-                                script_pubkey: prevout.scriptpubkey.clone(),
-                                value: Amount::from_sat(prevout.value),
-                            },
-                        ))
-                    });
-
-                    for (outpoint, txout) in previous_outputs {
-                        let _ = tx_graph.insert_txout(outpoint, txout);
-                    }
+                    insert_anchor_from_status(&mut tx_graph, tx.txid, tx.status);
+                    insert_prevouts(&mut tx_graph, tx.vin);
                 }
             }
 
@@ -330,15 +311,12 @@ impl EsploraAsyncExt for esplora_client::AsyncClient {
             for (txid, resp) in handles.try_collect::<Vec<_>>().await? {
                 match resp {
                     EsploraResp::TxStatus(status) => {
-                        if let Some(anchor) = anchor_from_status(&status) {
-                            let _ = tx_graph.insert_anchor(txid, anchor);
-                        }
+                        insert_anchor_from_status(&mut tx_graph, txid, status);
                     }
                     EsploraResp::Tx(Some(tx_info)) => {
                         let _ = tx_graph.insert_tx(tx_info.to_tx());
-                        if let Some(anchor) = anchor_from_status(&tx_info.status) {
-                            let _ = tx_graph.insert_anchor(txid, anchor);
-                        }
+                        insert_anchor_from_status(&mut tx_graph, txid, tx_info.status);
+                        insert_prevouts(&mut tx_graph, tx_info.vin);
                     }
                     _ => continue,
                 }
@@ -389,9 +367,7 @@ impl EsploraAsyncExt for esplora_client::AsyncClient {
                     missing_txs.push(spend_txid);
                 }
                 if let Some(spend_status) = op_status.status {
-                    if let Some(spend_anchor) = anchor_from_status(&spend_status) {
-                        let _ = tx_graph.insert_anchor(spend_txid, spend_anchor);
-                    }
+                    insert_anchor_from_status(&mut tx_graph, spend_txid, spend_status);
                 }
             }
         }
index a5bb0cd34e437a5c33311c356564c7a4171b1371..81ce76848bced35fb25fec47a82339d63545108c 100644 (file)
@@ -4,14 +4,14 @@ use std::thread::JoinHandle;
 use bdk_chain::collections::BTreeMap;
 use bdk_chain::spk_client::{FullScanRequest, FullScanResult, SyncRequest, SyncResult};
 use bdk_chain::{
-    bitcoin::{Amount, BlockHash, OutPoint, ScriptBuf, TxOut, Txid},
+    bitcoin::{BlockHash, OutPoint, ScriptBuf, Txid},
     local_chain::CheckPoint,
     BlockId, ConfirmationBlockTime, TxGraph,
 };
 use bdk_chain::{Anchor, Indexed};
 use esplora_client::{OutputStatus, Tx, TxStatus};
 
-use crate::anchor_from_status;
+use crate::{insert_anchor_from_status, insert_prevouts};
 
 /// [`esplora_client::Error`]
 pub type Error = Box<esplora_client::Error>;
@@ -210,27 +210,8 @@ impl EsploraExt for esplora_client::BlockingClient {
                 }
                 for tx in txs {
                     let _ = tx_graph.insert_tx(tx.to_tx());
-                    if let Some(anchor) = anchor_from_status(&tx.status) {
-                        let _ = tx_graph.insert_anchor(tx.txid, anchor);
-                    }
-
-                    let previous_outputs = tx.vin.iter().filter_map(|vin| {
-                        let prevout = vin.prevout.as_ref()?;
-                        Some((
-                            OutPoint {
-                                txid: vin.txid,
-                                vout: vin.vout,
-                            },
-                            TxOut {
-                                script_pubkey: prevout.scriptpubkey.clone(),
-                                value: Amount::from_sat(prevout.value),
-                            },
-                        ))
-                    });
-
-                    for (outpoint, txout) in previous_outputs {
-                        let _ = tx_graph.insert_txout(outpoint, txout);
-                    }
+                    insert_anchor_from_status(&mut tx_graph, tx.txid, tx.status);
+                    insert_prevouts(&mut tx_graph, tx.vin);
                 }
             }
 
@@ -310,15 +291,12 @@ impl EsploraExt for esplora_client::BlockingClient {
                 let (txid, resp) = handle.join().expect("thread must not panic")?;
                 match resp {
                     EsploraResp::TxStatus(status) => {
-                        if let Some(anchor) = anchor_from_status(&status) {
-                            let _ = tx_graph.insert_anchor(txid, anchor);
-                        }
+                        insert_anchor_from_status(&mut tx_graph, txid, status);
                     }
                     EsploraResp::Tx(Some(tx_info)) => {
                         let _ = tx_graph.insert_tx(tx_info.to_tx());
-                        if let Some(anchor) = anchor_from_status(&tx_info.status) {
-                            let _ = tx_graph.insert_anchor(txid, anchor);
-                        }
+                        insert_anchor_from_status(&mut tx_graph, txid, tx_info.status);
+                        insert_prevouts(&mut tx_graph, tx_info.vin);
                     }
                     _ => continue,
                 }
@@ -373,9 +351,7 @@ impl EsploraExt for esplora_client::BlockingClient {
                         missing_txs.push(spend_txid);
                     }
                     if let Some(spend_status) = op_status.status {
-                        if let Some(spend_anchor) = anchor_from_status(&spend_status) {
-                            let _ = tx_graph.insert_anchor(spend_txid, spend_anchor);
-                        }
+                        insert_anchor_from_status(&mut tx_graph, spend_txid, spend_status);
                     }
                 }
             }
index fab055888f9dc1bf31dccf4c9ca47d8519aed7fe..2c0e62b7e44f515000745fcbebc9c88592de2673 100644 (file)
@@ -56,7 +56,8 @@
 //! [`ChainOracle`]: bdk_chain::ChainOracle
 //! [`example_esplora`]: https://github.com/bitcoindevkit/bdk/tree/master/example-crates/example_esplora
 
-use bdk_chain::{BlockId, ConfirmationBlockTime};
+use bdk_chain::bitcoin::{Amount, OutPoint, TxOut, Txid};
+use bdk_chain::{BlockId, ConfirmationBlockTime, TxGraph};
 use esplora_client::TxStatus;
 
 pub use esplora_client;
@@ -71,19 +72,42 @@ mod async_ext;
 #[cfg(feature = "async")]
 pub use async_ext::*;
 
-fn anchor_from_status(status: &TxStatus) -> Option<ConfirmationBlockTime> {
+fn insert_anchor_from_status(
+    tx_graph: &mut TxGraph<ConfirmationBlockTime>,
+    txid: Txid,
+    status: TxStatus,
+) {
     if let TxStatus {
         block_height: Some(height),
         block_hash: Some(hash),
         block_time: Some(time),
         ..
-    } = status.clone()
+    } = status
     {
-        Some(ConfirmationBlockTime {
+        let anchor = ConfirmationBlockTime {
             block_id: BlockId { height, hash },
             confirmation_time: time,
-        })
-    } else {
-        None
+        };
+        let _ = tx_graph.insert_anchor(txid, anchor);
+    }
+}
+
+/// Inserts floating txouts into `tx_graph` using [`Vin`](esplora_client::api::Vin)s returned by
+/// Esplora.
+fn insert_prevouts(
+    tx_graph: &mut TxGraph<ConfirmationBlockTime>,
+    esplora_inputs: impl IntoIterator<Item = esplora_client::api::Vin>,
+) {
+    let prevouts = esplora_inputs
+        .into_iter()
+        .filter_map(|vin| Some((vin.txid, vin.vout, vin.prevout?)));
+    for (prev_txid, prev_vout, prev_txout) in prevouts {
+        let _ = tx_graph.insert_txout(
+            OutPoint::new(prev_txid, prev_vout),
+            TxOut {
+                script_pubkey: prev_txout.scriptpubkey,
+                value: Amount::from_sat(prev_txout.value),
+            },
+        );
     }
 }