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

Code before:
        memcpy(tmpsig + 64 - slen, input + spos, slen);
    }

    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());
}


Review comment (suggestion):
This is not DER encoding; DER is only used for signatures (and once upon a time, for private keys in the wallet). The byte encoding used for secp256k1 public keys is defined in section 2.3.3 of SEC1 v2 (https://www.secg.org/sec1-v2.pdf), though I believe ANSI and/or NIST also standardized it (not for secp256k1 specifically, but for prime-ordered curves in general).

Code after:
    } else {
        memcpy(tmpsig + 64 - slen, input + spos, slen);
    }

    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