Derive bitcoin private key from seed

This commit is contained in:
rishflab 2021-02-09 17:23:13 +11:00 committed by Daniel Karzel
parent 181e7c5096
commit 23cbee842f
3 changed files with 37 additions and 3 deletions

View File

@ -13,7 +13,6 @@ use backoff::{backoff::Constant as ConstantBackoff, tokio::retry};
use bdk::{
blockchain::{noop_progress, Blockchain, ElectrumBlockchain},
electrum_client::{Client, ElectrumApi},
keys::GeneratableDefaultOptions,
FeeRate,
};
use reqwest::{Method, Url};
@ -36,6 +35,7 @@ impl Wallet {
electrum_http_url: Url,
network: bitcoin::Network,
datadir: &Path,
p_key: bitcoin::PrivateKey,
) -> Result<Self> {
// todo: Implement conversion to anyhow::error so we can use ?
let client =
@ -43,8 +43,6 @@ impl Wallet {
let db = bdk::sled::open(datadir)?.open_tree(SLED_TREE_NAME)?;
// todo: make key generation configurable using a descriptor
let p_key = ::bitcoin::PrivateKey::generate_default()?;
let bdk_wallet = bdk::Wallet::new(
bdk::template::P2WPKH(p_key),
None,

View File

@ -19,6 +19,7 @@ use crate::{
},
execution_params::GetExecutionParams,
protocol::bob::cancel::CancelError,
seed::Seed,
};
use anyhow::{Context, Result};
use database::Database;
@ -97,6 +98,7 @@ async fn main() -> Result<()> {
bitcoin_network,
&wallet_data_dir,
monero_network,
seed,
)
.await?;
@ -139,6 +141,7 @@ async fn main() -> Result<()> {
bitcoin_network,
&wallet_data_dir,
monero_network,
seed,
)
.await?;
@ -188,6 +191,7 @@ async fn main() -> Result<()> {
bitcoin_network,
&wallet_data_dir,
monero_network,
seed,
)
.await?;
@ -216,6 +220,7 @@ async fn main() -> Result<()> {
bitcoin_network,
&wallet_data_dir,
monero_network,
seed,
)
.await?;
@ -247,6 +252,7 @@ async fn main() -> Result<()> {
bitcoin_network,
&wallet_data_dir,
monero_network,
seed,
)
.await?;
@ -297,6 +303,7 @@ async fn main() -> Result<()> {
bitcoin_network,
&wallet_data_dir,
monero_network,
seed,
)
.await?;
@ -334,6 +341,7 @@ async fn init_wallets(
bitcoin_network: bitcoin::Network,
bitcoin_wallet_data_dir: &Path,
monero_network: monero::Network,
seed: Seed,
) -> Result<(bitcoin::Wallet, monero::Wallet)> {
let config_path = if let Some(config_path) = config_path {
config_path
@ -354,6 +362,7 @@ async fn init_wallets(
config.bitcoin.electrum_http_url,
bitcoin_network,
bitcoin_wallet_data_dir,
seed.root_private_key(bitcoin_network),
)
.await?;
let bitcoin_balance = bitcoin_wallet.balance().await?;

View File

@ -1,4 +1,8 @@
use ::bitcoin::secp256k1::{self, constants::SECRET_KEY_SIZE, SecretKey};
use bitcoin::{
hashes::{sha512, Hash, HashEngine, Hmac, HmacEngine},
PrivateKey,
};
use rand::prelude::*;
use std::fmt;
@ -18,6 +22,29 @@ impl Seed {
Ok(Seed(bytes))
}
/// Return the private key and chain code to be used as root extended
/// private key for a BIP32 wallet.
pub fn root_private_key(&self, network: bitcoin::Network) -> PrivateKey {
let bytes = self.bytes();
// Yes, this is as per BIP32 and used in both Bitcoin and Ethereum ecosystems
let hash_key = b"Bitcoin seed";
let mut engine = HmacEngine::<sha512::Hash>::new(hash_key);
engine.input(&bytes);
let hash = Hmac::<sha512::Hash>::from_engine(engine);
let output = &hash.into_inner()[..];
let key = &output[..32];
let secret_key = SecretKey::from_slice(key).expect("32 bytes array should be fine");
PrivateKey {
compressed: true,
network,
key: secret_key,
}
}
pub fn bytes(&self) -> [u8; SEED_LENGTH] {
self.0
}