bip32: derive_xpriv should not return a Result

This commit is contained in:
Jose Storopoli 2024-05-12 08:49:14 +00:00
parent 0d627326ce
commit d353be4546
No known key found for this signature in database
GPG Key ID: 29E00111DE172C28
6 changed files with 21 additions and 26 deletions

View File

@ -41,7 +41,7 @@ fn main() {
// derive child xpub // derive child xpub
let path = DerivationPath::from_str("84h/0h/0h").unwrap(); let path = DerivationPath::from_str("84h/0h/0h").unwrap();
let child = root.derive_priv(&secp, &path).unwrap(); let child = root.derive_priv(&secp, &path);
println!("Child at {}: {}", path, child); println!("Child at {}: {}", path, child);
let xpub = Xpub::from_priv(&secp, &child); let xpub = Xpub::from_priv(&secp, &child);
println!("Public key at {}: {}", path, xpub); println!("Public key at {}: {}", path, xpub);

View File

@ -116,11 +116,11 @@ impl ColdStorage {
// Hardened children require secret data to derive. // Hardened children require secret data to derive.
let path = "84h/0h/0h".into_derivation_path()?; let path = "84h/0h/0h".into_derivation_path()?;
let account_0_xpriv = master_xpriv.derive_priv(secp, &path)?; let account_0_xpriv = master_xpriv.derive_priv(secp, &path);
let account_0_xpub = Xpub::from_priv(secp, &account_0_xpriv); let account_0_xpub = Xpub::from_priv(secp, &account_0_xpriv);
let path = INPUT_UTXO_DERIVATION_PATH.into_derivation_path()?; let path = INPUT_UTXO_DERIVATION_PATH.into_derivation_path()?;
let input_xpriv = master_xpriv.derive_priv(secp, &path)?; let input_xpriv = master_xpriv.derive_priv(secp, &path);
let input_xpub = Xpub::from_priv(secp, &input_xpriv); let input_xpub = Xpub::from_priv(secp, &input_xpriv);
let wallet = ColdStorage { master_xpriv, master_xpub }; let wallet = ColdStorage { master_xpriv, master_xpub };

View File

@ -296,7 +296,7 @@ fn generate_bip86_key_spend_tx(
.get(&input.tap_internal_key.ok_or("Internal key missing in PSBT")?) .get(&input.tap_internal_key.ok_or("Internal key missing in PSBT")?)
.ok_or("Missing taproot key origin")?; .ok_or("Missing taproot key origin")?;
let secret_key = master_xpriv.derive_priv(secp, &derivation_path)?.to_priv().inner; let secret_key = master_xpriv.derive_priv(secp, &derivation_path).to_priv().inner;
sign_psbt_taproot( sign_psbt_taproot(
&secret_key, &secret_key,
input.tap_internal_key.unwrap(), input.tap_internal_key.unwrap(),
@ -391,7 +391,7 @@ impl BenefactorWallet {
// that we use an unhardened path so we can make use of xpubs. // that we use an unhardened path so we can make use of xpubs.
let derivation_path = DerivationPath::from_str(&format!("101/1/0/0/{}", self.next))?; let derivation_path = DerivationPath::from_str(&format!("101/1/0/0/{}", self.next))?;
let internal_keypair = let internal_keypair =
self.master_xpriv.derive_priv(&self.secp, &derivation_path)?.to_keypair(&self.secp); self.master_xpriv.derive_priv(&self.secp, &derivation_path).to_keypair(&self.secp);
let beneficiary_key = let beneficiary_key =
self.beneficiary_xpub.derive_pub(&self.secp, &derivation_path)?.to_x_only_pub(); self.beneficiary_xpub.derive_pub(&self.secp, &derivation_path)?.to_x_only_pub();
@ -481,7 +481,7 @@ impl BenefactorWallet {
DerivationPath::from_str(&format!("101/1/0/0/{}", self.next))?; DerivationPath::from_str(&format!("101/1/0/0/{}", self.next))?;
let new_internal_keypair = self let new_internal_keypair = self
.master_xpriv .master_xpriv
.derive_priv(&self.secp, &new_derivation_path)? .derive_priv(&self.secp, &new_derivation_path)
.to_keypair(&self.secp); .to_keypair(&self.secp);
let beneficiary_key = let beneficiary_key =
self.beneficiary_xpub.derive_pub(&self.secp, &new_derivation_path)?.to_x_only_pub(); self.beneficiary_xpub.derive_pub(&self.secp, &new_derivation_path)?.to_x_only_pub();
@ -530,7 +530,7 @@ impl BenefactorWallet {
.get(&input.tap_internal_key.ok_or("Internal key missing in PSBT")?) .get(&input.tap_internal_key.ok_or("Internal key missing in PSBT")?)
.ok_or("Missing taproot key origin")?; .ok_or("Missing taproot key origin")?;
let secret_key = let secret_key =
self.master_xpriv.derive_priv(&self.secp, &derivation_path)?.to_priv().inner; self.master_xpriv.derive_priv(&self.secp, &derivation_path).to_priv().inner;
sign_psbt_taproot( sign_psbt_taproot(
&secret_key, &secret_key,
spend_info.internal_key(), spend_info.internal_key(),
@ -651,7 +651,7 @@ impl BeneficiaryWallet {
&psbt.inputs[0].tap_key_origins.clone() &psbt.inputs[0].tap_key_origins.clone()
{ {
let secret_key = let secret_key =
self.master_xpriv.derive_priv(&self.secp, &derivation_path)?.to_priv().inner; self.master_xpriv.derive_priv(&self.secp, &derivation_path).to_priv().inner;
for lh in leaf_hashes { for lh in leaf_hashes {
let sighash_type = TapSighashType::All; let sighash_type = TapSighashType::All;
let hash = SighashCache::new(&unsigned_tx).taproot_script_spend_signature_hash( let hash = SighashCache::new(&unsigned_tx).taproot_script_spend_signature_hash(

View File

@ -583,27 +583,23 @@ impl Xpriv {
.expect("BIP32 internal private key representation is broken") .expect("BIP32 internal private key representation is broken")
} }
/// Attempts to derive an extended private key from a path. /// Derives an extended private key from a path.
/// ///
/// The `path` argument can be both of type `DerivationPath` or `Vec<ChildNumber>`. /// The `path` argument can be both of type `DerivationPath` or `Vec<ChildNumber>`.
pub fn derive_priv<C: secp256k1::Signing, P: AsRef<[ChildNumber]>>( pub fn derive_priv<C: secp256k1::Signing, P: AsRef<[ChildNumber]>>(
&self, &self,
secp: &Secp256k1<C>, secp: &Secp256k1<C>,
path: &P, path: &P,
) -> Result<Xpriv, Error> { ) -> Xpriv {
let mut sk: Xpriv = *self; let mut sk: Xpriv = *self;
for cnum in path.as_ref() { for cnum in path.as_ref() {
sk = sk.ckd_priv(secp, *cnum)?; sk = sk.ckd_priv(secp, *cnum)
} }
Ok(sk) sk
} }
/// Private->Private child key derivation /// Private->Private child key derivation
fn ckd_priv<C: secp256k1::Signing>( fn ckd_priv<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>, i: ChildNumber) -> Xpriv {
&self,
secp: &Secp256k1<C>,
i: ChildNumber,
) -> Result<Xpriv, Error> {
let mut hmac_engine: HmacEngine<sha512::Hash> = HmacEngine::new(&self.chain_code[..]); let mut hmac_engine: HmacEngine<sha512::Hash> = HmacEngine::new(&self.chain_code[..]);
match i { match i {
ChildNumber::Normal { .. } => { ChildNumber::Normal { .. } => {
@ -626,14 +622,14 @@ impl Xpriv {
let tweaked = let tweaked =
sk.add_tweak(&self.private_key.into()).expect("statistically impossible to hit"); sk.add_tweak(&self.private_key.into()).expect("statistically impossible to hit");
Ok(Xpriv { Xpriv {
network: self.network, network: self.network,
depth: self.depth + 1, depth: self.depth + 1,
parent_fingerprint: self.fingerprint(secp), parent_fingerprint: self.fingerprint(secp),
child_number: i, child_number: i,
private_key: tweaked, private_key: tweaked,
chain_code: ChainCode::from_hmac(hmac_result), chain_code: ChainCode::from_hmac(hmac_result),
}) }
} }
/// Decoding extended private key from binary data according to BIP 32 /// Decoding extended private key from binary data according to BIP 32
@ -1001,7 +997,7 @@ mod tests {
let mut pk = Xpub::from_priv(secp, &sk); let mut pk = Xpub::from_priv(secp, &sk);
// Check derivation convenience method for Xpriv // Check derivation convenience method for Xpriv
assert_eq!(&sk.derive_priv(secp, &path).unwrap().to_string()[..], expected_sk); assert_eq!(&sk.derive_priv(secp, &path).to_string()[..], expected_sk);
// Check derivation convenience method for Xpub, should error // Check derivation convenience method for Xpub, should error
// appropriately if any ChildNumber is hardened // appropriately if any ChildNumber is hardened
@ -1013,7 +1009,7 @@ mod tests {
// Derive keys, checking hardened and non-hardened derivation one-by-one // Derive keys, checking hardened and non-hardened derivation one-by-one
for &num in path.0.iter() { for &num in path.0.iter() {
sk = sk.ckd_priv(secp, num).unwrap(); sk = sk.ckd_priv(secp, num);
match num { match num {
Normal { .. } => { Normal { .. } => {
let pk2 = pk.ckd_pub(secp, num).unwrap(); let pk2 = pk.ckd_pub(secp, num).unwrap();

View File

@ -762,7 +762,7 @@ impl GetKey for Xpriv {
KeyRequest::Pubkey(_) => Err(GetKeyError::NotSupported), KeyRequest::Pubkey(_) => Err(GetKeyError::NotSupported),
KeyRequest::Bip32((fingerprint, path)) => { KeyRequest::Bip32((fingerprint, path)) => {
let key = if self.fingerprint(secp) == fingerprint { let key = if self.fingerprint(secp) == fingerprint {
let k = self.derive_priv(secp, &path)?; let k = self.derive_priv(secp, &path);
Some(k.to_priv()) Some(k.to_priv())
} else { } else {
None None
@ -808,7 +808,7 @@ impl GetKey for $set<Xpriv> {
KeyRequest::Bip32((fingerprint, path)) => { KeyRequest::Bip32((fingerprint, path)) => {
for xpriv in self.iter() { for xpriv in self.iter() {
if xpriv.parent_fingerprint == fingerprint { if xpriv.parent_fingerprint == fingerprint {
let k = xpriv.derive_priv(secp, &path)?; let k = xpriv.derive_priv(secp, &path);
return Ok(Some(k.to_priv())); return Ok(Some(k.to_priv()));
} }
} }
@ -1366,7 +1366,7 @@ mod tests {
ChildNumber::from_normal_idx(31337).unwrap(), ChildNumber::from_normal_idx(31337).unwrap(),
]; ];
sk = sk.derive_priv(secp, &dpath).unwrap(); sk = sk.derive_priv(secp, &dpath);
let pk = Xpub::from_priv(secp, &sk); let pk = Xpub::from_priv(secp, &sk);

View File

@ -317,8 +317,7 @@ fn parse_and_verify_keys(
let path = let path =
derivation_path.into_derivation_path().expect("failed to convert derivation path"); derivation_path.into_derivation_path().expect("failed to convert derivation path");
let derived_priv = let derived_priv = ext_priv.derive_priv(secp, &path).to_priv();
ext_priv.derive_priv(secp, &path).expect("failed to derive ext priv key").to_priv();
assert_eq!(wif_priv, derived_priv); assert_eq!(wif_priv, derived_priv);
let derived_pub = derived_priv.public_key(secp); let derived_pub = derived_priv.public_key(secp);
key_map.insert(derived_pub, derived_priv); key_map.insert(derived_pub, derived_priv);