Skip to content

Commit

Permalink
feat: add finalize to Psbt
Browse files Browse the repository at this point in the history
  • Loading branch information
rustaceanrob committed Nov 16, 2024
1 parent 53f93ad commit c432e2d
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 0 deletions.
15 changes: 15 additions & 0 deletions bdk-ffi/src/bdk.udl
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,13 @@ interface PsbtParseError {
Base64Encoding(string error_message);
};

[Error]
interface PsbtFinalizeError {
InputError(string reason, u32 index);
WrongInputCount(u32 in_tx, u32 in_map);
InputIdxOutofBounds(u32 psbt_inp, u32 requested);
};

[Error]
interface RequestBuilderError {
RequestAlreadyConsumed();
Expand Down Expand Up @@ -958,9 +965,17 @@ interface Psbt {
[Throws=PsbtError]
Psbt combine(Psbt other);

FinalizedPsbtResult finalize();

string json_serialize();
};

dictionary FinalizedPsbtResult {
Psbt psbt;
boolean could_finalize;
sequence<PsbtFinalizeError>? errors;
};

dictionary TxIn {
OutPoint previous_output;
Script script_sig;
Expand Down
29 changes: 29 additions & 0 deletions bdk-ffi/src/bitcoin.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::error::PsbtFinalizeError;
use crate::error::{
AddressParseError, FromScriptError, PsbtError, PsbtParseError, TransactionError,
};
Expand All @@ -10,12 +11,14 @@ use bdk_wallet::bitcoin::consensus::encode::serialize;
use bdk_wallet::bitcoin::consensus::Decodable;
use bdk_wallet::bitcoin::io::Cursor;
use bdk_wallet::bitcoin::psbt::ExtractTxError;
use bdk_wallet::bitcoin::secp256k1::Secp256k1;
use bdk_wallet::bitcoin::Address as BdkAddress;
use bdk_wallet::bitcoin::Network;
use bdk_wallet::bitcoin::Psbt as BdkPsbt;
use bdk_wallet::bitcoin::Transaction as BdkTransaction;
use bdk_wallet::bitcoin::TxIn as BdkTxIn;
use bdk_wallet::bitcoin::TxOut as BdkTxOut;
use bdk_wallet::miniscript::psbt::PsbtExt;
use bdk_wallet::serde_json;

use std::fmt::Display;
Expand Down Expand Up @@ -188,6 +191,26 @@ impl Psbt {
Ok(Arc::new(Psbt(Mutex::new(original_psbt))))
}

pub(crate) fn finalize(&self) -> FinalizedPsbtResult {
let curve = Secp256k1::verification_only();
let finalized = self.0.lock().unwrap().clone().finalize(&curve);
match finalized {
Ok(psbt) => FinalizedPsbtResult {
psbt: Arc::new(psbt.into()),
could_finalize: true,
errors: None,
},
Err((psbt, errors)) => {
let errors = errors.into_iter().map(|e| e.into()).collect();
FinalizedPsbtResult {
psbt: Arc::new(psbt.into()),
could_finalize: false,
errors: Some(errors),
}
}
}
}

pub(crate) fn json_serialize(&self) -> String {
let psbt = self.0.lock().unwrap();
serde_json::to_string(psbt.deref()).unwrap()
Expand All @@ -200,6 +223,12 @@ impl From<BdkPsbt> for Psbt {
}
}

pub struct FinalizedPsbtResult {
pub psbt: Arc<Psbt>,
pub could_finalize: bool,
pub errors: Option<Vec<PsbtFinalizeError>>,
}

#[derive(Debug, Clone)]
pub struct TxIn {
pub previous_output: OutPoint,
Expand Down
34 changes: 34 additions & 0 deletions bdk-ffi/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use bdk_wallet::error::BuildFeeBumpError;
use bdk_wallet::error::CreateTxError as BdkCreateTxError;
use bdk_wallet::keys::bip39::Error as BdkBip39Error;
use bdk_wallet::miniscript::descriptor::DescriptorKeyParseError as BdkDescriptorKeyParseError;
use bdk_wallet::miniscript::psbt::Error as BdkPsbtFinalizeError;
use bdk_wallet::signer::SignerError as BdkSignerError;
use bdk_wallet::tx_builder::AddUtxoError;
use bdk_wallet::LoadWithPersistError as BdkLoadWithPersistError;
Expand Down Expand Up @@ -642,6 +643,16 @@ pub enum PsbtParseError {
Base64Encoding { error_message: String },
}

#[derive(Debug, thiserror::Error)]
pub enum PsbtFinalizeError {
#[error("an input at index {index} is invalid: {reason}")]
InputError { reason: String, index: u32 },
#[error("wrong input count; expected: {in_tx}, got: {in_map}")]
WrongInputCount { in_tx: u32, in_map: u32 },
#[error("input index out of bounds; inputs: {psbt_inp}, requested: {requested}")]
InputIdxOutofBounds { psbt_inp: u32, requested: u32 },
}

#[derive(Debug, thiserror::Error)]
pub enum SignerError {
#[error("missing key for signing")]
Expand Down Expand Up @@ -1344,6 +1355,29 @@ impl From<BdkPsbtParseError> for PsbtParseError {
}
}

impl From<BdkPsbtFinalizeError> for PsbtFinalizeError {
fn from(value: BdkPsbtFinalizeError) -> Self {
match value {
BdkPsbtFinalizeError::InputError(input_error, index) => PsbtFinalizeError::InputError {
reason: input_error.to_string(),
index: index as u32,
},
BdkPsbtFinalizeError::WrongInputCount { in_tx, in_map } => {
PsbtFinalizeError::WrongInputCount {
in_tx: in_tx as u32,
in_map: in_map as u32,
}
}
BdkPsbtFinalizeError::InputIdxOutofBounds { psbt_inp, index } => {
PsbtFinalizeError::InputIdxOutofBounds {
psbt_inp: psbt_inp as u32,
requested: index as u32,
}
}
}
}
}

impl From<BdkSignerError> for SignerError {
fn from(error: BdkSignerError) -> Self {
match error {
Expand Down
2 changes: 2 additions & 0 deletions bdk-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ mod types;
mod wallet;

use crate::bitcoin::Address;
use crate::bitcoin::FinalizedPsbtResult;
use crate::bitcoin::Psbt;
use crate::bitcoin::Transaction;
use crate::bitcoin::TxIn;
Expand All @@ -33,6 +34,7 @@ use crate::error::LoadWithPersistError;
use crate::error::MiniscriptError;
use crate::error::PersistenceError;
use crate::error::PsbtError;
use crate::error::PsbtFinalizeError;
use crate::error::PsbtParseError;
use crate::error::RequestBuilderError;
use crate::error::SignerError;
Expand Down

0 comments on commit c432e2d

Please sign in to comment.