]> Untitled Git - bdk/commitdiff
fix(wallet): add expected descriptors as signers after creating from wallet::ChangeSet
authorSteve Myers <steve@notmandatory.org>
Tue, 16 Apr 2024 03:13:07 +0000 (22:13 -0500)
committerDaniela Brozzoni <danielabrozzoni@protonmail.com>
Wed, 8 May 2024 13:49:42 +0000 (15:49 +0200)
crates/bdk/src/wallet/mod.rs

index c2b8ad95a1315d5805ce3d777f687dc75622bd2e..35edf22566ff29a98a89f3b6264ad01e1c860bc7 100644 (file)
@@ -54,6 +54,7 @@ pub mod tx_builder;
 pub(crate) mod utils;
 
 pub mod error;
+
 pub use utils::IsDust;
 
 use coin_selection::DefaultCoinSelectionAlgorithm;
@@ -606,7 +607,7 @@ impl Wallet {
             .map_err(NewOrLoadError::Persist)?;
         match changeset {
             Some(changeset) => {
-                let wallet = Self::load_from_changeset(db, changeset).map_err(|e| match e {
+                let mut wallet = Self::load_from_changeset(db, changeset).map_err(|e| match e {
                     LoadError::Descriptor(e) => NewOrLoadError::Descriptor(e),
                     LoadError::Persist(e) => NewOrLoadError::Persist(e),
                     LoadError::NotInitialized => NewOrLoadError::NotInitialized,
@@ -636,35 +637,72 @@ impl Wallet {
                     });
                 }
 
-                let expected_descriptor = descriptor
+                let (expected_descriptor, expected_descriptor_keymap) = descriptor
                     .into_wallet_descriptor(&wallet.secp, network)
-                    .map_err(NewOrLoadError::Descriptor)?
-                    .0;
+                    .map_err(NewOrLoadError::Descriptor)?;
                 let wallet_descriptor = wallet.public_descriptor(KeychainKind::External).cloned();
-                if wallet_descriptor != Some(expected_descriptor) {
+                if wallet_descriptor != Some(expected_descriptor.clone()) {
                     return Err(NewOrLoadError::LoadedDescriptorDoesNotMatch {
                         got: wallet_descriptor,
                         keychain: KeychainKind::External,
                     });
                 }
+                // if expected descriptor has private keys add them as new signers
+                if !expected_descriptor_keymap.is_empty() {
+                    let signer_container = SignersContainer::build(
+                        expected_descriptor_keymap,
+                        &expected_descriptor,
+                        &wallet.secp,
+                    );
+                    signer_container.signers().into_iter().for_each(|signer| {
+                        wallet.add_signer(
+                            KeychainKind::External,
+                            SignerOrdering::default(),
+                            signer.clone(),
+                        )
+                    });
+                }
 
                 let expected_change_descriptor = if let Some(c) = change_descriptor {
                     Some(
                         c.into_wallet_descriptor(&wallet.secp, network)
-                            .map_err(NewOrLoadError::Descriptor)?
-                            .0,
+                            .map_err(NewOrLoadError::Descriptor)?,
                     )
                 } else {
                     None
                 };
                 let wallet_change_descriptor =
                     wallet.public_descriptor(KeychainKind::Internal).cloned();
-                if wallet_change_descriptor != expected_change_descriptor {
-                    return Err(NewOrLoadError::LoadedDescriptorDoesNotMatch {
-                        got: wallet_change_descriptor,
-                        keychain: KeychainKind::Internal,
-                    });
+
+                match (expected_change_descriptor, wallet_change_descriptor) {
+                    (Some((expected_descriptor, expected_keymap)), Some(wallet_descriptor))
+                        if wallet_descriptor == expected_descriptor =>
+                    {
+                        // if expected change descriptor has private keys add them as new signers
+                        if !expected_keymap.is_empty() {
+                            let signer_container = SignersContainer::build(
+                                expected_keymap,
+                                &expected_descriptor,
+                                &wallet.secp,
+                            );
+                            signer_container.signers().into_iter().for_each(|signer| {
+                                wallet.add_signer(
+                                    KeychainKind::Internal,
+                                    SignerOrdering::default(),
+                                    signer.clone(),
+                                )
+                            });
+                        }
+                    }
+                    (None, None) => (),
+                    (_, wallet_descriptor) => {
+                        return Err(NewOrLoadError::LoadedDescriptorDoesNotMatch {
+                            got: wallet_descriptor,
+                            keychain: KeychainKind::Internal,
+                        });
+                    }
                 }
+
                 Ok(wallet)
             }
             None => Self::new_with_genesis_hash(