Inside Bitcoin
Opening the selected file…
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.
501struct btck_BlockSpentOutputs : Handle<btck_BlockSpentOutputs, std::shared_ptr<CBlockUndo>> {};502struct btck_TransactionSpentOutputs : Handle<btck_TransactionSpentOutputs, CTxUndo> {};503struct btck_Coin : Handle<btck_Coin, Coin> {};504struct btck_BlockHash : Handle<btck_BlockHash, uint256> {};505struct btck_TransactionInput : Handle<btck_TransactionInput, CTxIn> {};506struct btck_WitnessStack : Handle<btck_WitnessStack, CScriptWitness> {};507struct btck_TransactionOutPoint: Handle<btck_TransactionOutPoint, COutPoint> {};508struct btck_Txid: Handle<btck_Txid, Txid> {};509struct btck_PrecomputedTransactionData : Handle<btck_PrecomputedTransactionData, PrecomputedTransactionData> {};510struct btck_BlockHeader: Handle<btck_BlockHeader, CBlockHeader> {};511struct btck_ConsensusParams: Handle<btck_ConsensusParams, Consensus::Params> {};513btck_Transaction* btck_transaction_create(const void* raw_transaction, size_t raw_transaction_len)514{515assert(raw_transaction != nullptr || raw_transaction_len == 0);516try {517SpanReader stream{std::span{reinterpret_cast<const std::byte*>(raw_transaction), raw_transaction_len}};518return btck_Transaction::create(std::make_shared<const CTransaction>(deserialize, TX_WITH_WITNESS, stream));519} catch (...) {520return nullptr;521}522}524size_t btck_transaction_count_outputs(const btck_Transaction* transaction)525{526return btck_Transaction::get(transaction)->vout.size();527}529const btck_TransactionOutput* btck_transaction_get_output_at(const btck_Transaction* transaction, size_t output_index)530{531const CTransaction& tx = *btck_Transaction::get(transaction);532assert(output_index < tx.vout.size());533return btck_TransactionOutput::ref(&tx.vout[output_index]);534}536size_t btck_transaction_count_inputs(const btck_Transaction* transaction)537{538return btck_Transaction::get(transaction)->vin.size();539}541const btck_TransactionInput* btck_transaction_get_input_at(const btck_Transaction* transaction, size_t input_index)542{543assert(input_index < btck_Transaction::get(transaction)->vin.size());544return btck_TransactionInput::ref(&btck_Transaction::get(transaction)->vin[input_index]);545}547uint32_t btck_transaction_get_locktime(const btck_Transaction* transaction)548{549return btck_Transaction::get(transaction)->nLockTime;550}552const btck_Txid* btck_transaction_get_txid(const btck_Transaction* transaction)553{554return btck_Txid::ref(&btck_Transaction::get(transaction)->GetHash());555}557btck_Transaction* btck_transaction_copy(const btck_Transaction* transaction)558{559return btck_Transaction::copy(transaction);560}562int btck_transaction_to_bytes(const btck_Transaction* transaction, btck_WriteBytes writer, void* user_data)563{564try {565WriterStream ws{writer, user_data};566ws << TX_WITH_WITNESS(btck_Transaction::get(transaction));567return 0;568} catch (...) {569return -1;570}571}573void btck_transaction_destroy(btck_Transaction* transaction)574{575delete transaction;576}578btck_ScriptPubkey* btck_script_pubkey_create(const void* script_pubkey, size_t script_pubkey_len)579{580assert(script_pubkey != nullptr || script_pubkey_len == 0);581auto data = std::span{reinterpret_cast<const uint8_t*>(script_pubkey), script_pubkey_len};582return btck_ScriptPubkey::create(data.begin(), data.end());583}585int btck_script_pubkey_to_bytes(const btck_ScriptPubkey* script_pubkey_, btck_WriteBytes writer, void* user_data)586{587const auto& script_pubkey{btck_ScriptPubkey::get(script_pubkey_)};588return writer(script_pubkey.data(), script_pubkey.size(), user_data);589}591btck_ScriptPubkey* btck_script_pubkey_copy(const btck_ScriptPubkey* script_pubkey)592{593return btck_ScriptPubkey::copy(script_pubkey);594}596void btck_script_pubkey_destroy(btck_ScriptPubkey* script_pubkey)597{598delete script_pubkey;599}601btck_TransactionOutput* btck_transaction_output_create(const btck_ScriptPubkey* script_pubkey, int64_t amount)602{603return btck_TransactionOutput::create(amount, btck_ScriptPubkey::get(script_pubkey));604}606btck_TransactionOutput* btck_transaction_output_copy(const btck_TransactionOutput* output)607{608return btck_TransactionOutput::copy(output);609}611const btck_ScriptPubkey* btck_transaction_output_get_script_pubkey(const btck_TransactionOutput* output)612{613return btck_ScriptPubkey::ref(&btck_TransactionOutput::get(output).scriptPubKey);614}616int64_t btck_transaction_output_get_amount(const btck_TransactionOutput* output)617{618return btck_TransactionOutput::get(output).nValue;619}621void btck_transaction_output_destroy(btck_TransactionOutput* output)622{623delete output;624}626btck_PrecomputedTransactionData* btck_precomputed_transaction_data_create(627const btck_Transaction* tx_to,628const btck_TransactionOutput** spent_outputs_, size_t spent_outputs_len)629{630try {631const CTransaction& tx{*btck_Transaction::get(tx_to)};632auto txdata{btck_PrecomputedTransactionData::create()};633if (spent_outputs_ != nullptr && spent_outputs_len > 0) {634assert(spent_outputs_len == tx.vin.size());635std::vector<CTxOut> spent_outputs;636spent_outputs.reserve(spent_outputs_len);637for (size_t i = 0; i < spent_outputs_len; i++) {638const CTxOut& tx_out{btck_TransactionOutput::get(spent_outputs_[i])};639spent_outputs.push_back(tx_out);640}641btck_PrecomputedTransactionData::get(txdata).Init(tx, std::move(spent_outputs));642} else {643btck_PrecomputedTransactionData::get(txdata).Init(tx, {});644}646return txdata;647} catch (...) {648return nullptr;649}650}652btck_PrecomputedTransactionData* btck_precomputed_transaction_data_copy(const btck_PrecomputedTransactionData* precomputed_txdata)653{654return btck_PrecomputedTransactionData::copy(precomputed_txdata);655}657void btck_precomputed_transaction_data_destroy(btck_PrecomputedTransactionData* precomputed_txdata)658{659delete precomputed_txdata;660}662int btck_script_pubkey_verify(const btck_ScriptPubkey* script_pubkey,663const int64_t amount,664const btck_Transaction* tx_to,665const btck_PrecomputedTransactionData* precomputed_txdata,666const unsigned int input_index,667const btck_ScriptVerificationFlags flags,668btck_ScriptVerifyStatus* status)669{670// Assert that all specified flags are part of the interface before continuing671assert((flags & ~btck_ScriptVerificationFlags_ALL) == 0);673if (!is_valid_flag_combination(script_verify_flags::from_int(flags))) {674if (status) *status = btck_ScriptVerifyStatus_ERROR_INVALID_FLAGS_COMBINATION;675return 0;676}678const CTransaction& tx{*btck_Transaction::get(tx_to)};679assert(input_index < tx.vin.size());681const PrecomputedTransactionData& txdata{precomputed_txdata ? btck_PrecomputedTransactionData::get(precomputed_txdata) : PrecomputedTransactionData(tx)};683if (flags & btck_ScriptVerificationFlags_TAPROOT && txdata.m_spent_outputs.empty()) {684if (status) *status = btck_ScriptVerifyStatus_ERROR_SPENT_OUTPUTS_REQUIRED;685return 0;686}688if (status) *status = btck_ScriptVerifyStatus_OK;690bool result = VerifyScript(tx.vin[input_index].scriptSig,691btck_ScriptPubkey::get(script_pubkey),692&tx.vin[input_index].scriptWitness,693script_verify_flags::from_int(flags),694TransactionSignatureChecker(&tx, input_index, amount, txdata, MissingDataBehavior::FAIL),695nullptr);696return result ? 1 : 0;697}699btck_TransactionInput* btck_transaction_input_copy(const btck_TransactionInput* input)700{701return btck_TransactionInput::copy(input);702}704const btck_TransactionOutPoint* btck_transaction_input_get_out_point(const btck_TransactionInput* input)705{706return btck_TransactionOutPoint::ref(&btck_TransactionInput::get(input).prevout);707}709uint32_t btck_transaction_input_get_sequence(const btck_TransactionInput* input)710{711return btck_TransactionInput::get(input).nSequence;712}714const btck_WitnessStack* btck_transaction_input_get_witness_stack(const btck_TransactionInput* input)715{716return btck_WitnessStack::ref(&btck_TransactionInput::get(input).scriptWitness);717}719int btck_transaction_input_get_script_sig(const btck_TransactionInput* input, btck_WriteBytes writer, void* user_data)720{721const auto& script_sig{btck_TransactionInput::get(input).scriptSig};722return writer(script_sig.data(), script_sig.size(), user_data);723}725void btck_transaction_input_destroy(btck_TransactionInput* input)726{727delete input;728}730size_t btck_witness_stack_count_items(const btck_WitnessStack* witness_stack)731{732return btck_WitnessStack::get(witness_stack).stack.size();733}735int btck_witness_stack_get_item_at(const btck_WitnessStack* witness_stack, size_t index, btck_WriteBytes writer, void* user_data)736{737const auto& stack{btck_WitnessStack::get(witness_stack).stack};738assert(index < stack.size());739return writer(stack[index].data(), stack[index].size(), user_data);740}742btck_WitnessStack* btck_witness_stack_copy(const btck_WitnessStack* witness_stack)743{744return btck_WitnessStack::copy(witness_stack);745}747void btck_witness_stack_destroy(btck_WitnessStack* witness_stack)748{749delete witness_stack;750}