commands: a new command for broadcasting a Spend transaction

This commit is contained in:
Antoine Poinsot 2022-10-17 15:49:11 +02:00
parent b14bc602d4
commit 37ee93a1e6
No known key found for this signature in database
GPG Key ID: E13FC145CD3F4304
2 changed files with 42 additions and 2 deletions

View File

@ -5,7 +5,7 @@
mod utils;
use crate::{
bitcoin::BitcoinInterface,
bitcoin::{BitcoinError, BitcoinInterface},
database::{Coin, DatabaseInterface},
descriptors, DaemonControl, VERSION,
};
@ -50,6 +50,10 @@ pub enum CommandError {
/* target feerate */ u64,
),
SanityCheckFailure(Psbt),
UnknownSpend(bitcoin::Txid),
// FIXME: when upgrading Miniscript put the actual error there
SpendFinalization(String),
TxBroadcast(String),
}
impl fmt::Display for CommandError {
@ -71,6 +75,11 @@ impl fmt::Display for CommandError {
"BUG! Please report this. Failed sanity checks for PSBT '{:?}'.",
psbt
),
Self::UnknownSpend(txid) => write!(f, "Unknown spend transaction '{}'.", txid),
Self::SpendFinalization(e) => {
write!(f, "Failed to finalize the spend transaction PSBT: '{}'.", e)
}
Self::TxBroadcast(e) => write!(f, "Failed to broadcast transaction: '{}'.", e),
}
}
}
@ -446,6 +455,28 @@ impl DaemonControl {
let mut db_conn = self.db.connection();
db_conn.delete_spend(txid);
}
/// Finalize and broadcast this stored Spend transaction.
pub fn broadcast_spend(&self, txid: &bitcoin::Txid) -> Result<(), CommandError> {
let mut db_conn = self.db.connection();
// First, try to finalize the spending transaction with the elements contained
// in the PSBT.
let mut spend_psbt = db_conn
.spend_tx(txid)
.ok_or(CommandError::UnknownSpend(*txid))?;
log::debug!("B");
miniscript::psbt::finalize(&mut spend_psbt, &self.secp)
.map_err(|e| CommandError::SpendFinalization(e.to_string()))?;
// Then, broadcast it (or try to, we never know if we are not going to hit an
// error at broadcast time).
let final_tx = spend_psbt.extract_tx();
match self.bitcoin.broadcast_tx(&final_tx) {
Ok(()) => Ok(()),
Err(BitcoinError::Broadcast(e)) => Err(CommandError::TxBroadcast(e)),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]

View File

@ -51,6 +51,9 @@ pub struct Request {
pub id: ReqId,
}
/// A failure to broadcast a transaction to the P2P network.
const BROADCAST_ERROR: i64 = 1_000;
/// JSONRPC2 error codes. See https://www.jsonrpc.org/specification#error_object.
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ErrorCode {
@ -80,6 +83,7 @@ impl From<i64> for ErrorCode {
match code {
-32601 => ErrorCode::MethodNotFound,
-32602 => ErrorCode::InvalidParams,
-32603 => ErrorCode::InternalError,
code => ErrorCode::ServerError(code),
}
}
@ -153,12 +157,17 @@ impl From<commands::CommandError> for Error {
| commands::CommandError::InvalidFeerate(..)
| commands::CommandError::AlreadySpent(..)
| commands::CommandError::InvalidOutputValue(..)
| commands::CommandError::InsufficientFunds(..) => {
| commands::CommandError::InsufficientFunds(..)
| commands::CommandError::UnknownSpend(..)
| commands::CommandError::SpendFinalization(..) => {
Error::new(ErrorCode::InvalidParams, e.to_string())
}
commands::CommandError::SanityCheckFailure(_) => {
Error::new(ErrorCode::InternalError, e.to_string())
}
commands::CommandError::TxBroadcast(_) => {
Error::new(ErrorCode::ServerError(BROADCAST_ERROR), e.to_string())
}
}
}
}