Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
251bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig) const {252if (!keydata)253return false;254vchSig.resize(CPubKey::COMPACT_SIGNATURE_SIZE);255int rec = -1;256secp256k1_ecdsa_recoverable_signature rsig;257int ret = secp256k1_ecdsa_sign_recoverable(secp256k1_context_sign, &rsig, hash.begin(), UCharCast(begin()), secp256k1_nonce_function_rfc6979, nullptr);258assert(ret);259ret = secp256k1_ecdsa_recoverable_signature_serialize_compact(secp256k1_context_static, &vchSig[1], &rec, &rsig);260assert(ret);261assert(rec != -1);262vchSig[0] = 27 + rec + (fCompressed ? 4 : 0);263// Additional verification step to prevent using a potentially corrupted signature264secp256k1_pubkey epk, rpk;265ret = secp256k1_ec_pubkey_create(secp256k1_context_sign, &epk, UCharCast(begin()));266assert(ret);267ret = secp256k1_ecdsa_recover(secp256k1_context_static, &rpk, &rsig, hash.begin());268assert(ret);269ret = secp256k1_ec_pubkey_cmp(secp256k1_context_static, &epk, &rpk);270assert(ret == 0);271return true;272}274bool CKey::SignSchnorr(const uint256& hash, std::span<unsigned char> sig, const uint256* merkle_root, const uint256& aux) const275{276KeyPair kp = ComputeKeyPair(merkle_root);277return kp.SignSchnorr(hash, sig, aux);278}280bool CKey::Load(const CPrivKey &seckey, const CPubKey &vchPubKey, bool fSkipCheck=false) {281MakeKeyData();282if (!ec_seckey_import_der(secp256k1_context_static, (unsigned char*)begin(), seckey.data(), seckey.size())) {283ClearKeyData();284return false;285}286fCompressed = vchPubKey.IsCompressed();288if (fSkipCheck)289return true;291return VerifyPubKey(vchPubKey);292}294bool CKey::Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const {295assert(IsValid());296assert(IsCompressed());297std::vector<unsigned char, secure_allocator<unsigned char>> vout(64);298if ((nChild >> 31) == 0) {299CPubKey pubkey = GetPubKey();300assert(pubkey.size() == CPubKey::COMPRESSED_SIZE);301BIP32Hash(cc, nChild, *pubkey.begin(), pubkey.begin()+1, vout.data());302} else {303assert(size() == 32);304BIP32Hash(cc, nChild, 0, UCharCast(begin()), vout.data());305}306memcpy(ccChild.begin(), vout.data()+32, 32);307keyChild.Set(begin(), begin() + 32, true);308bool ret = secp256k1_ec_seckey_tweak_add(secp256k1_context_static, (unsigned char*)keyChild.begin(), vout.data());309if (!ret) keyChild.ClearKeyData();310return ret;311}313EllSwiftPubKey CKey::EllSwiftCreate(std::span<const std::byte> ent32) const314{315assert(keydata);316assert(ent32.size() == 32);317std::array<std::byte, EllSwiftPubKey::size()> encoded_pubkey;319auto success = secp256k1_ellswift_create(secp256k1_context_sign,320UCharCast(encoded_pubkey.data()),321keydata->data(),322UCharCast(ent32.data()));324// Should always succeed for valid keys (asserted above).325assert(success);326return {encoded_pubkey};327}329ECDHSecret CKey::ComputeBIP324ECDHSecret(const EllSwiftPubKey& their_ellswift, const EllSwiftPubKey& our_ellswift, bool initiating) const330{331assert(keydata);333ECDHSecret output;334// BIP324 uses the initiator as party A, and the responder as party B. Remap the inputs335// accordingly:336bool success = secp256k1_ellswift_xdh(secp256k1_context_static,337UCharCast(output.data()),338UCharCast(initiating ? our_ellswift.data() : their_ellswift.data()),339UCharCast(initiating ? their_ellswift.data() : our_ellswift.data()),340keydata->data(),341initiating ? 0 : 1,342secp256k1_ellswift_xdh_hash_function_bip324,343nullptr);344// Should always succeed for valid keys (assert above).345assert(success);346return output;347}349KeyPair CKey::ComputeKeyPair(const uint256* merkle_root) const350{351return KeyPair(*this, merkle_root);352}354CKey GenerateRandomKey(bool compressed) noexcept355{356CKey key;357key.MakeNewKey(/*fCompressed=*/compressed);358return key;359}361bool CExtKey::Derive(CExtKey &out, unsigned int _nChild) const {362if (nDepth == std::numeric_limits<unsigned char>::max()) return false;363out.nDepth = nDepth + 1;364out.fingerprint = id_key_fingerprint();365out.nChild = _nChild;366return key.Derive(out.key, out.chaincode, _nChild, chaincode);367}369std::optional<std::pair<CExtKey, KeyOriginInfo>> DeriveExtKey(const CExtKey& ext_key, const std::vector<uint32_t>& path)370{371CExtKey descendant = ext_key;372KeyOriginInfo origin;373origin.fingerprint = ext_key.id_key_fingerprint();374origin.path = path;375for (uint32_t i : path) {376if (!descendant.Derive(descendant, i)) return std::nullopt;377}378return std::make_pair(descendant, origin);379}381void CExtKey::SetSeed(std::span<const std::byte> seed)382{383Assert(16 <= seed.size() && seed.size() <= 64);384static const unsigned char hashkey[] = {'B','i','t','c','o','i','n',' ','s','e','e','d'};385std::vector<unsigned char, secure_allocator<unsigned char>> vout(64);386CHMAC_SHA512{hashkey, sizeof(hashkey)}.Write(UCharCast(seed.data()), seed.size()).Finalize(vout.data());387key.Set(vout.data(), vout.data() + 32, true);388memcpy(chaincode.begin(), vout.data() + 32, 32);389nDepth = 0;390nChild = 0;391fingerprint.fill(0);392}394CExtPubKey CExtKey::Neuter() const {395CExtPubKey ret;396ret.nDepth = nDepth;397ret.fingerprint = fingerprint;398ret.nChild = nChild;399ret.pubkey = key.GetPubKey();400ret.chaincode = chaincode;401return ret;402}404void CExtKey::Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const {405code[0] = nDepth;406std::ranges::copy(fingerprint, code+1);407WriteBE32(code+5, nChild);408memcpy(code+9, chaincode.begin(), 32);409code[41] = 0;410assert(key.size() == 32);411memcpy(code+42, key.begin(), 32);412}414void CExtKey::Decode(const unsigned char code[BIP32_EXTKEY_SIZE]) {415nDepth = code[0];416std::copy_n(code + 1, fingerprint.size(), fingerprint.begin());417nChild = ReadBE32(code+5);418memcpy(chaincode.begin(), code+9, 32);419key.Set(code+42, code+BIP32_EXTKEY_SIZE, true);420if ((nDepth == 0 && (nChild != 0 || ReadLE32(fingerprint.data()) != 0)) || code[41] != 0) key = CKey();421}423KeyPair::KeyPair(const CKey& key, const uint256* merkle_root)424{425static_assert(std::tuple_size<KeyType>() == sizeof(secp256k1_keypair));426MakeKeyPairData();427auto keypair = reinterpret_cast<secp256k1_keypair*>(m_keypair->data());428bool success = secp256k1_keypair_create(secp256k1_context_sign, keypair, UCharCast(key.data()));429if (success && merkle_root) {430secp256k1_xonly_pubkey pubkey;431unsigned char pubkey_bytes[32];432assert(secp256k1_keypair_xonly_pub(secp256k1_context_static, &pubkey, nullptr, keypair));433assert(secp256k1_xonly_pubkey_serialize(secp256k1_context_static, pubkey_bytes, &pubkey));434uint256 tweak = XOnlyPubKey(pubkey_bytes).ComputeTapTweakHash(merkle_root->IsNull() ? nullptr : merkle_root);435success = secp256k1_keypair_xonly_tweak_add(secp256k1_context_static, keypair, tweak.data());436}437if (!success) ClearKeyPairData();438}440bool KeyPair::SignSchnorr(const uint256& hash, std::span<unsigned char> sig, const uint256& aux) const441{442assert(sig.size() == 64);443if (!IsValid()) return false;444auto keypair = reinterpret_cast<const secp256k1_keypair*>(m_keypair->data());445bool ret = secp256k1_schnorrsig_sign32(secp256k1_context_sign, sig.data(), hash.data(), keypair, aux.data());446if (ret) {447// Additional verification step to prevent using a potentially corrupted signature448secp256k1_xonly_pubkey pubkey_verify;449ret = secp256k1_keypair_xonly_pub(secp256k1_context_static, &pubkey_verify, nullptr, keypair);450ret &= secp256k1_schnorrsig_verify(secp256k1_context_static, sig.data(), hash.begin(), 32, &pubkey_verify);451}452if (!ret) memory_cleanse(sig.data(), sig.size());453return ret;454}456bool ECC_InitSanityCheck() {457CKey key = GenerateRandomKey();458CPubKey pubkey = key.GetPubKey();459return key.VerifyPubKey(pubkey);460}462secp256k1_context* GetSecp256k1SignContext()463{464return secp256k1_context_sign;465}467/** Initialize the elliptic curve support. May not be called twice without calling ECC_Stop first. */468static void ECC_Start() {469assert(secp256k1_context_sign == nullptr);471secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);472assert(ctx != nullptr);474{475// Pass in a random blinding seed to the secp256k1 context.476std::vector<unsigned char, secure_allocator<unsigned char>> vseed(32);477GetRandBytes(vseed);478bool ret = secp256k1_context_randomize(ctx, vseed.data());479assert(ret);480}482secp256k1_context_sign = ctx;483}485/** Deinitialize the elliptic curve support. No-op if ECC_Start wasn't called first. */486static void ECC_Stop() {487secp256k1_context *ctx = secp256k1_context_sign;488secp256k1_context_sign = nullptr;490if (ctx) {491secp256k1_context_destroy(ctx);492}493}495ECC_Context::ECC_Context()496{497ECC_Start();498}500ECC_Context::~ECC_Context()
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.