From 7d1954c131d9f7fcea2ef5c468c2f5a2f20b8afd Mon Sep 17 00:00:00 2001 From: Luis Schwab Date: Sun, 9 Mar 2025 20:29:40 -0300 Subject: [PATCH 1/5] feat: implement Display for KeychainKind --- crates/wallet/src/types.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/crates/wallet/src/types.rs b/crates/wallet/src/types.rs index 54ddfa261..72c0e453d 100644 --- a/crates/wallet/src/types.rs +++ b/crates/wallet/src/types.rs @@ -12,6 +12,7 @@ use alloc::boxed::Box; use chain::{ChainPosition, ConfirmationBlockTime}; use core::convert::AsRef; +use core::fmt; use bitcoin::transaction::{OutPoint, Sequence, TxOut}; use bitcoin::{psbt, Weight}; @@ -37,6 +38,15 @@ impl KeychainKind { } } +impl fmt::Display for KeychainKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + KeychainKind::External => write!(f, "External"), + KeychainKind::Internal => write!(f, "Internal"), + } + } +} + impl AsRef<[u8]> for KeychainKind { fn as_ref(&self) -> &[u8] { match self { From 70d42edbaac6ba2e497fb62e6284969f7ee73663 Mon Sep 17 00:00:00 2001 From: Luis Schwab Date: Sun, 9 Mar 2025 20:30:24 -0300 Subject: [PATCH 2/5] feat: implement Display for LoadMismatch --- crates/wallet/src/wallet/mod.rs | 38 +++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/crates/wallet/src/wallet/mod.rs b/crates/wallet/src/wallet/mod.rs index e4dc6d056..d3cb7ac33 100644 --- a/crates/wallet/src/wallet/mod.rs +++ b/crates/wallet/src/wallet/mod.rs @@ -232,6 +232,44 @@ pub enum LoadMismatch { }, } +impl fmt::Display for LoadMismatch { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + LoadMismatch::Network { loaded, expected } => { + write!( + f, + "Network mismatch: loaded {}, expected {}", + loaded, expected + ) + } + LoadMismatch::Genesis { loaded, expected } => { + write!( + f, + "Genesis hash mismatch: loaded {}, expected {}", + loaded, expected + ) + } + LoadMismatch::Descriptor { + keychain, + loaded, + expected, + } => { + write!( + f, + "Descriptor mismatch for {} keychain: loaded {}, expected {}", + keychain, + loaded + .as_ref() + .map_or("None".to_string(), |d| d.to_string()), + expected + .as_ref() + .map_or("None".to_string(), |d| d.to_string()) + ) + } + } + } +} + impl From for LoadError { fn from(mismatch: LoadMismatch) -> Self { Self::Mismatch(mismatch) From 763ead16e1dea38f7814b4ff829e8d598e32a366 Mon Sep 17 00:00:00 2001 From: Luis Schwab Date: Sun, 9 Mar 2025 20:31:00 -0300 Subject: [PATCH 3/5] fix: no Debug on LoadError --- crates/wallet/src/wallet/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/wallet/src/wallet/mod.rs b/crates/wallet/src/wallet/mod.rs index d3cb7ac33..513552918 100644 --- a/crates/wallet/src/wallet/mod.rs +++ b/crates/wallet/src/wallet/mod.rs @@ -194,9 +194,9 @@ impl fmt::Display for LoadError { LoadError::MissingNetwork => write!(f, "loaded data is missing network type"), LoadError::MissingGenesis => write!(f, "loaded data is missing genesis hash"), LoadError::MissingDescriptor(k) => { - write!(f, "loaded data is missing descriptor for keychain {k:?}") + write!(f, "loaded data is missing descriptor for {k} keychain") } - LoadError::Mismatch(mismatch) => write!(f, "data mismatch: {mismatch:?}"), + LoadError::Mismatch(e) => write!(f, "{e}"), } } } From ffa857d8fbb42f3b76f62fc3fc6195e5df4e5477 Mon Sep 17 00:00:00 2001 From: Luis Schwab Date: Thu, 13 Mar 2025 15:42:20 -0300 Subject: [PATCH 4/5] fix: remove Debugs from CreateTxError --- crates/wallet/src/wallet/error.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/wallet/src/wallet/error.rs b/crates/wallet/src/wallet/error.rs index adce5b188..e736c5a43 100644 --- a/crates/wallet/src/wallet/error.rs +++ b/crates/wallet/src/wallet/error.rs @@ -112,7 +112,7 @@ impl fmt::Display for CreateTxError { Self::Descriptor(e) => e.fmt(f), Self::Policy(e) => e.fmt(f), CreateTxError::SpendingPolicyRequired(keychain_kind) => { - write!(f, "Spending policy required: {:?}", keychain_kind) + write!(f, "Spending policy required: {}", keychain_kind) } CreateTxError::Version0 => { write!(f, "Invalid version `0`") @@ -127,12 +127,12 @@ impl fmt::Display for CreateTxError { requested, required, } => { - write!(f, "TxBuilder requested timelock of `{:?}`, but at least `{:?}` is required to spend from this script", required, requested) + write!(f, "TxBuilder requested timelock of `{}`, but at least `{}` is required to spend from this script", required, requested) } CreateTxError::RbfSequenceCsv { sequence, csv } => { write!( f, - "Cannot enable RBF with nSequence `{:?}` given a required OP_CSV of `{:?}`", + "Cannot enable RBF with nSequence `{}` given a required OP_CSV of `{}`", sequence, csv ) } From 32d470bcc6a7cf1e1e7ae94c38c54dc7af7c0201 Mon Sep 17 00:00:00 2001 From: Luis Schwab Date: Fri, 21 Mar 2025 16:10:04 -0300 Subject: [PATCH 5/5] feat: add error messages for CreateWithPersistError Display implementation --- crates/wallet/src/wallet/persisted.rs | 46 +++++++++++++++++++++------ 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/crates/wallet/src/wallet/persisted.rs b/crates/wallet/src/wallet/persisted.rs index 1bc0a7884..b3ad1090a 100644 --- a/crates/wallet/src/wallet/persisted.rs +++ b/crates/wallet/src/wallet/persisted.rs @@ -6,10 +6,16 @@ use core::{ pin::Pin, }; -use alloc::boxed::Box; +use alloc::{ + boxed::Box, + string::{String, ToString}, +}; use chain::Merge; -use crate::{descriptor::DescriptorError, ChangeSet, CreateParams, LoadParams, Wallet}; +use crate::{ + descriptor::{calc_checksum, DescriptorError}, + ChangeSet, CreateParams, LoadParams, Wallet, +}; /// Trait that persists [`PersistedWallet`]. /// @@ -363,16 +369,38 @@ pub enum CreateWithPersistError { impl fmt::Display for CreateWithPersistError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Self::Persist(err) => fmt::Display::fmt(err, f), - Self::DataAlreadyExists(changeset) => write!( - f, - "Cannot create wallet in persister which already contains wallet data: {:?}", - changeset - ), - Self::Descriptor(err) => fmt::Display::fmt(&err, f), + Self::Persist(err) => write!(f, "Persistence error: {}", err), + Self::DataAlreadyExists(changeset) => { + write!(f, "{}", changeset_info(changeset)) + } + Self::Descriptor(err) => { + write!(f, "{err}") + } } } } +/// Helper function to write basic fingerprinting information about a changeset +fn changeset_info(changeset: &ChangeSet) -> String { + let network = match &changeset.network { + Some(network) => network.to_string(), + None => "None".to_string(), + }; + let external_checksum = match &changeset.descriptor { + Some(descriptor) => calc_checksum(&descriptor.to_string()).unwrap(), + None => "[no external descriptor in the changeset]".to_string(), + }; + let internal_checksum = match &changeset.change_descriptor { + Some(descriptor) => calc_checksum(&descriptor.to_string()).unwrap(), + None => "[no internal descriptor in the changeset]".to_string(), + }; + + format!( + "Cannot create wallet in a persister which already contains wallet data: \ + Network: {}, External Descriptor Checksum: {}, Internal Descriptor Checksum: {}", + network, external_checksum, internal_checksum + ) +} + #[cfg(feature = "std")] impl std::error::Error for CreateWithPersistError {}