Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add finalize to Psbt #630

Merged
merged 1 commit into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading