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

Code before:
                MakeKeyPairData();
                *m_keypair = *other.m_keypair;
            } else {
                ClearKeyPairData();
            }
        }
        return *this;
    }

    KeyPair(const KeyPair& other) { *this = other; }

    friend KeyPair CKey::ComputeKeyPair() const;
    [[nodiscard]] bool SignSchnorr(const uint256& hash, Span<unsigned char> sig, const uint256& aux) const;

    /**
     * data() is provided as a read-only method for passing a KeyPair object to secp256k1 functions
     * expecting a `secp256k1_keypair`. This avoids needing to create a temporary `secp256k1_keypair`
     * object by allowing the KeyPair to be passed directly in the following manner:
     *
     *     reinterpret_cast<const secp256k1_keypair*>(keypair.data())
     *
     * Recall that `secp256k1_keypair` is an opaque data type, so this method should only be used
     * for passing a KeyPair object as a secp256k1_keypair and should never be used to access the
     * underlying keypair bytes directly.
     */
    const unsigned char* data() const { return IsValid() ? m_keypair->data() : nullptr; }

    //! Check whether this keypair is valid.
    bool IsValid() const { return !!m_keypair; }

private:
    KeyPair(const CKey& key);

    using KeyType = std::array<unsigned char, 96>;
    secure_unique_ptr<KeyType> m_keypair;

    void MakeKeyPairData()
    {
        if (!m_keypair) m_keypair = make_secure_unique<KeyType>();
    }

    void ClearKeyPairData()
    {
        m_keypair.reset();
    }
};

/** Check that required EC support is available at runtime. */
bool ECC_InitSanityCheck();

/**

Review comment (suggestion):
If the only purpose of this function is constructing a `const secp256k1_keypair*`, I think it would be better to make it private (it seems only accessed inside `KeyPair` anyway?), and give it another name (`data()` is used in STL containers to give raw access to the contents, which seems to be explicitly what we don't want here).

Code after:
 *
 *  A KeyPair can be created from a CKey with an optional merkle_root tweak (per BIP342). See
 *  CKey::ComputeKeyPair for more details.
 */
class KeyPair
{
public:
    KeyPair() noexcept = default;
    KeyPair(KeyPair&&) noexcept = default;
    KeyPair& operator=(KeyPair&&) noexcept = default;
    KeyPair& operator=(const KeyPair& other)
    {
        if (this != &other) {
            if (other.m_keypair) {
                MakeKeyPairData();
                *m_keypair = *other.m_keypair;
            } else {
                ClearKeyPairData();
            }
        }
        return *this;
    }

    KeyPair(const KeyPair& other) { *this = other; }

    friend KeyPair CKey::ComputeKeyPair(const uint256* merkle_root) const;
    [[nodiscard]] bool SignSchnorr(const uint256& hash, Span<unsigned char> sig, const uint256& aux) const;

    //! Check whether this keypair is valid.
    bool IsValid() const { return !!m_keypair; }

private:
    KeyPair(const CKey& key, const uint256* merkle_root);

    using KeyType = std::array<unsigned char, 96>;
    secure_unique_ptr<KeyType> m_keypair;

    void MakeKeyPairData()
    {
        if (!m_keypair) m_keypair = make_secure_unique<KeyType>();
    }

    void ClearKeyPairData()
    {
        m_keypair.reset();
    }
};

/** Check that required EC support is available at runtime. */
bool ECC_InitSanityCheck();