mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-10-11 03:53:22 +02:00
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.
This commit is contained in:
@@ -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));
|
||||
}
|
||||
|
Reference in New Issue
Block a user