bitcoin: interface for broadcasting a transaction

This commit is contained in:
Antoine Poinsot 2022-10-17 15:48:12 +02:00
parent 9bb20303e7
commit b14bc602d4
No known key found for this signature in database
GPG Key ID: E13FC145CD3F4304
3 changed files with 52 additions and 3 deletions

View File

@ -679,6 +679,14 @@ impl BitcoinD {
blockhash,
}
}
pub fn broadcast_tx(&self, tx: &bitcoin::Transaction) -> Result<(), BitcoindError> {
self.make_fallible_node_request(
"sendrawtransaction",
&params!(bitcoin::consensus::encode::serialize_hex(tx)),
)?;
Ok(())
}
}
// Bitcoind uses a guess for the value of verificationprogress. It will eventually get to
// be 1, and we want to be less conservative.

View File

@ -4,12 +4,30 @@
pub mod d;
pub mod poller;
use d::LSBlockEntry;
use d::{BitcoindError, LSBlockEntry};
use std::{collections::HashMap, fmt, sync};
use std::{collections::HashMap, error, fmt, sync};
use miniscript::bitcoin;
/// Error occuring when querying our Bitcoin backend.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum BitcoinError {
Broadcast(String),
}
impl fmt::Display for BitcoinError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
BitcoinError::Broadcast(reason) => {
write!(f, "Failed to broadcast transaction: '{}'", reason)
}
}
}
}
impl error::Error for BitcoinError {}
/// Information about the best block in the chain
#[derive(Debug, Clone, Eq, PartialEq, Copy)]
pub struct BlockChainTip {
@ -60,6 +78,9 @@ pub trait BitcoinInterface: Send {
/// Get the common ancestor between the Bitcoin backend's tip and the given tip.
fn common_ancestor(&self, tip: &BlockChainTip) -> BlockChainTip;
/// Broadcast this transaction to the Bitcoin P2P network
fn broadcast_tx(&self, tx: &bitcoin::Transaction) -> Result<(), BitcoinError>;
}
impl BitcoinInterface for d::BitcoinD {
@ -234,6 +255,18 @@ impl BitcoinInterface for d::BitcoinD {
ancestor
}
fn broadcast_tx(&self, tx: &bitcoin::Transaction) -> Result<(), BitcoinError> {
match self.broadcast_tx(tx) {
Ok(()) => Ok(()),
Err(BitcoindError::Server(e)) => Err(BitcoinError::Broadcast(e.to_string())),
// We assume the Bitcoin backend doesn't fail, so it must be a JSONRPC error.
Err(e) => panic!(
"Unexpected Bitcoin error when broadcast transaction: '{}'.",
e
),
}
}
}
// FIXME: do we need to repeat the entire trait implemenation? Isn't there a nicer way?
@ -282,6 +315,10 @@ impl BitcoinInterface for sync::Arc<sync::Mutex<dyn BitcoinInterface + 'static>>
fn common_ancestor(&self, tip: &BlockChainTip) -> BlockChainTip {
self.lock().unwrap().common_ancestor(tip)
}
fn broadcast_tx(&self, tx: &bitcoin::Transaction) -> Result<(), BitcoinError> {
self.lock().unwrap().broadcast_tx(tx)
}
}
// FIXME: We could avoid this type (and all the conversions entailing allocations) if bitcoind

View File

@ -1,5 +1,5 @@
use crate::{
bitcoin::{BitcoinInterface, BlockChainTip, UTxO},
bitcoin::{BitcoinError, BitcoinInterface, BlockChainTip, UTxO},
config::{BitcoinConfig, Config},
database::{Coin, DatabaseConnection, DatabaseInterface, SpendBlock},
DaemonHandle,
@ -66,6 +66,10 @@ impl BitcoinInterface for DummyBitcoind {
fn common_ancestor(&self, _: &BlockChainTip) -> BlockChainTip {
todo!()
}
fn broadcast_tx(&self, _: &bitcoin::Transaction) -> Result<(), BitcoinError> {
todo!()
}
}
pub struct DummyDb {