@@ -196,31 +196,34 @@ bool XOnlyPubKey::VerifySchnorr(const uint256& msg, Span<const unsigned char> si
196196
197197static const CHashWriter HASHER_TAPTWEAK = TaggedHash(" TapTweak" );
198198
199- uint256 XOnlyPubKey::ComputeTapTweakHash (const uint256* merkle_root) const
199+ uint256 XOnlyPubKey::ComputeTapTweakHash (const uint256* merkle_root, const int *parity_bit ) const
200200{
201201 if (merkle_root == nullptr ) {
202202 // We have no scripts. The actual tweak does not matter, but follow BIP341 here to
203203 // allow for reproducible tweaking.
204204 return (CHashWriter (HASHER_TAPTWEAK) << m_keydata).GetSHA256 ();
205+ } else if (parity_bit != nullptr ) {
206+ // We have scripts and the parity bit has been committed.
207+ return (CHashWriter (HASHER_TAPTWEAK) << m_keydata << *merkle_root << ((uint8_t )*parity_bit)).GetSHA256 ();
205208 } else {
206209 return (CHashWriter (HASHER_TAPTWEAK) << m_keydata << *merkle_root).GetSHA256 ();
207210 }
208211}
209212
210- bool XOnlyPubKey::CheckTapTweak (const XOnlyPubKey& internal, const uint256& merkle_root, bool parity ) const
213+ bool XOnlyPubKey::CheckTapTweak (const XOnlyPubKey& internal, const uint256& merkle_root, bool q_parity, int * p_parity ) const
211214{
212215 secp256k1_xonly_pubkey internal_key;
213216 if (!secp256k1_xonly_pubkey_parse (secp256k1_context_verify, &internal_key, internal.data ())) return false ;
214- uint256 tweak = internal.ComputeTapTweakHash (&merkle_root);
215- return secp256k1_xonly_pubkey_tweak_add_check (secp256k1_context_verify, m_keydata.begin (), parity , &internal_key, tweak.begin ());
217+ uint256 tweak = internal.ComputeTapTweakHash (&merkle_root, p_parity );
218+ return secp256k1_xonly_pubkey_tweak_add_check (secp256k1_context_verify, m_keydata.begin (), q_parity , &internal_key, tweak.begin ());
216219}
217220
218221std::optional<std::pair<XOnlyPubKey, bool >> XOnlyPubKey::CreateTapTweak (const uint256* merkle_root) const
219222{
220223 secp256k1_xonly_pubkey base_point;
221224 if (!secp256k1_xonly_pubkey_parse (secp256k1_context_verify, &base_point, data ())) return std::nullopt ;
222225 secp256k1_pubkey out;
223- uint256 tweak = ComputeTapTweakHash (merkle_root);
226+ uint256 tweak = ComputeTapTweakHash (merkle_root, nullptr );
224227 if (!secp256k1_xonly_pubkey_tweak_add (secp256k1_context_verify, &out, &base_point, tweak.data ())) return std::nullopt ;
225228 int parity = -1 ;
226229 std::pair<XOnlyPubKey, bool > ret;
@@ -232,6 +235,21 @@ std::optional<std::pair<XOnlyPubKey, bool>> XOnlyPubKey::CreateTapTweak(const ui
232235 return ret;
233236}
234237
238+ std::optional<XOnlyPubKey> XOnlyPubKey::UpdateInternalKey (Span<const unsigned char > raw_sub_point, int parity_bit, int *new_parity_bit) const
239+ {
240+ secp256k1_xonly_pubkey base_point;
241+ if (!secp256k1_xonly_pubkey_parse (secp256k1_context_verify, &base_point, data ())) return std::nullopt ;
242+
243+ secp256k1_xonly_pubkey sub_point;
244+ if (!secp256k1_xonly_pubkey_parse (secp256k1_context_verify, &sub_point, raw_sub_point.begin ())) return std::nullopt ;
245+
246+ XOnlyPubKey new_point;
247+ if (!secp256k1_xonly_pubkey_negate (secp256k1_context_verify, &sub_point)) return std::nullopt ;
248+ if (!secp256k1_xonly_pubkey_add (secp256k1_context_verify, &base_point, &sub_point, parity_bit, new_parity_bit)) return std::nullopt ;
249+
250+ secp256k1_xonly_pubkey_serialize (secp256k1_context_verify, new_point.begin (), &base_point);
251+ return new_point;
252+ }
235253
236254bool CPubKey::Verify (const uint256 &hash, const std::vector<unsigned char >& vchSig) const {
237255 if (!IsValid ())
0 commit comments