Skip to content

Commit 03fb39c

Browse files
ValuedMammalluisschwab
authored andcommitted
fix: GeneratableKey options for PrivateKey, Xpriv
..to require the NetworkKind when generating the key. This fixes an issue where keys generated for mainnet were incorrectly marked valid for any network. test(keys): Add `test_xpriv_generate_options` fixes #22
1 parent 3e25aef commit 03fb39c

File tree

1 file changed

+67
-13
lines changed

1 file changed

+67
-13
lines changed

wallet/src/keys/mod.rs

Lines changed: 67 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use bitcoin::{
2727
bip32,
2828
key::XOnlyPublicKey,
2929
secp256k1::{self, Secp256k1, Signing},
30-
Network, NetworkKind, PrivateKey, PublicKey,
30+
NetworkKind, PrivateKey, PublicKey,
3131
};
3232
use miniscript::{
3333
descriptor::{Descriptor, DescriptorMultiXKey, DescriptorXKey, Wildcard},
@@ -621,7 +621,7 @@ pub trait GeneratableKey<Ctx: ScriptContext>: Sized {
621621
/// Type specifying the amount of entropy required e.g. `[u8;32]`
622622
type Entropy: AsMut<[u8]> + Default;
623623

624-
/// Extra options required by the `generate_with_entropy`
624+
/// Extra options required to generate the key.
625625
type Options;
626626
/// Returned error in case of failure
627627
type Error: core::fmt::Debug;
@@ -700,16 +700,35 @@ where
700700
impl<Ctx: ScriptContext> GeneratableKey<Ctx> for bip32::Xpriv {
701701
type Entropy = [u8; 32];
702702

703-
type Options = ();
703+
type Options = XprivGenerateOptions;
704704
type Error = bip32::Error;
705705

706706
fn generate_with_entropy(
707-
_: Self::Options,
707+
options: Self::Options,
708708
entropy: Self::Entropy,
709709
) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
710-
// Pick an arbitrary network kind here, but say that we support all of them.
711-
let xprv = bip32::Xpriv::new_master(NetworkKind::Main, entropy.as_ref())?;
712-
Ok(GeneratedKey::new(xprv, any_network_kind()))
710+
let (kind, valid_networks) = if options.network.is_mainnet() {
711+
(NetworkKind::Main, mainnet_network_kind())
712+
} else {
713+
(NetworkKind::Test, test_network_kind())
714+
};
715+
let xprv = bip32::Xpriv::new_master(kind, entropy.as_ref())?;
716+
Ok(GeneratedKey::new(xprv, valid_networks))
717+
}
718+
}
719+
720+
/// Options for generating a [`bip32::Xpriv`].
721+
#[derive(Debug, Copy, Clone)]
722+
pub struct XprivGenerateOptions {
723+
/// The network to be used when generating the xprv, default to `NetworkKind::Main`
724+
pub network: NetworkKind,
725+
}
726+
727+
impl Default for XprivGenerateOptions {
728+
fn default() -> Self {
729+
XprivGenerateOptions {
730+
network: NetworkKind::Main,
731+
}
713732
}
714733
}
715734

@@ -720,11 +739,16 @@ impl<Ctx: ScriptContext> GeneratableKey<Ctx> for bip32::Xpriv {
720739
pub struct PrivateKeyGenerateOptions {
721740
/// Whether the generated key should be "compressed" or not.
722741
pub compressed: bool,
742+
/// The kind of network to be used, defaults to `NetworkKind::Main`.
743+
pub network: NetworkKind,
723744
}
724745

725746
impl Default for PrivateKeyGenerateOptions {
726747
fn default() -> Self {
727-
PrivateKeyGenerateOptions { compressed: true }
748+
PrivateKeyGenerateOptions {
749+
compressed: true,
750+
network: NetworkKind::Main,
751+
}
728752
}
729753
}
730754

@@ -738,15 +762,19 @@ impl<Ctx: ScriptContext> GeneratableKey<Ctx> for PrivateKey {
738762
options: Self::Options,
739763
entropy: Self::Entropy,
740764
) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
741-
// pick a arbitrary network here, but say that we support all of them
742765
let inner = secp256k1::SecretKey::from_slice(&entropy)?;
743766
let private_key = PrivateKey {
744767
compressed: options.compressed,
745-
network: Network::Bitcoin.into(),
768+
network: options.network,
746769
inner,
747770
};
771+
let valid_networks = if private_key.network.is_mainnet() {
772+
mainnet_network_kind()
773+
} else {
774+
test_network_kind()
775+
};
748776

749-
Ok(GeneratedKey::new(private_key, any_network_kind()))
777+
Ok(GeneratedKey::new(private_key, valid_networks))
750778
}
751779
}
752780

