Repository: bitcoin/bitcoin
File: src/pubkey.cpp (C++)

Code before:

    if (!overflow) {
        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(secp256k1_context_static, sig, tmpsig);
    }
    return 1;
}

XOnlyPubKey::XOnlyPubKey(Span<const unsigned char> bytes)
{
    assert(bytes.size() == 32);
    std::copy(bytes.begin(), bytes.end(), m_keydata.begin());
}

std::vector<CKeyID> XOnlyPubKey::GetKeyIDs() const
{
    std::vector<CKeyID> out;
    // For now, use the old full pubkey-based key derivation logic. As it is indexed by
    // Hash160(full pubkey), we need to return both a version prefixed with 0x02, and one
    // with 0x03.
    unsigned char b[33] = {0x02};
    std::copy(m_keydata.begin(), m_keydata.end(), b + 1);
    CPubKey fullpubkey;
    fullpubkey.Set(b, b + 33);
    out.push_back(fullpubkey.GetID());
    b[0] = 0x03;
    fullpubkey.Set(b, b + 33);
    out.push_back(fullpubkey.GetID());
    return out;
}

CPubKey XOnlyPubKey::GetEvenCorrespondingCPubKey() const
{
    unsigned char full_key[CPubKey::COMPRESSED_SIZE] = {0x02};
    std::copy(begin(), end(), full_key + 1);
    return CPubKey{full_key};
}

bool XOnlyPubKey::IsFullyValid() const
{
    secp256k1_xonly_pubkey pubkey;
    return secp256k1_xonly_pubkey_parse(secp256k1_context_static, &pubkey, m_keydata.data());
}

bool XOnlyPubKey::VerifySchnorr(const uint256& msg, Span<const unsigned char> sigbytes) const
{

Review comment (suggestion):
This code snippet doesn't work for me on Sage 9.5 (see https://github.com/BlockstreamResearch/secp256k1-zkp/pull/292). Also, we only need to output the x-coordinate here:
```suggestion
    G2 = EllipticCurve ([F (0), F (7)]).lift_x(F(int(hashlib.sha256(bytes.fromhex(G_DER)).hexdigest(),16)))
    print('%x' % G2.xy()[0])
```
(That said, I think it's also completely fine to not include any sage code here and instead just keep the first paragraph.)

Code after:
    }

    if (!overflow) {
        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(secp256k1_context_static, sig, tmpsig);
    }
    return 1;
}

/** Nothing Up My Sleeve (NUMS) point
 *
 *  NUMS_H is a point with an unknown discrete logarithm, constructed by taking the sha256 of 'g'
 *  (uncompressed encoding), which happens to be a point on the curve.
 *
 *  For an example script for calculating H, refer to the unit tests in
 *  ./test/functional/test_framework/crypto/secp256k1.py
 */
static const std::vector<unsigned char> NUMS_H_DATA{ParseHex("50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0")};
const XOnlyPubKey XOnlyPubKey::NUMS_H{NUMS_H_DATA};

XOnlyPubKey::XOnlyPubKey(Span<const unsigned char> bytes)
{
    assert(bytes.size() == 32);
    std::copy(bytes.begin(), bytes.end(), m_keydata.begin());
}

std::vector<CKeyID> XOnlyPubKey::GetKeyIDs() const
{
    std::vector<CKeyID> out;
    // For now, use the old full pubkey-based key derivation logic. As it is indexed by
    // Hash160(full pubkey), we need to return both a version prefixed with 0x02, and one
    // with 0x03.
    unsigned char b[33] = {0x02};
    std::copy(m_keydata.begin(), m_keydata.end(), b + 1);
    CPubKey fullpubkey;
    fullpubkey.Set(b, b + 33);
    out.push_back(fullpubkey.GetID());
    b[0] = 0x03;
    fullpubkey.Set(b, b + 33);
    out.push_back(fullpubkey.GetID());
    return out;
}

CPubKey XOnlyPubKey::GetEvenCorrespondingCPubKey() const
{
    unsigned char full_key[CPubKey::COMPRESSED_SIZE] = {0x02};