Abstract Daemon methods in RpcCall trait

This commit is contained in:
Sosthene 2024-11-18 15:21:52 +01:00
parent 8eae4408f2
commit 39a8ff87a9
2 changed files with 101 additions and 56 deletions

View File

@ -122,18 +122,14 @@ fn rpc_connect(rpcwallet: Option<String>, network: Network, mut rpc_url: String)
#[derive(Debug)] #[derive(Debug)]
pub struct Daemon { pub struct Daemon {
// p2p: Mutex<Connection>,
rpc: Client, rpc: Client,
} }
impl Daemon { impl RpcCall for Daemon {
pub(crate) fn connect( fn connect(
rpcwallet: Option<String>, rpcwallet: Option<String>,
rpc_url: String, rpc_url: String,
network: Network, network: Network,
// config: &Config,
// exit_flag: &ExitFlag,
// metrics: &Metrics,
) -> Result<Self> { ) -> Result<Self> {
let mut rpc = rpc_connect(rpcwallet, network, rpc_url)?; let mut rpc = rpc_connect(rpcwallet, network, rpc_url)?;
@ -150,9 +146,6 @@ impl Daemon {
} }
let network_info = rpc.get_network_info()?; let network_info = rpc.get_network_info()?;
// if network_info.version < 21_00_00 {
// bail!("electrs requires bitcoind 0.21+");
// }
if !network_info.network_active { if !network_info.network_active {
anyhow::bail!("electrs requires active bitcoind p2p network"); anyhow::bail!("electrs requires active bitcoind p2p network");
} }
@ -161,16 +154,10 @@ impl Daemon {
anyhow::bail!("electrs requires non-pruned bitcoind node"); anyhow::bail!("electrs requires non-pruned bitcoind node");
} }
// let p2p = tokio::sync::Mutex::new(Connection::connect(
// config.network,
// config.daemon_p2p_addr,
// metrics,
// config.signet_magic,
// )?);
Ok(Self { rpc }) Ok(Self { rpc })
} }
pub(crate) fn estimate_fee(&self, nblocks: u16) -> Result<Amount> { fn estimate_fee(&self, nblocks: u16) -> Result<Amount> {
let res = self let res = self
.rpc .rpc
.estimate_smart_fee(nblocks, None) .estimate_smart_fee(nblocks, None)
@ -182,7 +169,7 @@ impl Daemon {
} }
} }
pub(crate) fn get_relay_fee(&self) -> Result<Amount> { fn get_relay_fee(&self) -> Result<Amount> {
Ok(self Ok(self
.rpc .rpc
.get_network_info() .get_network_info()
@ -190,21 +177,21 @@ impl Daemon {
.relay_fee) .relay_fee)
} }
pub(crate) fn get_current_height(&self) -> Result<u64> { fn get_current_height(&self) -> Result<u64> {
Ok(self Ok(self
.rpc .rpc
.get_block_count() .get_block_count()
.context("failed to get block count")?) .context("failed to get block count")?)
} }
pub(crate) fn get_block(&self, block_hash: BlockHash) -> Result<Block> { fn get_block(&self, block_hash: BlockHash) -> Result<Block> {
Ok(self Ok(self
.rpc .rpc
.get_block(&block_hash) .get_block(&block_hash)
.context("failed to get block")?) .context("failed to get block")?)
} }
pub(crate) fn get_filters(&self, block_height: u32) -> Result<(u32, BlockHash, BlockFilter)> { fn get_filters(&self, block_height: u32) -> Result<(u32, BlockHash, BlockFilter)> {
let block_hash = self.rpc.get_block_hash(block_height.try_into()?)?; let block_hash = self.rpc.get_block_hash(block_height.try_into()?)?;
let filter = self let filter = self
.rpc .rpc
@ -214,7 +201,7 @@ impl Daemon {
Ok((block_height, block_hash, filter)) Ok((block_height, block_hash, filter))
} }
pub(crate) fn list_unspent_from_to( fn list_unspent_from_to(
&self, &self,
minamt: Option<Amount>, minamt: Option<Amount>,
) -> Result<Vec<json::ListUnspentResultEntry>> { ) -> Result<Vec<json::ListUnspentResultEntry>> {
@ -235,7 +222,7 @@ impl Daemon {
)?) )?)
} }
pub(crate) fn create_psbt( fn create_psbt(
&self, &self,
unspents: &[ListUnspentResultEntry], unspents: &[ListUnspentResultEntry],
spk: ScriptBuf, spk: ScriptBuf,
@ -273,7 +260,7 @@ impl Daemon {
Ok(wallet_create_funded_result.psbt.to_string()) Ok(wallet_create_funded_result.psbt.to_string())
} }
pub(crate) fn process_psbt(&self, psbt: String) -> Result<String> { fn process_psbt(&self, psbt: String) -> Result<String> {
let processed_psbt = self.rpc.wallet_process_psbt(&psbt, None, None, None)?; let processed_psbt = self.rpc.wallet_process_psbt(&psbt, None, None, None)?;
match processed_psbt.complete { match processed_psbt.complete {
true => Ok(processed_psbt.psbt), true => Ok(processed_psbt.psbt),
@ -281,7 +268,7 @@ impl Daemon {
} }
} }
pub(crate) fn finalize_psbt(&self, psbt: String) -> Result<String> { fn finalize_psbt(&self, psbt: String) -> Result<String> {
let final_tx = self.rpc.finalize_psbt(&psbt, Some(false))?; let final_tx = self.rpc.finalize_psbt(&psbt, Some(false))?;
match final_tx.complete { match final_tx.complete {
@ -292,13 +279,13 @@ impl Daemon {
} }
} }
pub(crate) fn get_network(&self) -> Result<Network> { fn get_network(&self) -> Result<Network> {
let blockchain_info = self.rpc.get_blockchain_info()?; let blockchain_info = self.rpc.get_blockchain_info()?;
Ok(blockchain_info.chain) Ok(blockchain_info.chain)
} }
pub(crate) fn test_mempool_accept( fn test_mempool_accept(
&self, &self,
tx: &Transaction, tx: &Transaction,
) -> Result<crate::bitcoin_json::TestMempoolAcceptResult> { ) -> Result<crate::bitcoin_json::TestMempoolAcceptResult> {
@ -307,13 +294,13 @@ impl Daemon {
Ok(res.get(0).unwrap().clone()) Ok(res.get(0).unwrap().clone())
} }
pub(crate) fn broadcast(&self, tx: &Transaction) -> Result<Txid> { fn broadcast(&self, tx: &Transaction) -> Result<Txid> {
let txid = self.rpc.send_raw_transaction(tx)?; let txid = self.rpc.send_raw_transaction(tx)?;
Ok(txid) Ok(txid)
} }
pub(crate) fn get_transaction_info( fn get_transaction_info(
&self, &self,
txid: &Txid, txid: &Txid,
blockhash: Option<BlockHash>, blockhash: Option<BlockHash>,
@ -327,7 +314,7 @@ impl Daemon {
.context("failed to get transaction info") .context("failed to get transaction info")
} }
pub(crate) fn get_transaction_hex( fn get_transaction_hex(
&self, &self,
txid: &Txid, txid: &Txid,
blockhash: Option<BlockHash>, blockhash: Option<BlockHash>,
@ -341,7 +328,7 @@ impl Daemon {
serde_json::to_value(TxAsHex(tx)).map_err(Into::into) serde_json::to_value(TxAsHex(tx)).map_err(Into::into)
} }
pub(crate) fn get_transaction( fn get_transaction(
&self, &self,
txid: &Txid, txid: &Txid,
blockhash: Option<BlockHash>, blockhash: Option<BlockHash>,
@ -351,7 +338,7 @@ impl Daemon {
.context("failed to get transaction") .context("failed to get transaction")
} }
pub(crate) fn get_block_txids(&self, blockhash: BlockHash) -> Result<Vec<Txid>> { fn get_block_txids(&self, blockhash: BlockHash) -> Result<Vec<Txid>> {
Ok(self Ok(self
.rpc .rpc
.get_block_info(&blockhash) .get_block_info(&blockhash)
@ -359,13 +346,13 @@ impl Daemon {
.tx) .tx)
} }
pub(crate) fn get_mempool_txids(&self) -> Result<Vec<Txid>> { fn get_mempool_txids(&self) -> Result<Vec<Txid>> {
self.rpc self.rpc
.get_raw_mempool() .get_raw_mempool()
.context("failed to get mempool txids") .context("failed to get mempool txids")
} }
pub(crate) fn get_mempool_entries( fn get_mempool_entries(
&self, &self,
txids: &[Txid], txids: &[Txid],
) -> Result<Vec<Result<json::GetMempoolEntryResult>>> { ) -> Result<Vec<Result<json::GetMempoolEntryResult>>> {
@ -391,7 +378,7 @@ impl Daemon {
.collect()) .collect())
} }
pub(crate) fn get_mempool_transactions( fn get_mempool_transactions(
&self, &self,
txids: &[Txid], txids: &[Txid],
) -> Result<Vec<Result<Transaction>>> { ) -> Result<Vec<Result<Transaction>>> {
@ -420,21 +407,81 @@ impl Daemon {
.collect()) .collect())
} }
// pub(crate) fn get_new_headers(&self, chain: &Chain) -> Result<Vec<NewHeader>> { }
// self.p2p.lock().get_new_headers(chain)
// }
// pub(crate) fn for_blocks<B, F>(&self, blockhashes: B, func: F) -> Result<()> pub(crate) trait RpcCall: Send + Sync + std::fmt::Debug {
// where fn connect(
// B: IntoIterator<Item = BlockHash>, rpcwallet: Option<String>,
// F: FnMut(BlockHash, SerBlock), rpc_url: String,
// { network: Network,
// self.p2p.lock().for_blocks(blockhashes, func) ) -> Result<Self> where Self: Sized;
// }
// pub(crate) fn new_block_notification(&self) -> Receiver<()> { fn estimate_fee(&self, nblocks: u16) -> Result<Amount>;
// self.p2p.lock().new_block_notification()
// } fn get_relay_fee(&self) -> Result<Amount>;
fn get_current_height(&self) -> Result<u64>;
fn get_block(&self, block_hash: BlockHash) -> Result<Block>;
fn get_filters(&self, block_height: u32) -> Result<(u32, BlockHash, BlockFilter)>;
fn list_unspent_from_to(
&self,
minamt: Option<Amount>,
) -> Result<Vec<json::ListUnspentResultEntry>>;
fn create_psbt(
&self,
unspents: &[ListUnspentResultEntry],
spk: ScriptBuf,
network: Network,
) -> Result<String>;
fn process_psbt(&self, psbt: String) -> Result<String>;
fn finalize_psbt(&self, psbt: String) -> Result<String>;
fn get_network(&self) -> Result<Network>;
fn test_mempool_accept(
&self,
tx: &Transaction,
) -> Result<crate::bitcoin_json::TestMempoolAcceptResult>;
fn broadcast(&self, tx: &Transaction) -> Result<Txid>;
fn get_transaction_info(
&self,
txid: &Txid,
blockhash: Option<BlockHash>,
) -> Result<Value>;
fn get_transaction_hex(
&self,
txid: &Txid,
blockhash: Option<BlockHash>,
) -> Result<Value>;
fn get_transaction(
&self,
txid: &Txid,
blockhash: Option<BlockHash>,
) -> Result<Transaction>;
fn get_block_txids(&self, blockhash: BlockHash) -> Result<Vec<Txid>>;
fn get_mempool_txids(&self) -> Result<Vec<Txid>>;
fn get_mempool_entries(
&self,
txids: &[Txid],
) -> Result<Vec<Result<json::GetMempoolEntryResult>>>;
fn get_mempool_transactions(
&self,
txids: &[Txid],
) -> Result<Vec<Result<Transaction>>>;
} }
pub(crate) type RpcError = bitcoincore_rpc::jsonrpc::error::RpcError; pub(crate) type RpcError = bitcoincore_rpc::jsonrpc::error::RpcError;

View File

@ -15,13 +15,13 @@ use futures_util::{future, pin_mut, stream::TryStreamExt, FutureExt, StreamExt};
use log::{debug, error, warn}; use log::{debug, error, warn};
use message::{broadcast_message, process_message, BroadcastType, MessageCache, MESSAGECACHE}; use message::{broadcast_message, process_message, BroadcastType, MessageCache, MESSAGECACHE};
use scan::compute_partial_tweak_to_transaction; use scan::compute_partial_tweak_to_transaction;
use sdk_common::{pcd::{AnkPcdHash, RoleDefinition}, process::CACHEDPROCESSES, signature::{AnkHash, Proof}, sp_client::bitcoin::{ use sdk_common::{process::CACHEDPROCESSES, sp_client::bitcoin::{
consensus::deserialize, consensus::deserialize,
hex::{DisplayHex, FromHex}, hex::{DisplayHex, FromHex},
Amount, Network, Transaction, Amount, Network, Transaction,
}, MutexExt}; }, MutexExt};
use sdk_common::sp_client::{ use sdk_common::sp_client::{
bitcoin::{Txid, OutPoint}, bitcoin::OutPoint,
bitcoin::secp256k1::rand::{thread_rng, Rng}, bitcoin::secp256k1::rand::{thread_rng, Rng},
spclient::SpWallet, spclient::SpWallet,
}; };
@ -48,7 +48,7 @@ mod scan;
mod commit; mod commit;
use crate::config::Config; use crate::config::Config;
use crate::{daemon::Daemon, scan::scan_blocks}; use crate::{daemon::{Daemon, RpcCall}, scan::scan_blocks};
type Tx = UnboundedSender<Message>; type Tx = UnboundedSender<Message>;
@ -56,9 +56,7 @@ type PeerMap = Mutex<HashMap<SocketAddr, Tx>>;
pub(crate) static PEERMAP: OnceLock<PeerMap> = OnceLock::new(); pub(crate) static PEERMAP: OnceLock<PeerMap> = OnceLock::new();
type SharedDaemon = Mutex<Daemon>; pub(crate) static DAEMON: OnceLock<Mutex<Box<dyn RpcCall>>> = OnceLock::new();
pub(crate) static DAEMON: OnceLock<SharedDaemon> = OnceLock::new();
pub static FREEZED_UTXOS: OnceLock<Mutex<HashSet<OutPoint>>> = OnceLock::new(); pub static FREEZED_UTXOS: OnceLock<Mutex<HashSet<OutPoint>>> = OnceLock::new();
@ -190,7 +188,7 @@ async fn handle_connection(raw_stream: TcpStream, addr: SocketAddr) {
let broadcast_incoming = incoming.try_for_each(|msg| { let broadcast_incoming = incoming.try_for_each(|msg| {
if let Ok(raw_msg) = msg.to_text() { if let Ok(raw_msg) = msg.to_text() {
debug!("Received msg: {}", raw_msg); // debug!("Received msg: {}", raw_msg);
process_message(raw_msg, addr); process_message(raw_msg, addr);
} else { } else {
debug!("Received non-text message {} from peer {}", msg, addr); debug!("Received non-text message {} from peer {}", msg, addr);
@ -309,11 +307,11 @@ async fn main() -> Result<()> {
// Connect the rpc daemon // Connect the rpc daemon
DAEMON DAEMON
.set(Mutex::new(Daemon::connect( .set(Mutex::new(Box::new(Daemon::connect(
config.core_wallet, config.core_wallet,
config.core_url, config.core_url,
config.network, config.network,
)?)) )?)))
.expect("DAEMON initialization failed"); .expect("DAEMON initialization failed");
let current_tip: u32 = DAEMON let current_tip: u32 = DAEMON