From 2fbfb1becb3c0c109cd7c30b245b51da22039932 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 1 Feb 2021 16:21:59 -0800 Subject: Make consensus checking of tweaks in pubkey.* Taproot-specific That results in a much safer interface (making the tweak commit to the key implicitly using a fixed tag means it can't be used for unrelated tweaking). --- src/pubkey.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'src/pubkey.cpp') diff --git a/src/pubkey.cpp b/src/pubkey.cpp index 334acb454e..f78779c182 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -188,11 +188,25 @@ bool XOnlyPubKey::VerifySchnorr(const uint256& msg, Span si return secp256k1_schnorrsig_verify(secp256k1_context_verify, sigbytes.data(), msg.begin(), &pubkey); } -bool XOnlyPubKey::CheckPayToContract(const XOnlyPubKey& base, const uint256& hash, bool parity) const +static const CHashWriter HASHER_TAPTWEAK = TaggedHash("TapTweak"); + +uint256 XOnlyPubKey::ComputeTapTweakHash(const uint256* merkle_root) const +{ + if (merkle_root == nullptr) { + // We have no scripts. The actual tweak does not matter, but follow BIP341 here to + // allow for reproducible tweaking. + return (CHashWriter(HASHER_TAPTWEAK) << m_keydata).GetSHA256(); + } else { + return (CHashWriter(HASHER_TAPTWEAK) << m_keydata << *merkle_root).GetSHA256(); + } +} + +bool XOnlyPubKey::CheckTapTweak(const XOnlyPubKey& internal, const uint256& merkle_root, bool parity) const { - secp256k1_xonly_pubkey base_point; - if (!secp256k1_xonly_pubkey_parse(secp256k1_context_verify, &base_point, base.data())) return false; - return secp256k1_xonly_pubkey_tweak_add_check(secp256k1_context_verify, m_keydata.begin(), parity, &base_point, hash.begin()); + secp256k1_xonly_pubkey internal_key; + if (!secp256k1_xonly_pubkey_parse(secp256k1_context_verify, &internal_key, internal.data())) return false; + uint256 tweak = internal.ComputeTapTweakHash(&merkle_root); + return secp256k1_xonly_pubkey_tweak_add_check(secp256k1_context_verify, m_keydata.begin(), parity, &internal_key, tweak.begin()); } bool CPubKey::Verify(const uint256 &hash, const std::vector& vchSig) const { -- cgit v1.2.3 From 5f6cc8daa83700d1c949d968a5cf0d935be337b7 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 23 May 2021 18:32:30 -0700 Subject: Add XOnlyPubKey::CreateTapTweak --- src/pubkey.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'src/pubkey.cpp') diff --git a/src/pubkey.cpp b/src/pubkey.cpp index f78779c182..8382897f95 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -209,6 +209,24 @@ bool XOnlyPubKey::CheckTapTweak(const XOnlyPubKey& internal, const uint256& merk return secp256k1_xonly_pubkey_tweak_add_check(secp256k1_context_verify, m_keydata.begin(), parity, &internal_key, tweak.begin()); } +std::optional> XOnlyPubKey::CreateTapTweak(const uint256* merkle_root) const +{ + secp256k1_xonly_pubkey base_point; + if (!secp256k1_xonly_pubkey_parse(secp256k1_context_verify, &base_point, data())) return std::nullopt; + secp256k1_pubkey out; + uint256 tweak = ComputeTapTweakHash(merkle_root); + if (!secp256k1_xonly_pubkey_tweak_add(secp256k1_context_verify, &out, &base_point, tweak.data())) return std::nullopt; + int parity = -1; + std::pair ret; + secp256k1_xonly_pubkey out_xonly; + if (!secp256k1_xonly_pubkey_from_pubkey(secp256k1_context_verify, &out_xonly, &parity, &out)) return std::nullopt; + secp256k1_xonly_pubkey_serialize(secp256k1_context_verify, ret.first.begin(), &out_xonly); + assert(parity == 0 || parity == 1); + ret.second = parity; + return ret; +} + + bool CPubKey::Verify(const uint256 &hash, const std::vector& vchSig) const { if (!IsValid()) return false; -- cgit v1.2.3 From 90fcac365e1616779b40a69736428435df75fdf2 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 1 Feb 2021 18:53:24 -0800 Subject: Add TaprootBuilder class This class functions as a utility for building taproot outputs, from internal key and script leaves. --- src/pubkey.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/pubkey.cpp') diff --git a/src/pubkey.cpp b/src/pubkey.cpp index 8382897f95..51cc826b00 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -180,6 +180,12 @@ XOnlyPubKey::XOnlyPubKey(Span bytes) std::copy(bytes.begin(), bytes.end(), m_keydata.begin()); } +bool XOnlyPubKey::IsFullyValid() const +{ + secp256k1_xonly_pubkey pubkey; + return secp256k1_xonly_pubkey_parse(secp256k1_context_verify, &pubkey, m_keydata.data()); +} + bool XOnlyPubKey::VerifySchnorr(const uint256& msg, Span sigbytes) const { assert(sigbytes.size() == 64); -- cgit v1.2.3