@@ -1024,12 +1052,38 @@ mod test {
10241052

10251053
pub const TEST_ENTROPY: [u8; 32] = [0xAA; 32];
10261054

1055+
#[test]
1056+
fn test_xpriv_generate_options() {
1057+
use bitcoin::bip32::Xpriv;
1058+
let secp = SecpCtx::new();
1059+
// Test
1060+
let options = XprivGenerateOptions {
1061+
network: NetworkKind::Test,
1062+
};
1063+
let xpriv: GeneratedKey<Xpriv, miniscript::Segwitv0> = Xpriv::generate(options).unwrap();
1064+
let desc_key = xpriv
1065+
.into_descriptor_key(None, "m/84h/1h/0h".parse().unwrap())
1066+
.unwrap();
1067+
let desc_pk = desc_key.extract(&secp).unwrap().0;
1068+
assert!(desc_pk.to_string().contains("tpub"));
1069+
// Main
1070+
let options = XprivGenerateOptions {
1071+
network: NetworkKind::Main,
1072+
};
1073+
let xpriv: GeneratedKey<Xpriv, miniscript::Segwitv0> = Xpriv::generate(options).unwrap();
1074+
let desc_key = xpriv
1075+
.into_descriptor_key(None, "m/84h/1h/0h".parse().unwrap())
1076+
.unwrap();
1077+
let desc_pk = desc_key.extract(&secp).unwrap().0;
1078+
assert!(desc_pk.to_string().contains("xpub"));
1079+
}
1080+
10271081
#[test]
10281082
fn test_keys_generate_xprv() {
10291083
let generated_xprv: GeneratedKey<_, miniscript::Segwitv0> =
10301084
bip32::Xpriv::generate_with_entropy_default(TEST_ENTROPY).unwrap();
10311085

1032-
assert_eq!(generated_xprv.valid_network_kinds, any_network_kind());
1086+
assert_eq!(generated_xprv.valid_network_kinds, mainnet_network_kind());
10331087
assert_eq!(generated_xprv.to_string(), "xprv9s21ZrQH143K4Xr1cJyqTvuL2FWR8eicgY9boWqMBv8MDVUZ65AXHnzBrK1nyomu6wdcabRgmGTaAKawvhAno1V5FowGpTLVx3jxzE5uk3Q");
10341088
}
10351089

@@ -1038,7 +1092,7 @@ mod test {
10381092
let generated_wif: GeneratedKey<_, miniscript::Segwitv0> =
10391093
bitcoin::PrivateKey::generate_with_entropy_default(TEST_ENTROPY).unwrap();
10401094

1041-
assert_eq!(generated_wif.valid_network_kinds, any_network_kind());
1095+
assert_eq!(generated_wif.valid_network_kinds, mainnet_network_kind());
10421096
assert_eq!(
10431097
generated_wif.to_string(),
10441098
"L2wTu6hQrnDMiFNWA5na6jB12ErGQqtXwqpSL7aWquJaZG8Ai3ch"

0 commit comments

Comments
 (0)