Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions dash/examples/taproot-psbt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let tx_hex_string = encode::serialize_hex(&generate_bip86_key_spend_tx(
&secp,
// The master extended private key from the descriptor in step 4
ExtendedPrivKey::from_str(BENEFACTOR_XPRIV_STR)?,
&ExtendedPrivKey::from_str(BENEFACTOR_XPRIV_STR)?,
// Set these fields with valid data for the UTXO from step 5 above
UTXO_1,
vec![
Expand Down Expand Up @@ -231,7 +231,7 @@ struct P2trUtxo<'a> {

fn generate_bip86_key_spend_tx(
secp: &secp256k1::Secp256k1<secp256k1::All>,
master_xpriv: ExtendedPrivKey,
master_xpriv: &ExtendedPrivKey,
input_utxo: P2trUtxo,
outputs: Vec<TxOut>,
) -> Result<Transaction, Box<dyn std::error::Error>> {
Expand Down Expand Up @@ -430,7 +430,7 @@ impl BenefactorWallet {
// Spend a normal BIP86-like output as an input in our inheritance funding transaction
let tx = generate_bip86_key_spend_tx(
&self.secp,
self.master_xpriv,
&self.master_xpriv,
input_utxo,
vec![TxOut {
script_pubkey: script_pubkey.clone(),
Expand Down
30 changes: 28 additions & 2 deletions key-wallet/src/bip32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ use base58ck;
#[cfg(feature = "bincode")]
use bincode_derive::{Decode, Encode};
use dashcore::Network;
use zeroize::Zeroize;

/// XpubIdentifier as a hash160 result
type XpubIdentifier = hash160::Hash;
Expand Down Expand Up @@ -340,7 +341,7 @@ impl<'de> serde::Deserialize<'de> for Fingerprint {
}

/// Extended private key
#[derive(Copy, Clone, PartialEq, Eq)]
#[derive(Clone, PartialEq, Eq)]
pub struct ExtendedPrivKey {
/// The network this key is to be used on
pub network: Network,
Expand All @@ -356,6 +357,31 @@ pub struct ExtendedPrivKey {
pub chain_code: ChainCode,
}

// Hand-written (not `#[derive(Zeroize)]`): `secp256k1::SecretKey` has no
// `Zeroize` impl, only `non_secure_erase()`, so a derive would not compile.
// `Drop` (below) calls this, so the value is wiped automatically on scope exit
// with no caller action required. Cf. `RootExtendedPrivKey`.
impl zeroize::Zeroize for ExtendedPrivKey {
fn zeroize(&mut self) {
// Secret key material.
self.private_key.non_secure_erase();
self.chain_code.zeroize();
// Derivation metadata — cleared too so the whole value is wiped.
self.depth.zeroize();
self.parent_fingerprint.0.zeroize();
self.child_number = ChildNumber::Normal {
index: 0,
};
self.network = Network::Mainnet; // repr(u8)=0 discriminant, the "zero" value
}
}

impl Drop for ExtendedPrivKey {
fn drop(&mut self) {
self.zeroize();
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
}

#[cfg(feature = "bincode")]
impl bincode::Encode for ExtendedPrivKey {
fn encode<E: bincode::enc::Encoder>(
Expand Down Expand Up @@ -1522,7 +1548,7 @@ impl ExtendedPrivKey {
secp: &Secp256k1<C>,
path: &P,
) -> Result<ExtendedPrivKey, Error> {
let mut sk: ExtendedPrivKey = *self;
let mut sk: ExtendedPrivKey = self.clone();
for cnum in path.as_ref() {
sk = sk.ckd_priv(secp, *cnum)?;
}
Expand Down
5 changes: 3 additions & 2 deletions key-wallet/src/tests/account_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,11 +342,11 @@ fn test_account_extended_key_generation() {
let derivation_path = account_type.derivation_path(network).unwrap();
let account_key = master.derive_priv(&secp, &derivation_path).unwrap();

let expected_xpub = ExtendedPubKey::from_priv(&secp, &account_key);
let account = Account::from_xpriv(Some([0u8; 32]), account_type, account_key, network).unwrap();

// Verify extended public key can be derived
let xpub = account.extended_public_key();
let expected_xpub = ExtendedPubKey::from_priv(&secp, &account_key);
assert_eq!(xpub, expected_xpub);

// Verify the account can be created as watch-only
Expand Down Expand Up @@ -400,7 +400,8 @@ fn test_account_network_consistency() {
let derivation_path = account_type.derivation_path(network).unwrap();
let account_key = master.derive_priv(&secp, &derivation_path).unwrap();

let account = Account::from_xpriv(Some([0u8; 32]), account_type, account_key, network).unwrap();
let account =
Account::from_xpriv(Some([0u8; 32]), account_type, account_key.clone(), network).unwrap();

// Verify account stores the correct network
assert_eq!(account.network, network);
Expand Down
3 changes: 2 additions & 1 deletion key-wallet/src/tests/wallet_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ fn test_wallet_creation_from_extended_key() {
let seed = mnemonic.to_seed("");
let root_key = RootExtendedPrivKey::new_master(&seed).unwrap();
let master_key = root_key.to_extended_priv_key(Network::Testnet);
let master_private_key = master_key.private_key;

let wallet = Wallet::from_extended_key(
master_key,
Expand All @@ -113,7 +114,7 @@ fn test_wallet_creation_from_extended_key() {
// Verify extended key is stored
match &wallet.wallet_type {
WalletType::ExtendedPrivKey(wallet_key) => {
assert_eq!(wallet_key.root_private_key, master_key.private_key);
assert_eq!(wallet_key.root_private_key, master_private_key);
}
_ => panic!("Expected extended private key wallet type"),
}
Expand Down
Loading