Skip to content

Commit

Permalink
feat: add json_serialize method on psbt type
Browse files Browse the repository at this point in the history
  • Loading branch information
thunderbiscuit committed May 29, 2024
1 parent 093eb1f commit 9790d60
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 88 deletions.
2 changes: 1 addition & 1 deletion bdk-ffi/src/bdk.udl
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ interface PsbtError {
Version(string error_message);
PartialDataConsumption();
Io(string error_message);
OtherPsbtError();
OtherPsbtErr();
};

[Error]
Expand Down
8 changes: 2 additions & 6 deletions bdk-ffi/src/bitcoin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,19 +222,15 @@ impl Psbt {
}

pub(crate) fn fee(&self) -> Result<u64, PsbtError> {
self
.0
self.0
.lock()
.unwrap()
.fee()
.map(|fee| fee.to_sat())
.map_err(PsbtError::from)
}

pub(crate) fn combine(
&self,
other: Arc<Psbt>,
) -> Result<Arc<Psbt>, PsbtError> {
pub(crate) fn combine(&self, other: Arc<Psbt>) -> Result<Arc<Psbt>, PsbtError> {
let mut original_psbt = self.0.lock().unwrap().clone();
let other_psbt = other.0.lock().unwrap().clone();
original_psbt.combine(other_psbt)?;
Expand Down
187 changes: 106 additions & 81 deletions bdk-ffi/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
use crate::bitcoin::{OutPoint};
use crate::bitcoin::OutPoint;

use bdk::bitcoin::address::Error as BdkAddressError;
use bdk::bitcoin::address::ParseError;
use bdk::bitcoin::amount::ParseAmountError as BdkParseAmountError;
use bdk::bitcoin::bip32::Error as BdkBip32Error;
use bdk::bitcoin::consensus::encode::Error as BdkEncodeError;
use bdk::bitcoin::psbt::Error as BdkPsbtError;
use bdk::bitcoin::psbt::ExtractTxError as BdkExtractTxError;
use bdk::bitcoin::psbt::PsbtParseError as BdkPsbtParseError;
use bdk::bitcoin::Network;
use bdk::bitcoin::psbt::Error as BdkPsbtError;
use bdk::chain::local_chain::CannotConnectError as BdkCannotConnectError;
use bdk::chain::tx_graph::CalculateFeeError as BdkCalculateFeeError;
use bdk::descriptor::DescriptorError as BdkDescriptorError;
use bdk::keys::bip39::Error as BdkBip39Error;
Expand All @@ -14,21 +19,12 @@ use bdk::wallet::error::CreateTxError as BdkCreateTxError;
use bdk::wallet::signer::SignerError as BdkSignerError;
use bdk::wallet::tx_builder::AddUtxoError;
use bdk::wallet::NewOrLoadError;
use bdk::KeychainKind;
use bdk_electrum::electrum_client::Error as BdkElectrumError;
use bdk_esplora::esplora_client::{Error as BdkEsploraError, Error};
use bdk_file_store::FileError as BdkFileError;
use bitcoin_internals::hex::display::DisplayHex;

use bdk::bitcoin::amount::ParseAmountError as BdkParseAmountError;

use std::convert::TryInto;

use bdk::bitcoin::address::Error as BdkAddressError;
use bdk::bitcoin::consensus::encode::Error as BdkEncodeError;
use bdk::bitcoin::psbt::ExtractTxError as BdkExtractTxError;
use bdk::chain::local_chain::CannotConnectError as BdkCannotConnectError;
use bdk::KeychainKind;

use std::convert::TryInto;

// ------------------------------------------------------------------------
Expand Down Expand Up @@ -436,17 +432,13 @@ pub enum PsbtError {
PsbtUtxoOutOfBounds,

#[error("invalid key: {key}")]
InvalidKey {
key: String,
},
InvalidKey { key: String },

#[error("non-proprietary key type found when proprietary key was expected")]
InvalidProprietaryKey,

#[error("duplicate key: {key}")]
DuplicateKey {
key: String,
},
DuplicateKey { key: String },

#[error("the unsigned transaction has script sigs")]
UnsignedTxHasScriptSigs,
Expand All @@ -465,28 +457,20 @@ pub enum PsbtError {
UnexpectedUnsignedTx,

#[error("non-standard sighash type: {sighash}")]
NonStandardSighashType {
sighash: u32,
},
NonStandardSighashType { sighash: u32 },

#[error("invalid hash when parsing slice: {hash}")]
InvalidHash {
hash: String,
},
InvalidHash { hash: String },

// Note: to provide the data returned in Rust, we need to dereference the fields
#[error("preimage does not match")]
InvalidPreimageHashPair,

#[error("combine conflict: {xpub}")]
CombineInconsistentKeySources {
xpub: String,
},
CombineInconsistentKeySources { xpub: String },

#[error("bitcoin consensus encoding error: {encoding_error}")]
ConsensusEncoding {
encoding_error: String,
},
ConsensusEncoding { encoding_error: String },

#[error("PSBT has a negative fee which is not allowed")]
NegativeFee,
Expand All @@ -495,27 +479,19 @@ pub enum PsbtError {
FeeOverflow,

#[error("invalid public key {error_message}")]
InvalidPublicKey {
error_message: String
},
InvalidPublicKey { error_message: String },

#[error("invalid secp256k1 public key: {secp256k1_error}")]
InvalidSecp256k1PublicKey {
secp256k1_error: String
},
InvalidSecp256k1PublicKey { secp256k1_error: String },

#[error("invalid xonly public key")]
InvalidXOnlyPublicKey,

#[error("invalid ECDSA signature: {error_message}")]
InvalidEcdsaSignature {
error_message: String
},
InvalidEcdsaSignature { error_message: String },

#[error("invalid taproot signature: {error_message}")]
InvalidTaprootSignature {
error_message: String
},
InvalidTaprootSignature { error_message: String },

#[error("invalid control block")]
InvalidControlBlock,
Expand All @@ -527,28 +503,22 @@ pub enum PsbtError {
Taproot,

#[error("taproot tree error: {error_message}")]
TapTree {
error_message: String
},
TapTree { error_message: String },

#[error("xpub key error")]
XPubKey,

#[error("version error: {error_message}")]
Version {
error_message: String
},
Version { error_message: String },

#[error("data not consumed entirely when explicitly deserializing")]
PartialDataConsumption,

#[error("I/O error: {error_message}")]
Io {
error_message: String
},
Io { error_message: String },

#[error("other PSBT error")]
OtherPsbtError,
OtherPsbtErr,
}

#[derive(Debug, thiserror::Error)]
Expand Down Expand Up @@ -1113,41 +1083,63 @@ impl From<BdkPsbtError> for PsbtError {
BdkPsbtError::MissingUtxo => PsbtError::MissingUtxo,
BdkPsbtError::InvalidSeparator => PsbtError::InvalidSeparator,
BdkPsbtError::PsbtUtxoOutOfbounds => PsbtError::PsbtUtxoOutOfBounds,
BdkPsbtError::InvalidKey(key) => PsbtError::InvalidKey { key: key.to_string() },
BdkPsbtError::InvalidKey(key) => PsbtError::InvalidKey {
key: key.to_string(),
},
BdkPsbtError::InvalidProprietaryKey => PsbtError::InvalidProprietaryKey,
BdkPsbtError::DuplicateKey(key) => PsbtError::DuplicateKey { key: key.to_string() },
BdkPsbtError::DuplicateKey(key) => PsbtError::DuplicateKey {
key: key.to_string(),
},
BdkPsbtError::UnsignedTxHasScriptSigs => PsbtError::UnsignedTxHasScriptSigs,
BdkPsbtError::UnsignedTxHasScriptWitnesses => PsbtError::UnsignedTxHasScriptWitnesses,
BdkPsbtError::MustHaveUnsignedTx => PsbtError::MustHaveUnsignedTx,
BdkPsbtError::NoMorePairs => PsbtError::NoMorePairs,
BdkPsbtError::UnexpectedUnsignedTx { .. } => PsbtError::UnexpectedUnsignedTx,
BdkPsbtError::NonStandardSighashType(sighash) => {
PsbtError::NonStandardSighashType { sighash }
}
BdkPsbtError::InvalidHash(hash) => PsbtError::InvalidHash {
hash: hash.to_string(),
},
BdkPsbtError::InvalidHash(hash) => PsbtError::InvalidHash { hash: hash.to_string() },
BdkPsbtError::InvalidPreimageHashPair { .. } => PsbtError::InvalidPreimageHashPair,
BdkPsbtError::CombineInconsistentKeySources(xpub) => {
PsbtError::CombineInconsistentKeySources { xpub: xpub.to_string() }
},
BdkPsbtError::ConsensusEncoding(encoding_error) => {
PsbtError::ConsensusEncoding { encoding_error: encoding_error.to_string() }
PsbtError::CombineInconsistentKeySources {
xpub: xpub.to_string(),
}
}
BdkPsbtError::ConsensusEncoding(encoding_error) => PsbtError::ConsensusEncoding {
encoding_error: encoding_error.to_string(),
},
BdkPsbtError::NegativeFee => PsbtError::NegativeFee,
BdkPsbtError::FeeOverflow => PsbtError::FeeOverflow,
BdkPsbtError::InvalidPublicKey(e) => PsbtError::InvalidPublicKey { error_message: e.to_string() },
BdkPsbtError::InvalidSecp256k1PublicKey(e) => PsbtError::InvalidSecp256k1PublicKey { secp256k1_error: e.to_string() },
BdkPsbtError::InvalidPublicKey(e) => PsbtError::InvalidPublicKey {
error_message: e.to_string(),
},
BdkPsbtError::InvalidSecp256k1PublicKey(e) => PsbtError::InvalidSecp256k1PublicKey {
secp256k1_error: e.to_string(),
},
BdkPsbtError::InvalidXOnlyPublicKey => PsbtError::InvalidXOnlyPublicKey,
BdkPsbtError::InvalidEcdsaSignature(e) => PsbtError::InvalidEcdsaSignature { error_message: e.to_string() },
BdkPsbtError::InvalidTaprootSignature(e) => PsbtError::InvalidTaprootSignature { error_message: e.to_string() },
BdkPsbtError::InvalidEcdsaSignature(e) => PsbtError::InvalidEcdsaSignature {
error_message: e.to_string(),
},
BdkPsbtError::InvalidTaprootSignature(e) => PsbtError::InvalidTaprootSignature {
error_message: e.to_string(),
},
BdkPsbtError::InvalidControlBlock => PsbtError::InvalidControlBlock,
BdkPsbtError::InvalidLeafVersion => PsbtError::InvalidLeafVersion,
BdkPsbtError::Taproot(_) => PsbtError::Taproot,
BdkPsbtError::TapTree(e) => PsbtError::TapTree { error_message: e.to_string() },
BdkPsbtError::TapTree(e) => PsbtError::TapTree {
error_message: e.to_string(),
},
BdkPsbtError::XPubKey(_) => PsbtError::XPubKey,
BdkPsbtError::Version(e) => PsbtError::Version { error_message: e.to_string() },
BdkPsbtError::Version(e) => PsbtError::Version {
error_message: e.to_string(),
},
BdkPsbtError::PartialDataConsumption => PsbtError::PartialDataConsumption,
BdkPsbtError::Io(e) => PsbtError::Io { error_message: e.to_string() },
_ => PsbtError::OtherPsbtError,
BdkPsbtError::Io(e) => PsbtError::Io {
error_message: e.to_string(),
},
_ => PsbtError::OtherPsbtErr,
}
}
}
Expand Down Expand Up @@ -1265,8 +1257,8 @@ mod test {
use crate::error::{
AddressError, Bip32Error, Bip39Error, CannotConnectError, CreateTxError, DescriptorError,
DescriptorKeyError, ElectrumError, EsploraError, ExtractTxError, FeeRateError,
InspectError, ParseAmountError, PersistenceError, PsbtParseError, TransactionError,
TxidParseError, WalletCreationError,
InspectError, ParseAmountError, PersistenceError, PsbtError, PsbtParseError,
TransactionError, TxidParseError, WalletCreationError,
};
use crate::CalculateFeeError;
use crate::OutPoint;
Expand Down Expand Up @@ -1933,30 +1925,51 @@ mod test {
fn test_error_psbt() {
let cases = vec![
(PsbtError::InvalidMagic, "invalid magic"),
(PsbtError::MissingUtxo, "UTXO information is not present in PSBT"),
(
PsbtError::MissingUtxo,
"UTXO information is not present in PSBT",
),
(PsbtError::InvalidSeparator, "invalid separator"),
(PsbtError::PsbtUtxoOutOfBounds, "output index is out of bounds of non witness script output array"),
(
PsbtError::PsbtUtxoOutOfBounds,
"output index is out of bounds of non witness script output array",
),
(
PsbtError::InvalidKey {
key: "key".to_string(),
},
"invalid key: key",
),
(PsbtError::InvalidProprietaryKey, "non-proprietary key type found when proprietary key was expected"),
(
PsbtError::InvalidProprietaryKey,
"non-proprietary key type found when proprietary key was expected",
),
(
PsbtError::DuplicateKey {
key: "key".to_string(),
},
"duplicate key: key",
),
(PsbtError::UnsignedTxHasScriptSigs, "the unsigned transaction has script sigs"),
(
PsbtError::UnsignedTxHasScriptSigs,
"the unsigned transaction has script sigs",
),
(
PsbtError::UnsignedTxHasScriptWitnesses,
"the unsigned transaction has script witnesses",
),
(PsbtError::MustHaveUnsignedTx, "partially signed transactions must have an unsigned transaction"),
(PsbtError::NoMorePairs, "no more key-value pairs for this psbt map"),
(PsbtError::UnexpectedUnsignedTx, "different unsigned transaction"),
(
PsbtError::MustHaveUnsignedTx,
"partially signed transactions must have an unsigned transaction",
),
(
PsbtError::NoMorePairs,
"no more key-value pairs for this psbt map",
),
(
PsbtError::UnexpectedUnsignedTx,
"different unsigned transaction",
),
(
PsbtError::NonStandardSighashType { sighash: 200 },
"non-standard sighash type: 200",
Expand All @@ -1967,7 +1980,10 @@ mod test {
},
"invalid hash when parsing slice: abcde",
),
(PsbtError::InvalidPreimageHashPair, "preimage does not match"),
(
PsbtError::InvalidPreimageHashPair,
"preimage does not match",
),
(
PsbtError::CombineInconsistentKeySources {
xpub: "xpub".to_string(),
Expand All @@ -1980,8 +1996,14 @@ mod test {
},
"bitcoin consensus encoding error: encoding error",
),
(PsbtError::NegativeFee, "PSBT has a negative fee which is not allowed"),
(PsbtError::FeeOverflow, "integer overflow in fee calculation"),
(
PsbtError::NegativeFee,
"PSBT has a negative fee which is not allowed",
),
(
PsbtError::FeeOverflow,
"integer overflow in fee calculation",
),
(
PsbtError::InvalidPublicKey {
error_message: "invalid public key".to_string(),
Expand Down Expand Up @@ -2023,14 +2045,17 @@ mod test {
},
"version error: version error",
),
(PsbtError::PartialDataConsumption, "data not consumed entirely when explicitly deserializing"),
(
PsbtError::PartialDataConsumption,
"data not consumed entirely when explicitly deserializing",
),
(
PsbtError::Io {
error_message: "io error".to_string(),
},
"I/O error: io error",
),
(PsbtError::OtherPsbtError, "other PSBT error"),
(PsbtError::OtherPsbtErr, "other PSBT error"),
];

for (error, expected_message) in cases {
Expand Down

0 comments on commit 9790d60

Please sign in to comment.