diff --git a/Cargo.lock b/Cargo.lock
index 94585c46..96b341ce 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -64,6 +64,18 @@ version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445"
+[[package]]
+name = "bip39"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9e89470017230c38e52b82b3ee3f530db1856ba1d434e3a67a3456a8a8dec5f"
+dependencies = [
+ "bitcoin_hashes 0.9.7",
+ "rand_core 0.4.2",
+ "serde",
+ "unicode-normalization",
+]
+
[[package]]
name = "bitcoin"
version = "0.29.1"
@@ -71,11 +83,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cb36de3b18ad25f396f9168302e36fb7e1e8923298ab3127da252d288d5af9d"
dependencies = [
"bech32",
- "bitcoin_hashes",
+ "bitcoin_hashes 0.11.0",
"secp256k1",
"serde",
]
+[[package]]
+name = "bitcoin_hashes"
+version = "0.9.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ce18265ec2324ad075345d5814fbeed4f41f0a660055dc78840b74d19b874b1"
+
[[package]]
name = "bitcoin_hashes"
version = "0.11.0"
@@ -209,12 +227,15 @@ version = "0.2.0"
dependencies = [
"backtrace",
"base64",
+ "bip39",
"dirs",
"fern",
+ "getrandom",
"jsonrpc",
"libc",
"log",
"miniscript",
+ "rdrand",
"rusqlite",
"serde",
"serde_json",
@@ -247,6 +268,12 @@ dependencies = [
"cfg-if",
]
+[[package]]
+name = "maybe-uninit"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
+
[[package]]
name = "memchr"
version = "2.5.0"
@@ -310,6 +337,30 @@ dependencies = [
"proc-macro2",
]
+[[package]]
+name = "rand_core"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rdrand"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e233b642160555c1aa1ff7a78443c6139342f411b6fa6602af2ebbfee9e166bb"
+dependencies = [
+ "rand_core 0.6.4",
+]
+
[[package]]
name = "redox_syscall"
version = "0.2.16"
@@ -342,7 +393,7 @@ dependencies = [
"hashlink",
"libsqlite3-sys",
"memchr",
- "smallvec",
+ "smallvec 1.10.0",
]
[[package]]
@@ -363,7 +414,7 @@ version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7649a0b3ffb32636e60c7ce0d70511eda9c52c658cd0634e194d5a19943aeff"
dependencies = [
- "bitcoin_hashes",
+ "bitcoin_hashes 0.11.0",
"secp256k1-sys",
"serde",
]
@@ -408,6 +459,15 @@ dependencies = [
"serde",
]
+[[package]]
+name = "smallvec"
+version = "0.6.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0"
+dependencies = [
+ "maybe-uninit",
+]
+
[[package]]
name = "smallvec"
version = "1.10.0"
@@ -460,6 +520,15 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7"
+[[package]]
+name = "unicode-normalization"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09c8070a9942f5e7cfccd93f490fdebd230ee3c3c9f107cb25bad5351ef671cf"
+dependencies = [
+ "smallvec 0.6.14",
+]
+
[[package]]
name = "vcpkg"
version = "0.2.15"
diff --git a/Cargo.toml b/Cargo.toml
index c76325a7..e7161e75 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -56,3 +56,15 @@ libc = "0.2"
# Used for PSBTs
base64 = "0.13"
+
+# Used for generating mnemonics
+getrandom = "0.2"
+
+# Additional entropy for generating mnemonics
+[target.'cfg(target_arch = "x86")'.dependencies]
+rdrand = "0.8"
+[target.'cfg(target_arch = "x86_64")'.dependencies]
+rdrand = "0.8"
+
+# Used for the hot signer
+bip39 = "1.0"
diff --git a/src/lib.rs b/src/lib.rs
index fce5863e..8b1cc4c5 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -7,9 +7,12 @@ mod database;
pub mod descriptors;
#[cfg(feature = "jsonrpc_server")]
mod jsonrpc;
+mod random;
+pub mod signer;
#[cfg(test)]
mod testutils;
+pub use bip39;
pub use miniscript;
pub use crate::bitcoin::d::{BitcoindError, WalletError};
diff --git a/src/random.rs b/src/random.rs
new file mode 100644
index 00000000..b433ac2a
--- /dev/null
+++ b/src/random.rs
@@ -0,0 +1,128 @@
+use miniscript::bitcoin::hashes::{sha256, Hash, HashEngine};
+use std::{
+ collections::hash_map,
+ error, fmt,
+ hash::{BuildHasher, Hasher},
+ time::{SystemTime, UNIX_EPOCH},
+};
+
+#[derive(Debug)]
+pub enum RandomnessError {
+ Hardware(String),
+ Os(String),
+ ContextualInfo(String),
+}
+
+impl fmt::Display for RandomnessError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Self::Hardware(s) => write!(f, "Error when getting randomness from hardware: {}", s),
+ Self::Os(s) => write!(f, "Error when getting randomness from the OS: {}", s),
+ Self::ContextualInfo(s) => write!(f, "Error when getting contextual info: {}", s),
+ }
+ }
+}
+
+impl error::Error for RandomnessError {}
+
+// Get some entrop from RDRAND when available.
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+fn cpu_randomness() -> Result