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

Code before:

void CExtKey::Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const {
    code[0] = nDepth;
    memcpy(code+1, vchFingerprint, 4);
    WriteBE32(code+5, nChild);
    memcpy(code+9, chaincode.begin(), 32);
    code[41] = 0;
    assert(key.size() == 32);
    memcpy(code+42, key.begin(), 32);
}

void CExtKey::Decode(const unsigned char code[BIP32_EXTKEY_SIZE]) {
    nDepth = code[0];
    memcpy(vchFingerprint, code+1, 4);
    nChild = ReadBE32(code+5);
    memcpy(chaincode.begin(), code+9, 32);
    key.Set(code+42, code+BIP32_EXTKEY_SIZE, true);
    if ((nDepth == 0 && (nChild != 0 || ReadLE32(vchFingerprint) != 0)) || code[41] != 0) key = CKey();
}

KeyPair::KeyPair(const CKey& key, const uint256* merkle_root)
{
    static_assert(std::tuple_size<KeyType>() == sizeof(secp256k1_keypair));
    MakeKeyPairData();
    auto keypair = reinterpret_cast<secp256k1_keypair*>(m_keypair->data());
    bool ret = secp256k1_keypair_create(secp256k1_context_sign, keypair, UCharCast(key.data()));
    if (ret && merkle_root) {
        CPubKey pubkey_bytes = key.GetPubKey();
        uint256 tweak = XOnlyPubKey(pubkey_bytes).ComputeTapTweakHash(merkle_root->IsNull() ? nullptr : merkle_root);
        ret = secp256k1_keypair_xonly_tweak_add(secp256k1_context_static, keypair, tweak.data());
    }
    if (!ret) ClearKeyPairData();
}

bool ECC_InitSanityCheck() {
    CKey key = GenerateRandomKey();
    CPubKey pubkey = key.GetPubKey();
    return key.VerifyPubKey(pubkey);
}

/** Initialize the elliptic curve support. May not be called twice without calling ECC_Stop first. */
static void ECC_Start() {
    assert(secp256k1_context_sign == nullptr);

    secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
    assert(ctx != nullptr);

    {
        // Pass in a random blinding seed to the secp256k1 context.
        std::vector<unsigned char, secure_allocator<unsigned char>> vseed(32);
        GetRandBytes(vseed);

Review comment (suggestion):
nit: in other cases it makes sense to call it `ret`, since it's the return value, here it's just a validity check - if you think it makes sense, [consider renaming](https://github.com/bitcoin/bitcoin/blob/master/src/key.cpp#L338) to avoid the surprise

Code after:
    memcpy(vchFingerprint, code+1, 4);
    nChild = ReadBE32(code+5);
    memcpy(chaincode.begin(), code+9, 32);
    key.Set(code+42, code+BIP32_EXTKEY_SIZE, true);
    if ((nDepth == 0 && (nChild != 0 || ReadLE32(vchFingerprint) != 0)) || code[41] != 0) key = CKey();
}

KeyPair::KeyPair(const CKey& key, const uint256* merkle_root)
{
    static_assert(std::tuple_size<KeyType>() == sizeof(secp256k1_keypair));
    MakeKeyPairData();
    auto keypair = reinterpret_cast<secp256k1_keypair*>(m_keypair->data());
    bool success = secp256k1_keypair_create(secp256k1_context_sign, keypair, UCharCast(key.data()));
    if (success && merkle_root) {
        secp256k1_xonly_pubkey pubkey;
        unsigned char pubkey_bytes[32];
        assert(secp256k1_keypair_xonly_pub(secp256k1_context_sign, &pubkey, nullptr, keypair));
        assert(secp256k1_xonly_pubkey_serialize(secp256k1_context_sign, pubkey_bytes, &pubkey));
        uint256 tweak = XOnlyPubKey(pubkey_bytes).ComputeTapTweakHash(merkle_root->IsNull() ? nullptr : merkle_root);
        success = secp256k1_keypair_xonly_tweak_add(secp256k1_context_static, keypair, tweak.data());
    }
    if (!success) ClearKeyPairData();
}

bool KeyPair::SignSchnorr(const uint256& hash, Span<unsigned char> sig, const uint256& aux) const
{
    assert(sig.size() == 64);
    if (!IsValid()) return false;
    auto keypair = reinterpret_cast<const secp256k1_keypair*>(m_keypair->data());
    bool ret = secp256k1_schnorrsig_sign32(secp256k1_context_sign, sig.data(), hash.data(), keypair, aux.data());
    if (ret) {
        // Additional verification step to prevent using a potentially corrupted signature
        secp256k1_xonly_pubkey pubkey_verify;
        ret = secp256k1_keypair_xonly_pub(secp256k1_context_static, &pubkey_verify, nullptr, keypair);
        ret &= secp256k1_schnorrsig_verify(secp256k1_context_static, sig.data(), hash.begin(), 32, &pubkey_verify);
    }
    if (!ret) memory_cleanse(sig.data(), sig.size());
    return ret;
}

bool ECC_InitSanityCheck() {
    CKey key = GenerateRandomKey();
    CPubKey pubkey = key.GetPubKey();
    return key.VerifyPubKey(pubkey);
}

/** Initialize the elliptic curve support. May not be called twice without calling ECC_Stop first. */
static void ECC_Start() {
    assert(secp256k1_context_sign == nullptr);

    secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);