Skip to content
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
38 changes: 38 additions & 0 deletions bdk-ffi/src/tests/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,3 +150,41 @@ fn test_create_two_path_wallet() {
assert_eq!(wallet.derivation_index(KeychainKind::External), Some(0));
assert_eq!(wallet.derivation_index(KeychainKind::Internal), Some(0));
}

#[test]
fn test_load_from_two_path_descriptor() {
let persister = Arc::new(Persister::new_in_memory().unwrap());
let wallet = Wallet::create_from_two_path_descriptor(
two_path_descriptor(),
Network::Signet,
Arc::clone(&persister),
25,
)
.unwrap();

wallet.reveal_next_address(KeychainKind::External);
wallet.reveal_next_address(KeychainKind::Internal);
assert!(wallet.persist(Arc::clone(&persister)).unwrap());

let loaded_wallet =
Wallet::load_from_two_path_descriptor(two_path_descriptor(), Arc::clone(&persister), 25)
.unwrap();

assert_eq!(loaded_wallet.network(), Network::Signet);
assert_eq!(
loaded_wallet.derivation_index(KeychainKind::External),
Some(0)
);
assert_eq!(
loaded_wallet.derivation_index(KeychainKind::Internal),
Some(0)
);
assert_eq!(
loaded_wallet.next_derivation_index(KeychainKind::External),
1
);
assert_eq!(
loaded_wallet.next_derivation_index(KeychainKind::Internal),
1
);
}
39 changes: 36 additions & 3 deletions bdk-ffi/src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,18 @@ impl Wallet {

/// Build a new `Wallet` from a two-path descriptor.
///
/// This function parses a multipath descriptor with exactly 2 paths and creates a wallet using the existing receive and change wallet creation logic.
/// This function parses a multipath descriptor with exactly 2 paths and creates a wallet
/// using the existing receive and change wallet creation logic.
///
/// Multipath descriptors follow [BIP-389](https://github.com/bitcoin/bips/blob/master/bip-0389.mediawiki) and allow defining both receive and change derivation paths in a single descriptor using the <0;1> syntax.
/// The provided descriptor may only contain extended public keys (`xpub`) with exactly 2 paths.
///
/// Multipath descriptors follow [BIP-389](https://github.com/bitcoin/bips/blob/master/bip-0389.mediawiki)
/// and allow defining both receive and change derivation paths in a single descriptor using
/// the `<0;1>` syntax.
///
/// If you have previously created a wallet, use load instead.
///
/// Returns an error if the descriptor is invalid or not a 2-path multipath descriptor.
/// Returns an error if the descriptor is not a 2-path multipath descriptor.
#[uniffi::constructor(default(lookahead = 25))]
pub fn create_from_two_path_descriptor(
two_path_descriptor: Arc<Descriptor>,
Expand Down Expand Up @@ -168,6 +173,34 @@ impl Wallet {
})
}

/// Build a two-path descriptor `Wallet` by loading from persistence.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merged yesterday was an update to the API docs for this. See bitcoindevkit/bdk_wallet@77a727d

They now read:

/// The provided descriptor may only contain extended public keys (`xpub`) with exactly 2 paths,
/// or an error will occur at load time.

In our case you can't use that sentence directly because it's just pure impossible to create the Descriptor with private keys so you won't "error at load time", but I would use the first part:

/// The provided descriptor may only contain extended public keys (`xpub`) with exactly 2 paths

Note that this goes away with miniscript 13 so bdk_wallet 4.0. Issue here: bitcoindevkit/bdk_wallet#511.

///
/// Checks that the provided two-path descriptor matches exactly what is loaded
/// for both the external and internal keychains.
///
/// The provided descriptor may only contain extended public keys (`xpub`) with exactly 2 paths.
#[uniffi::constructor(default(lookahead = 25))]
pub fn load_from_two_path_descriptor(
two_path_descriptor: Arc<Descriptor>,
persister: Arc<Persister>,
lookahead: u32,
) -> Result<Wallet, LoadWithPersistError> {
let descriptor = two_path_descriptor.to_string();
let mut persist_lock = persister.inner.lock().unwrap();
let deref = persist_lock.deref_mut();

let wallet: PersistedWallet<PersistenceType> = BdkWallet::load()
.two_path_descriptor(descriptor)
.lookahead(lookahead)
.load_wallet(deref)
.map_err(LoadWithPersistError::from)?
.ok_or(LoadWithPersistError::CouldNotLoad)?;

Ok(Wallet {
inner_mutex: Mutex::new(wallet),
})
}

/// Build a single-descriptor Wallet by loading from persistence.
///
/// Note that the descriptor secret keys are not persisted to the db.
Expand Down
Loading