commands: a new command for broadcasting a Spend transaction
This commit is contained in:
parent
b14bc602d4
commit
37ee93a1e6
@ -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)]
|
||||
|
||||
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user