Return parity when doing tap_tweak

Currently we calculate the parity during `tap_tweak` but do not return
it, this means others must re-do work done inside `tap_tweak` in order
to calculate the parity. We can just return the parity along with the
tweaked key.
This commit is contained in:
Tobin Harding 2021-12-02 14:43:38 +11:00
parent 7af0999745
commit a6d3514f2b
3 changed files with 11 additions and 17 deletions

View File

@ -527,11 +527,12 @@ impl Address {
merkle_root: Option<TapBranchHash>, merkle_root: Option<TapBranchHash>,
network: Network network: Network
) -> Address { ) -> Address {
let (output_key, _parity) = internal_key.tap_tweak(secp, merkle_root);
Address { Address {
network: network, network: network,
payload: Payload::WitnessProgram { payload: Payload::WitnessProgram {
version: WitnessVersion::V1, version: WitnessVersion::V1,
program: internal_key.tap_tweak(secp, merkle_root).into_inner().serialize().to_vec() program: output_key.into_inner().serialize().to_vec()
} }
} }
} }

View File

@ -39,7 +39,10 @@ pub trait TapTweak {
/// * H is the hash function /// * H is the hash function
/// * c is the commitment data /// * c is the commitment data
/// * G is the generator point /// * G is the generator point
fn tap_tweak<C: Verification>(self, secp: &Secp256k1<C>, merkle_root: Option<TapBranchHash>) -> TweakedPublicKey; ///
/// # Returns
/// The tweaked key and its parity.
fn tap_tweak<C: Verification>(self, secp: &Secp256k1<C>, merkle_root: Option<TapBranchHash>) -> (TweakedPublicKey, bool);
/// Directly convert an UntweakedPublicKey to a TweakedPublicKey /// Directly convert an UntweakedPublicKey to a TweakedPublicKey
/// ///
@ -49,13 +52,13 @@ pub trait TapTweak {
} }
impl TapTweak for UntweakedPublicKey { impl TapTweak for UntweakedPublicKey {
fn tap_tweak<C: Verification>(self, secp: &Secp256k1<C>, merkle_root: Option<TapBranchHash>) -> TweakedPublicKey { fn tap_tweak<C: Verification>(self, secp: &Secp256k1<C>, merkle_root: Option<TapBranchHash>) -> (TweakedPublicKey, bool) {
let tweak_value = TapTweakHash::from_key_and_tweak(self, merkle_root).into_inner(); let tweak_value = TapTweakHash::from_key_and_tweak(self, merkle_root).into_inner();
let mut output_key = self.clone(); let mut output_key = self.clone();
let parity = output_key.tweak_add_assign(&secp, &tweak_value).expect("Tap tweak failed"); let parity = output_key.tweak_add_assign(&secp, &tweak_value).expect("Tap tweak failed");
debug_assert!(self.tweak_add_check(&secp, &output_key, parity, tweak_value)); debug_assert!(self.tweak_add_check(&secp, &output_key, parity, tweak_value));
TweakedPublicKey(output_key) (TweakedPublicKey(output_key), parity)
} }
fn dangerous_assume_tweaked(self) -> TweakedPublicKey { fn dangerous_assume_tweaked(self) -> TweakedPublicKey {

View File

@ -25,7 +25,7 @@ use core::cmp::Reverse;
use std::error; use std::error;
use hashes::{sha256, sha256t, Hash, HashEngine}; use hashes::{sha256, sha256t, Hash, HashEngine};
use schnorr::{TweakedPublicKey, UntweakedPublicKey}; use schnorr::{TweakedPublicKey, UntweakedPublicKey, TapTweak};
use Script; use Script;
use consensus::Encodable; use consensus::Encodable;
@ -253,22 +253,12 @@ impl TaprootSpendInfo {
internal_key: UntweakedPublicKey, internal_key: UntweakedPublicKey,
merkle_root: Option<TapBranchHash>, merkle_root: Option<TapBranchHash>,
) -> Self { ) -> Self {
let tweak = TapTweakHash::from_key_and_tweak(internal_key, merkle_root); let (output_key, parity) = internal_key.tap_tweak(secp, merkle_root);
let mut output_key = internal_key;
// # Panics:
//
// This would return Err if the merkle root hash is the negation of the secret
// key corresponding to the internal key.
// Because the tweak is derived as specified in BIP341 (hash output of a function),
// this is unlikely to occur (1/2^128) in real life usage, it is safe to unwrap this
let parity = output_key
.tweak_add_assign(&secp, &tweak)
.expect("TapTweakHash::from_key_and_tweak is broken");
Self { Self {
internal_key: internal_key, internal_key: internal_key,
merkle_root: merkle_root, merkle_root: merkle_root,
output_key_parity: parity, output_key_parity: parity,
output_key: TweakedPublicKey::dangerous_assume_tweaked(output_key), output_key: output_key,
script_map: BTreeMap::new(), script_map: BTreeMap::new(),
} }
} }