diff options
author | Pieter Wuille <pieter@wuille.net> | 2022-12-12 23:44:53 -0500 |
---|---|---|
committer | Pieter Wuille <pieter@wuille.net> | 2022-12-13 15:08:24 -0500 |
commit | 4462cb04986d77eddcfc6e8f75e04dc278a8147a (patch) | |
tree | b734303912ceb551182d106edc1b713a055ba4c1 /src/pubkey.cpp | |
parent | 3d8a6ae28326ed10b6ca1c2807ceb400575f2ba7 (diff) |
Adapt to libsecp256k1 API changes
* Use SECP256K1_CONTEXT_NONE when creating signing context, as
SECP256K1_CONTEXT_SIGN is deprecated and unnecessary.
* Use secp256k1_static_context where applicable.
Diffstat (limited to 'src/pubkey.cpp')
-rw-r--r-- | src/pubkey.cpp | 94 |
1 files changed, 28 insertions, 66 deletions
diff --git a/src/pubkey.cpp b/src/pubkey.cpp index 2e37e16690..6c068fcc06 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -16,12 +16,6 @@ #include <algorithm> #include <cassert> -namespace -{ -/* Global secp256k1_context object used for verification. */ -secp256k1_context* secp256k1_context_verify = nullptr; -} // namespace - /** This function is taken from the libsecp256k1 distribution and implements * DER parsing for ECDSA signatures, while supporting an arbitrary subset of * format violations. @@ -32,7 +26,7 @@ secp256k1_context* secp256k1_context_verify = nullptr; * strict DER before being passed to this module, and we know it supports all * violations present in the blockchain before that point. */ -int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { +int ecdsa_signature_parse_der_lax(secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { size_t rpos, rlen, spos, slen; size_t pos = 0; size_t lenbyte; @@ -40,7 +34,7 @@ int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_ int overflow = 0; /* Hack to initialize sig with a correctly-parsed but invalid signature. */ - secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); + secp256k1_ecdsa_signature_parse_compact(secp256k1_context_static, sig, tmpsig); /* Sequence tag byte */ if (pos == inputlen || input[pos] != 0x30) { @@ -163,13 +157,13 @@ int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_ } if (!overflow) { - overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); + overflow = !secp256k1_ecdsa_signature_parse_compact(secp256k1_context_static, sig, tmpsig); } if (overflow) { /* Overwrite the result again with a correctly-parsed but invalid signature if parsing failed. */ memset(tmpsig, 0, 64); - secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); + secp256k1_ecdsa_signature_parse_compact(secp256k1_context_static, sig, tmpsig); } return 1; } @@ -200,15 +194,15 @@ std::vector<CKeyID> XOnlyPubKey::GetKeyIDs() const bool XOnlyPubKey::IsFullyValid() const { secp256k1_xonly_pubkey pubkey; - return secp256k1_xonly_pubkey_parse(secp256k1_context_verify, &pubkey, m_keydata.data()); + return secp256k1_xonly_pubkey_parse(secp256k1_context_static, &pubkey, m_keydata.data()); } bool XOnlyPubKey::VerifySchnorr(const uint256& msg, Span<const unsigned char> sigbytes) const { assert(sigbytes.size() == 64); secp256k1_xonly_pubkey pubkey; - if (!secp256k1_xonly_pubkey_parse(secp256k1_context_verify, &pubkey, m_keydata.data())) return false; - return secp256k1_schnorrsig_verify(secp256k1_context_verify, sigbytes.data(), msg.begin(), 32, &pubkey); + if (!secp256k1_xonly_pubkey_parse(secp256k1_context_static, &pubkey, m_keydata.data())) return false; + return secp256k1_schnorrsig_verify(secp256k1_context_static, sigbytes.data(), msg.begin(), 32, &pubkey); } static const HashWriter HASHER_TAPTWEAK{TaggedHash("TapTweak")}; @@ -227,23 +221,23 @@ uint256 XOnlyPubKey::ComputeTapTweakHash(const uint256* merkle_root) const bool XOnlyPubKey::CheckTapTweak(const XOnlyPubKey& internal, const uint256& merkle_root, bool parity) const { secp256k1_xonly_pubkey internal_key; - if (!secp256k1_xonly_pubkey_parse(secp256k1_context_verify, &internal_key, internal.data())) return false; + if (!secp256k1_xonly_pubkey_parse(secp256k1_context_static, &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()); + return secp256k1_xonly_pubkey_tweak_add_check(secp256k1_context_static, m_keydata.begin(), parity, &internal_key, tweak.begin()); } std::optional<std::pair<XOnlyPubKey, bool>> 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; + if (!secp256k1_xonly_pubkey_parse(secp256k1_context_static, &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; + if (!secp256k1_xonly_pubkey_tweak_add(secp256k1_context_static, &out, &base_point, tweak.data())) return std::nullopt; int parity = -1; std::pair<XOnlyPubKey, bool> 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); + if (!secp256k1_xonly_pubkey_from_pubkey(secp256k1_context_static, &out_xonly, &parity, &out)) return std::nullopt; + secp256k1_xonly_pubkey_serialize(secp256k1_context_static, ret.first.begin(), &out_xonly); assert(parity == 0 || parity == 1); ret.second = parity; return ret; @@ -255,17 +249,16 @@ bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchS return false; secp256k1_pubkey pubkey; secp256k1_ecdsa_signature sig; - assert(secp256k1_context_verify && "secp256k1_context_verify must be initialized to use CPubKey."); - if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, vch, size())) { + if (!secp256k1_ec_pubkey_parse(secp256k1_context_static, &pubkey, vch, size())) { return false; } - if (!ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig, vchSig.data(), vchSig.size())) { + if (!ecdsa_signature_parse_der_lax(&sig, vchSig.data(), vchSig.size())) { return false; } /* libsecp256k1's ECDSA verification requires lower-S signatures, which have * not historically been enforced in Bitcoin, so normalize them first. */ - secp256k1_ecdsa_signature_normalize(secp256k1_context_verify, &sig, &sig); - return secp256k1_ecdsa_verify(secp256k1_context_verify, &sig, hash.begin(), &pubkey); + secp256k1_ecdsa_signature_normalize(secp256k1_context_static, &sig, &sig); + return secp256k1_ecdsa_verify(secp256k1_context_static, &sig, hash.begin(), &pubkey); } bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) { @@ -275,16 +268,15 @@ bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned cha bool fComp = ((vchSig[0] - 27) & 4) != 0; secp256k1_pubkey pubkey; secp256k1_ecdsa_recoverable_signature sig; - assert(secp256k1_context_verify && "secp256k1_context_verify must be initialized to use CPubKey."); - if (!secp256k1_ecdsa_recoverable_signature_parse_compact(secp256k1_context_verify, &sig, &vchSig[1], recid)) { + if (!secp256k1_ecdsa_recoverable_signature_parse_compact(secp256k1_context_static, &sig, &vchSig[1], recid)) { return false; } - if (!secp256k1_ecdsa_recover(secp256k1_context_verify, &pubkey, &sig, hash.begin())) { + if (!secp256k1_ecdsa_recover(secp256k1_context_static, &pubkey, &sig, hash.begin())) { return false; } unsigned char pub[SIZE]; size_t publen = SIZE; - secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, fComp ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED); + secp256k1_ec_pubkey_serialize(secp256k1_context_static, pub, &publen, &pubkey, fComp ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED); Set(pub, pub + publen); return true; } @@ -293,21 +285,19 @@ bool CPubKey::IsFullyValid() const { if (!IsValid()) return false; secp256k1_pubkey pubkey; - assert(secp256k1_context_verify && "secp256k1_context_verify must be initialized to use CPubKey."); - return secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, vch, size()); + return secp256k1_ec_pubkey_parse(secp256k1_context_static, &pubkey, vch, size()); } bool CPubKey::Decompress() { if (!IsValid()) return false; secp256k1_pubkey pubkey; - assert(secp256k1_context_verify && "secp256k1_context_verify must be initialized to use CPubKey."); - if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, vch, size())) { + if (!secp256k1_ec_pubkey_parse(secp256k1_context_static, &pubkey, vch, size())) { return false; } unsigned char pub[SIZE]; size_t publen = SIZE; - secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, SECP256K1_EC_UNCOMPRESSED); + secp256k1_ec_pubkey_serialize(secp256k1_context_static, pub, &publen, &pubkey, SECP256K1_EC_UNCOMPRESSED); Set(pub, pub + publen); return true; } @@ -320,16 +310,15 @@ bool CPubKey::Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChi BIP32Hash(cc, nChild, *begin(), begin()+1, out); memcpy(ccChild.begin(), out+32, 32); secp256k1_pubkey pubkey; - assert(secp256k1_context_verify && "secp256k1_context_verify must be initialized to use CPubKey."); - if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, vch, size())) { + if (!secp256k1_ec_pubkey_parse(secp256k1_context_static, &pubkey, vch, size())) { return false; } - if (!secp256k1_ec_pubkey_tweak_add(secp256k1_context_verify, &pubkey, out)) { + if (!secp256k1_ec_pubkey_tweak_add(secp256k1_context_static, &pubkey, out)) { return false; } unsigned char pub[COMPRESSED_SIZE]; size_t publen = COMPRESSED_SIZE; - secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, SECP256K1_EC_COMPRESSED); + secp256k1_ec_pubkey_serialize(secp256k1_context_static, pub, &publen, &pubkey, SECP256K1_EC_COMPRESSED); pubkeyChild.Set(pub, pub + publen); return true; } @@ -375,35 +364,8 @@ bool CExtPubKey::Derive(CExtPubKey &out, unsigned int _nChild) const { /* static */ bool CPubKey::CheckLowS(const std::vector<unsigned char>& vchSig) { secp256k1_ecdsa_signature sig; - assert(secp256k1_context_verify && "secp256k1_context_verify must be initialized to use CPubKey."); - if (!ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig, vchSig.data(), vchSig.size())) { + if (!ecdsa_signature_parse_der_lax(&sig, vchSig.data(), vchSig.size())) { return false; } - return (!secp256k1_ecdsa_signature_normalize(secp256k1_context_verify, nullptr, &sig)); -} - -/* static */ int ECCVerifyHandle::refcount = 0; - -ECCVerifyHandle::ECCVerifyHandle() -{ - if (refcount == 0) { - assert(secp256k1_context_verify == nullptr); - secp256k1_context_verify = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); - assert(secp256k1_context_verify != nullptr); - } - refcount++; -} - -ECCVerifyHandle::~ECCVerifyHandle() -{ - refcount--; - if (refcount == 0) { - assert(secp256k1_context_verify != nullptr); - secp256k1_context_destroy(secp256k1_context_verify); - secp256k1_context_verify = nullptr; - } -} - -const secp256k1_context* GetVerifyContext() { - return secp256k1_context_verify; + return (!secp256k1_ecdsa_signature_normalize(secp256k1_context_static, nullptr, &sig)); } |