From 7b5e4d50cec9f2736124d605fb6b555f7d645c43 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Thu, 19 Aug 2021 13:22:11 +0000 Subject: [PATCH] Add XOnlyPubKey::CreateTapTweak https://github.com/bitcoin/bitcoin/pull/22051 (6/9) Modified to use the old-style Optional rather than std::optional --- src/pubkey.cpp | 18 ++++++++++++++++++ src/pubkey.h | 5 +++++ 2 files changed, 23 insertions(+) diff --git a/src/pubkey.cpp b/src/pubkey.cpp index ea5936d89ca..8acef4fd3a0 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -223,6 +223,24 @@ bool CPubKey::TweakMulVerify(const CPubKey& untweaked, const uint256& tweak) con return *this == CPubKey(out_pk, out_pk + CPubKey::COMPRESSED_SIZE); } +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 nullopt; + secp256k1_pubkey out; + uint256 tweak = ComputeTapTweakHash(merkle_root); + if (!secp256k1_xonly_pubkey_tweak_add(secp256k1_context_verify, &out, &base_point, tweak.data())) return 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 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; diff --git a/src/pubkey.h b/src/pubkey.h index b26ef349e5f..9cb60f3e9da 100644 --- a/src/pubkey.h +++ b/src/pubkey.h @@ -8,11 +8,13 @@ #define BITCOIN_PUBKEY_H #include +#include #include #include #include #include +#include #include const unsigned int BIP32_EXTKEY_SIZE = 74; @@ -248,6 +250,9 @@ class XOnlyPubKey * Merkle root, and parity. */ bool CheckTapTweak(const XOnlyPubKey& internal, const uint256& merkle_root, bool parity) const; + /** Construct a Taproot tweaked output point with this point as internal key. */ + Optional> CreateTapTweak(const uint256* merkle_root) const; + const unsigned char& operator[](int pos) const { return *(m_keydata.begin() + pos); } const unsigned char* data() const { return m_keydata.begin(); } static constexpr size_t size() { return decltype(m_keydata)::size(); }