From 507184caeab845f552237cec3ae5e9992032eca5 Mon Sep 17 00:00:00 2001 From: Jose Storopoli Date: Fri, 7 Feb 2025 18:30:58 -0300 Subject: [PATCH 1/2] fix!(btcio): move submit_package to BroadcastRpc from ReaderRpc --- crates/btcio/src/rpc/client.rs | 12 +++++------ crates/btcio/src/rpc/traits.rs | 24 ++++++++++----------- crates/btcio/src/test_utils.rs | 38 +++++++++++++++++----------------- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/crates/btcio/src/rpc/client.rs b/crates/btcio/src/rpc/client.rs index 1f91605aa..1be42297b 100644 --- a/crates/btcio/src/rpc/client.rs +++ b/crates/btcio/src/rpc/client.rs @@ -292,12 +292,6 @@ impl ReaderRpc for BitcoinClient { .await } - async fn submit_package(&self, txs: &[Transaction]) -> ClientResult { - let txstrs: Vec = txs.iter().map(serialize_hex).collect(); - self.call::("submitpackage", &[to_value(txstrs)?]) - .await - } - async fn network(&self) -> ClientResult { Ok(self .call::("getblockchaininfo", &[]) @@ -336,6 +330,12 @@ impl BroadcasterRpc for BitcoinClient { self.call::>("testmempoolaccept", &[to_value([txstr])?]) .await } + + async fn submit_package(&self, txs: &[Transaction]) -> ClientResult { + let txstrs: Vec = txs.iter().map(serialize_hex).collect(); + self.call::("submitpackage", &[to_value(txstrs)?]) + .await + } } #[async_trait] diff --git a/crates/btcio/src/rpc/traits.rs b/crates/btcio/src/rpc/traits.rs index 6938e4895..2069e462b 100644 --- a/crates/btcio/src/rpc/traits.rs +++ b/crates/btcio/src/rpc/traits.rs @@ -77,18 +77,6 @@ pub trait ReaderRpc { include_mempool: bool, ) -> ClientResult; - /// Submit a package of raw transactions (serialized, hex-encoded) to local node. - /// - /// The package will be validated according to consensus and mempool policy rules. If any - /// transaction passes, it will be accepted to mempool. This RPC is experimental and the - /// interface may be unstable. Refer to doc/policy/packages.md for documentation on package - /// policies. - /// - /// # Warning - /// - /// Successful submission does not mean the transactions will propagate throughout the network. - async fn submit_package(&self, txs: &[Transaction]) -> ClientResult; - /// Gets the underlying [`Network`] information. async fn network(&self) -> ClientResult; } @@ -116,6 +104,18 @@ pub trait BroadcasterRpc { /// Tests if a raw transaction is valid. async fn test_mempool_accept(&self, tx: &Transaction) -> ClientResult>; + + /// Submit a package of raw transactions (serialized, hex-encoded) to local node. + /// + /// The package will be validated according to consensus and mempool policy rules. If any + /// transaction passes, it will be accepted to mempool. This RPC is experimental and the + /// interface may be unstable. Refer to doc/policy/packages.md for documentation on package + /// policies. + /// + /// # Warning + /// + /// Successful submission does not mean the transactions will propagate throughout the network. + async fn submit_package(&self, txs: &[Transaction]) -> ClientResult; } /// Wallet functionality that any Bitcoin client **without private keys** that diff --git a/crates/btcio/src/test_utils.rs b/crates/btcio/src/test_utils.rs index 2b534bbf0..e76591f36 100644 --- a/crates/btcio/src/test_utils.rs +++ b/crates/btcio/src/test_utils.rs @@ -136,6 +136,25 @@ impl ReaderRpc for TestBitcoinClient { }) } + async fn network(&self) -> ClientResult { + Ok(Network::Regtest) + } +} + +#[async_trait] +impl BroadcasterRpc for TestBitcoinClient { + // send_raw_transaction sends a raw transaction to the network + async fn send_raw_transaction(&self, _tx: &Transaction) -> ClientResult { + Ok(Txid::from_slice(&[1u8; 32]).unwrap()) + } + async fn test_mempool_accept(&self, _tx: &Transaction) -> ClientResult> { + let some_tx: Transaction = consensus::encode::deserialize_hex(SOME_TX).unwrap(); + Ok(vec![TestMempoolAccept { + txid: some_tx.compute_txid(), + reject_reason: None, + }]) + } + async fn submit_package(&self, _txs: &[Transaction]) -> ClientResult { let some_tx: Transaction = consensus::encode::deserialize_hex(SOME_TX).unwrap(); let wtxid = some_tx.compute_wtxid(); @@ -156,25 +175,6 @@ impl ReaderRpc for TestBitcoinClient { replaced_transactions: vec![], }) } - - async fn network(&self) -> ClientResult { - Ok(Network::Regtest) - } -} - -#[async_trait] -impl BroadcasterRpc for TestBitcoinClient { - // send_raw_transaction sends a raw transaction to the network - async fn send_raw_transaction(&self, _tx: &Transaction) -> ClientResult { - Ok(Txid::from_slice(&[1u8; 32]).unwrap()) - } - async fn test_mempool_accept(&self, _tx: &Transaction) -> ClientResult> { - let some_tx: Transaction = consensus::encode::deserialize_hex(SOME_TX).unwrap(); - Ok(vec![TestMempoolAccept { - txid: some_tx.compute_txid(), - reject_reason: None, - }]) - } } #[async_trait] From a8e1c4c3ec7275c181508df49061b9049b6db1d6 Mon Sep 17 00:00:00 2001 From: Jose Storopoli Date: Fri, 7 Feb 2025 18:31:17 -0300 Subject: [PATCH 2/2] feat(btcio): make BitcoinClient Clone --- crates/btcio/src/rpc/client.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/crates/btcio/src/rpc/client.rs b/crates/btcio/src/rpc/client.rs index 1be42297b..baad6d3fd 100644 --- a/crates/btcio/src/rpc/client.rs +++ b/crates/btcio/src/rpc/client.rs @@ -1,7 +1,10 @@ use std::{ env::var, fmt, - sync::atomic::{AtomicUsize, Ordering}, + sync::{ + atomic::{AtomicUsize, Ordering}, + Arc, + }, time::Duration, }; @@ -54,14 +57,18 @@ where } /// An `async` client for interacting with a `bitcoind` instance. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct BitcoinClient { /// The URL of the `bitcoind` instance. url: String, /// The underlying `async` HTTP client. client: Client, /// The ID of the current request. - id: AtomicUsize, + /// + /// # Implementation Details + /// + /// Using an [`Arc`] so that [`BitcoinClient`] is [`Clone`]. + id: Arc, /// The maximum number of retries for a request. max_retries: u8, /// Interval between retries for a request in ms. @@ -107,7 +114,7 @@ impl BitcoinClient { .build() .map_err(|e| ClientError::Other(format!("Could not create client: {e}")))?; - let id = AtomicUsize::new(0); + let id = Arc::new(AtomicUsize::new(0)); let max_retries = max_retries.unwrap_or(DEFAULT_MAX_RETRIES); let retry_interval = retry_interval.unwrap_or(DEFAULT_RETRY_INTERVAL_MS);