]> Untitled Git - bdk/commitdiff
[keys] Less convoluted entropy generation
authorLLFourn <lloyd.fourn@gmail.com>
Tue, 29 Sep 2020 22:17:49 +0000 (08:17 +1000)
committerLLFourn <lloyd.fourn@gmail.com>
Wed, 30 Sep 2020 10:05:17 +0000 (20:05 +1000)
Since const generics aren't in rust yet you have to find some awkward
workarounds. This improves the workaround for specifying entropy length.

src/keys/bip39.rs
src/keys/mod.rs

index 96a5c3ef1c580551a2a59f0826d84a7736a7141d..5d446c91f0685af2e3070ac7f56b93352f775aed 100644 (file)
@@ -77,14 +77,14 @@ impl<Ctx: ScriptContext> DerivableKey<Ctx> for Mnemonic {
 }
 
 impl<Ctx: ScriptContext> GeneratableKey<Ctx> for Mnemonic {
-    const ENTROPY_LENGTH: usize = 32;
+    type Entropy = [u8; 32];
 
     type Options = (MnemonicType, Language);
     type Error = Option<bip39::ErrorKind>;
 
-    fn generate_with_entropy<E: AsRef<[u8]>>(
+    fn generate_with_entropy(
         (mnemonic_type, language): Self::Options,
-        entropy: E,
+        entropy: Self::Entropy,
     ) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
         let entropy = &entropy.as_ref()[..(mnemonic_type.entropy_bits() / 8)];
         let mnemonic = Mnemonic::from_entropy(entropy, language).map_err(|e| e.downcast().ok())?;
index a647699d4dd29096e2bbf2ac17ea6327ee02c91c..70e14829af9939bf1f97117c8dd6663b22a9aa4d 100644 (file)
@@ -370,8 +370,8 @@ where
 /// This trait is particularly useful when combined with [`DerivableKey`]: if `Self`
 /// implements it, the returned [`GeneratedKey`] will also implement it.
 pub trait GeneratableKey<Ctx: ScriptContext>: Sized {
-    /// Lenght in bytes of the required entropy
-    const ENTROPY_LENGTH: usize;
+    /// Type specifying the amount of entropy required e.g. [u8;32]
+    type Entropy: AsMut<[u8]> + Default;
 
     /// Extra options required by the `generate_with_entropy`
     type Options;
@@ -379,37 +379,32 @@ pub trait GeneratableKey<Ctx: ScriptContext>: Sized {
     type Error: std::fmt::Debug;
 
     /// Generate a key given the extra options and the entropy
-    fn generate_with_entropy<E: AsRef<[u8]>>(
+    fn generate_with_entropy(
         options: Self::Options,
-        entropy: E,
+        entropy: Self::Entropy,
     ) -> Result<GeneratedKey<Self, Ctx>, Self::Error>;
 
     /// Generate a key given the options with a random entropy
     fn generate(options: Self::Options) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
         use rand::{thread_rng, Rng};
 
-        let mut entropy = Vec::<u8>::with_capacity(Self::ENTROPY_LENGTH);
-        for _ in 0..Self::ENTROPY_LENGTH {
-            entropy.push(0x00);
-        }
-
-        thread_rng().fill(&mut entropy[..Self::ENTROPY_LENGTH]);
-
-        Self::generate_with_entropy(options, &entropy)
+        let mut entropy = Self::Entropy::default();
+        thread_rng().fill(entropy.as_mut());
+        Self::generate_with_entropy(options, entropy)
     }
 }
 
 impl<Ctx: ScriptContext> GeneratableKey<Ctx> for bip32::ExtendedPrivKey {
-    const ENTROPY_LENGTH: usize = 32;
+    type Entropy = [u8; 32];
 
     type Options = ();
     type Error = bip32::Error;
 
-    fn generate_with_entropy<E: AsRef<[u8]>>(
+    fn generate_with_entropy(
         _: Self::Options,
-        entropy: E,
+        entropy: Self::Entropy,
     ) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
-        // pick a random network here, but say that we support all of them
+        // pick a arbitrary network here, but say that we support all of them
         let xprv = bip32::ExtendedPrivKey::new_master(Network::Bitcoin, entropy.as_ref())?;
         Ok(GeneratedKey::new(xprv, any_network()))
     }
@@ -567,14 +562,12 @@ pub mod test {
 
     use super::*;
 
-    pub fn get_test_entropy() -> Vec<u8> {
-        [0xAA; 32].to_vec()
-    }
+    const test_entropy: [u8; 32] = [0xAA; 32];
 
     #[test]
     fn test_keys_generate_xprv() {
         let generated_xprv: GeneratedKey<_, miniscript::Segwitv0> =
-            bip32::ExtendedPrivKey::generate_with_entropy((), get_test_entropy()).unwrap();
+            bip32::ExtendedPrivKey::generate_with_entropy((), test_entropy).unwrap();
 
         assert_eq!(generated_xprv.valid_networks, any_network());
         assert_eq!(generated_xprv.to_string(), "xprv9s21ZrQH143K4Xr1cJyqTvuL2FWR8eicgY9boWqMBv8MDVUZ65AXHnzBrK1nyomu6wdcabRgmGTaAKawvhAno1V5FowGpTLVx3jxzE5uk3Q");