]> Untitled Git - bdk/commitdiff
[keys] Implement `DerivableKey<Ctx>` for `(GeneratedKey<Mnemonic, Ctx>, Option<String>)`
authorAlekos Filini <alekos.filini@gmail.com>
Wed, 13 Apr 2022 10:37:27 +0000 (12:37 +0200)
committerAlekos Filini <alekos.filini@gmail.com>
Wed, 13 Apr 2022 10:37:27 +0000 (12:37 +0200)
This lets us use a tuple of (generated mnemonic, optional passphrase) as
a `DerivableKey` directly, without extracting the inner mnemonic from the
`GeneratedKey` wrapper. For BIP39 keys specifically it doesn't make much
difference because the mnemonic format doesn't encode the network, but in
general this is not the case and having a consistent API will make it
harder for people to make mistakes.

To explain why we should not extract the key: some key formats (like
BIP32 extended keys) are network-specific, meaning that if somebody
tries to use a Testnet key on a Mainnet BDK wallet, it won't work.

However, when we generate a new key we would like to be able to use that
key on any network, but we need to set some kind of placeholder for the
`network` field in the structure. This is why (or at least one of the
reasons why) we wrap the key in the `GeneratedKey` struct: we keep track
of the "valid_networks" separately, which means that even if we set our
BIP32 xprv to be a "Mainnet" key, once we go try creating a wallet with
that key BDK is smart enough to understand that `GeneratedKey`s have
their own separate set of valid networks and it will use that set to
validate whether the key can be used in the wallet or not.

src/keys/bip39.rs

index c6cf24fd49f5f76404d88c53ed2c2027cb045854..a8902a9fabae8d18473f4a804393398f63952885 100644 (file)
@@ -94,6 +94,23 @@ impl<Ctx: ScriptContext> DerivableKey<Ctx> for MnemonicWithPassphrase {
     }
 }
 
+#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
+impl<Ctx: ScriptContext> DerivableKey<Ctx> for (GeneratedKey<Mnemonic, Ctx>, Option<String>) {
+    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
+        let (mnemonic, passphrase) = self;
+        (mnemonic.into_key(), passphrase).into_extended_key()
+    }
+
+    fn into_descriptor_key(
+        self,
+        source: Option<bip32::KeySource>,
+        derivation_path: bip32::DerivationPath,
+    ) -> Result<DescriptorKey<Ctx>, KeyError> {
+        let (mnemonic, passphrase) = self;
+        (mnemonic.into_key(), passphrase).into_descriptor_key(source, derivation_path)
+    }
+}
+
 #[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
 impl<Ctx: ScriptContext> DerivableKey<Ctx> for Mnemonic {
     fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {