2020-10-16 12:58:35 +00:00
|
|
|
extern crate bitcoin;
|
|
|
|
|
|
|
|
use std::str::FromStr;
|
2022-06-06 03:57:02 +00:00
|
|
|
use std::{env, process};
|
2020-10-16 12:58:35 +00:00
|
|
|
|
2022-08-05 03:40:26 +00:00
|
|
|
use bitcoin::address::Address;
|
2023-08-21 22:03:55 +00:00
|
|
|
use bitcoin::bip32::{ChildNumber, DerivationPath, Xpriv, Xpub};
|
2023-07-21 00:38:34 +00:00
|
|
|
use bitcoin::hex::FromHex;
|
2022-06-06 03:57:02 +00:00
|
|
|
use bitcoin::secp256k1::ffi::types::AlignedType;
|
2020-10-16 12:58:35 +00:00
|
|
|
use bitcoin::secp256k1::Secp256k1;
|
2023-12-11 20:10:32 +00:00
|
|
|
use bitcoin::CompressedPublicKey;
|
2020-10-16 12:58:35 +00:00
|
|
|
|
|
|
|
fn main() {
|
2022-01-09 15:10:57 +00:00
|
|
|
// This example derives root xprv from a 32-byte seed,
|
2020-10-16 12:58:35 +00:00
|
|
|
// derives the child xprv with path m/84h/0h/0h,
|
|
|
|
// prints out corresponding xpub,
|
|
|
|
// calculates and prints out the first receiving segwit address.
|
2022-01-09 15:10:57 +00:00
|
|
|
// Run this example with cargo and seed(hex-encoded) argument:
|
|
|
|
// cargo run --example bip32 7934c09359b234e076b9fa5a1abfd38e3dc2a9939745b7cc3c22a48d831d14bd
|
2020-10-16 12:58:35 +00:00
|
|
|
|
|
|
|
let args: Vec<String> = env::args().collect();
|
|
|
|
if args.len() < 2 {
|
2022-01-09 15:10:57 +00:00
|
|
|
eprintln!("not enough arguments. usage: {} <hex-encoded 32-byte seed>", &args[0]);
|
2020-10-16 12:58:35 +00:00
|
|
|
process::exit(1);
|
|
|
|
}
|
|
|
|
|
2022-01-09 15:10:57 +00:00
|
|
|
let seed_hex = &args[1];
|
|
|
|
println!("Seed: {}", seed_hex);
|
2020-10-16 12:58:35 +00:00
|
|
|
|
2022-01-09 15:10:57 +00:00
|
|
|
// default network as mainnet
|
|
|
|
let network = bitcoin::Network::Bitcoin;
|
2020-10-16 12:58:35 +00:00
|
|
|
println!("Network: {:?}", network);
|
2022-01-09 15:10:57 +00:00
|
|
|
|
|
|
|
let seed = Vec::from_hex(seed_hex).unwrap();
|
2020-10-16 12:58:35 +00:00
|
|
|
|
|
|
|
// we need secp256k1 context for key derivation
|
2021-06-09 10:34:44 +00:00
|
|
|
let mut buf: Vec<AlignedType> = Vec::new();
|
|
|
|
buf.resize(Secp256k1::preallocate_size(), AlignedType::zeroed());
|
|
|
|
let secp = Secp256k1::preallocated_new(buf.as_mut_slice()).unwrap();
|
2020-10-16 12:58:35 +00:00
|
|
|
|
|
|
|
// calculate root key from seed
|
2023-08-21 22:03:55 +00:00
|
|
|
let root = Xpriv::new_master(network, &seed).unwrap();
|
2020-10-16 12:58:35 +00:00
|
|
|
println!("Root key: {}", root);
|
|
|
|
|
|
|
|
// derive child xpub
|
|
|
|
let path = DerivationPath::from_str("m/84h/0h/0h").unwrap();
|
|
|
|
let child = root.derive_priv(&secp, &path).unwrap();
|
|
|
|
println!("Child at {}: {}", path, child);
|
2023-08-21 22:03:55 +00:00
|
|
|
let xpub = Xpub::from_priv(&secp, &child);
|
2020-10-16 12:58:35 +00:00
|
|
|
println!("Public key at {}: {}", path, xpub);
|
|
|
|
|
|
|
|
// generate first receiving address at m/0/0
|
|
|
|
// manually creating indexes this time
|
|
|
|
let zero = ChildNumber::from_normal_idx(0).unwrap();
|
2023-02-21 17:22:44 +00:00
|
|
|
let public_key = xpub.derive_pub(&secp, &[zero, zero]).unwrap().public_key;
|
2023-12-11 20:10:32 +00:00
|
|
|
let address = Address::p2wpkh(&CompressedPublicKey(public_key), network);
|
2020-10-16 12:58:35 +00:00
|
|
|
println!("First receiving address: {}", address);
|
|
|
|
}
|