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.
251const auto v2_extras = Cat<std::vector<RPCResult>>(252std::vector<RPCResult>{{253RPCResult::Type::NUM, "fee", /*optional=*/true,254"transaction fee in " + CURRENCY_UNIT + ", omitted if block undo data is not available"255}},256TxDoc({.elision_mode = ElisionMode::Silent,257.prevout = true,258.prevout_optional = true,259.vin_inner_elision = "Same vin fields as verbosity = 1"}));260return RPCMethod{261"getrawtransaction",263"By default, this call only returns a transaction if it is in the mempool. If -txindex is enabled\n"264"and no blockhash argument is passed, it will return the transaction if it is in the mempool or any block.\n"265"If a blockhash argument is passed, it will return the transaction if\n"266"the specified block is available and the transaction is in that block.\n\n"267"Hint: Use gettransaction for wallet transactions.\n\n"269"If verbosity is 0 or omitted, returns the serialized transaction as a hex-encoded string.\n"270"If verbosity is 1, returns a JSON Object with information about the transaction.\n"271"If verbosity is 2, returns a JSON Object with information about the transaction, including fee and prevout information.",272{273{"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},274{"verbosity|verbose", RPCArg::Type::NUM, RPCArg::Default{0}, "0 for hex-encoded data, 1 for a JSON object, and 2 for JSON object with fee and prevout",275RPCArgOptions{.skip_type_check = true}},276{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "The block in which to look for the transaction"},277},278{279RPCResult{"if verbosity is not set or set to 0",280RPCResult::Type::STR, "data", "The serialized transaction as a hex-encoded string for 'txid'"281},282RPCResult{"if verbosity is set to 1",283RPCResult::Type::OBJ, "", "",284Cat<std::vector<RPCResult>>(285verbosity_1_block,286TxDoc({.txid_field_doc="The transaction id (same as provided)"})),287},288RPCResult{"for verbosity = 2", RPCResult::Type::OBJ, "", "",289Cat(ElideGroup(verbosity_1_block, "Same output as verbosity = 1"), v2_extras)},290},291RPCExamples{292HelpExampleCli("getrawtransaction", "\"mytxid\"")293+ HelpExampleCli("getrawtransaction", "\"mytxid\" 1")294+ HelpExampleRpc("getrawtransaction", "\"mytxid\", 1")295+ HelpExampleCli("getrawtransaction", "\"mytxid\" 0 \"myblockhash\"")296+ HelpExampleCli("getrawtransaction", "\"mytxid\" 1 \"myblockhash\"")297+ HelpExampleCli("getrawtransaction", "\"mytxid\" 2 \"myblockhash\"")298},299[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue300{301const NodeContext& node = EnsureAnyNodeContext(request.context);302ChainstateManager& chainman = EnsureChainman(node);304auto txid{Txid::FromUint256(ParseHashV(request.params[0], "parameter 1"))};305const CBlockIndex* blockindex = nullptr;307if (txid.ToUint256() == chainman.GetParams().GenesisBlock().hashMerkleRoot) {308// Special exception for the genesis block coinbase transaction309throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "The genesis block coinbase is not considered an ordinary transaction and cannot be retrieved");310}312int verbosity{ParseVerbosity(request.params[1], /*default_verbosity=*/0, /*allow_bool=*/true)};314if (!request.params[2].isNull()) {315LOCK(cs_main);317uint256 blockhash = ParseHashV(request.params[2], "parameter 3");318blockindex = chainman.m_blockman.LookupBlockIndex(blockhash);319if (!blockindex) {320throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block hash not found");321}322}324bool f_txindex_ready = false;325if (g_txindex && !blockindex) {326f_txindex_ready = g_txindex->BlockUntilSyncedToCurrentChain();327}329uint256 hash_block;330const CTransactionRef tx = GetTransaction(blockindex, node.mempool.get(), txid, chainman.m_blockman, hash_block);331if (!tx) {332std::string errmsg;333if (blockindex) {334const bool block_has_data = WITH_LOCK(::cs_main, return blockindex->nStatus & BLOCK_HAVE_DATA);335if (!block_has_data) {336throw JSONRPCError(RPC_MISC_ERROR, "Block not available");337}338errmsg = "No such transaction found in the provided block";339} else if (!g_txindex) {340errmsg = "No such mempool transaction. Use -txindex or provide a block hash to enable blockchain transaction queries";341} else if (!f_txindex_ready) {342errmsg = "No such mempool transaction. Blockchain transactions are still in the process of being indexed";343} else {344errmsg = "No such mempool or blockchain transaction";345}346throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, errmsg + ". Use gettransaction for wallet transactions.");347}349if (verbosity <= 0) {350return EncodeHexTx(*tx);351}353UniValue result(UniValue::VOBJ);354if (blockindex) {355LOCK(cs_main);356result.pushKV("in_active_chain", chainman.ActiveChain().Contains(*blockindex));357}358// If request is verbosity >= 1 but no blockhash was given, then look up the blockindex359if (request.params[2].isNull()) {360LOCK(cs_main);361blockindex = chainman.m_blockman.LookupBlockIndex(hash_block); // May be nullptr for mempool transactions362}364// Add sigop-adjusted virtual size if the transaction exists in the mempool.365if (blockindex == nullptr && hash_block.IsNull() && node.mempool) {366auto info = node.mempool->info(tx->GetHash());367if (info.tx) {368result.pushKV("vsize_adjusted", info.vsize);369}370}372if (verbosity == 1) {373TxToJSON(*tx, hash_block, result, chainman.ActiveChainstate());374return result;375}377CBlockUndo blockUndo;378CBlock block;380if (tx->IsCoinBase() || !blockindex || WITH_LOCK(::cs_main, return !(blockindex->nStatus & BLOCK_HAVE_MASK))) {381TxToJSON(*tx, hash_block, result, chainman.ActiveChainstate());382return result;383}384if (!chainman.m_blockman.ReadBlockUndo(blockUndo, *blockindex)) {385throw JSONRPCError(RPC_INTERNAL_ERROR, "Undo data expected but can't be read. This could be due to disk corruption or a conflict with a pruning event.");386}387if (!chainman.m_blockman.ReadBlock(block, *blockindex)) {388throw JSONRPCError(RPC_INTERNAL_ERROR, "Block data expected but can't be read. This could be due to disk corruption or a conflict with a pruning event.");389}391CTxUndo* undoTX {nullptr};392auto it = std::find_if(block.vtx.begin(), block.vtx.end(), [tx](CTransactionRef t){ return t->Equals(*tx); });393if (it != block.vtx.end()) {394// -1 as blockundo does not have coinbase tx395undoTX = &blockUndo.vtxundo.at(it - block.vtx.begin() - 1);396}397TxToJSON(*tx, hash_block, result, chainman.ActiveChainstate(), undoTX, TxVerbosity::SHOW_DETAILS_AND_PREVOUT);398return result;399},400};401}403static RPCMethod createrawtransaction()404{405return RPCMethod{406"createrawtransaction",407"Create a transaction spending the given inputs and creating new outputs.\n"408"Outputs can be addresses or data.\n"409"Returns hex-encoded raw transaction.\n"410"Note that the transaction's inputs are not signed, and\n"411"it is not stored in the wallet or transmitted to the network.\n",412CreateTxDoc(),413RPCResult{414RPCResult::Type::STR_HEX, "transaction", "hex string of the transaction"415},416RPCExamples{417HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"address\\\":0.01}]\"")418+ HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"")419+ HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"[{\\\"address\\\":0.01}]\"")420+ HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"[{\\\"data\\\":\\\"00010203\\\"}]\"")421},422[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue423{424std::optional<bool> rbf;425if (!request.params[3].isNull()) {426rbf = request.params[3].get_bool();427}428CMutableTransaction rawTx = ConstructTransaction(request.params[0], request.params[1], request.params[2], rbf, self.Arg<uint32_t>("version"));430return EncodeHexTx(CTransaction(rawTx));431},432};433}435static RPCMethod decoderawtransaction()436{437return RPCMethod{"decoderawtransaction",438"Return a JSON object representing the serialized, hex-encoded transaction.",439{440{"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction hex string"},441{"iswitness", RPCArg::Type::BOOL, RPCArg::DefaultHint{"depends on heuristic tests"}, "Whether the transaction hex is a serialized witness transaction.\n"442"If iswitness is not present, heuristic tests will be used in decoding.\n"443"If true, only witness deserialization will be tried.\n"444"If false, only non-witness deserialization will be tried.\n"445"This boolean should reflect whether the transaction has inputs\n"446"(e.g. fully valid, or on-chain transactions), if known by the caller."447},448},449RPCResult{450RPCResult::Type::OBJ, "", "",451TxDoc(),452},453RPCExamples{454HelpExampleCli("decoderawtransaction", "\"hexstring\"")455+ HelpExampleRpc("decoderawtransaction", "\"hexstring\"")456},457[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue458{459CMutableTransaction mtx;461bool try_witness = request.params[1].isNull() ? true : request.params[1].get_bool();462bool try_no_witness = request.params[1].isNull() ? true : !request.params[1].get_bool();464if (!DecodeHexTx(mtx, request.params[0].get_str(), try_no_witness, try_witness)) {465throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");466}468UniValue result(UniValue::VOBJ);469TxToUniv(CTransaction(std::move(mtx)), /*block_hash=*/uint256(), /*entry=*/result, /*include_hex=*/false);471return result;472},473};474}476static RPCMethod decodescript()477{478return RPCMethod{479"decodescript",480"Decode a hex-encoded script.\n",481{482{"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded script"},483},484RPCResult{485RPCResult::Type::OBJ, "", "",486{487{RPCResult::Type::STR, "asm", "Disassembly of the script"},488{RPCResult::Type::STR, "desc", "Inferred descriptor for the script"},489{RPCResult::Type::STR, "type", "The output type (e.g. " + GetAllOutputTypes() + ")"},490{RPCResult::Type::STR, "address", /*optional=*/true, "The Bitcoin address (only if a well-defined address exists)"},491{RPCResult::Type::STR, "p2sh", /*optional=*/true,492"address of P2SH script wrapping this redeem script (not returned for types that should not be wrapped)"},493{RPCResult::Type::OBJ, "segwit", /*optional=*/true,494"Result of a witness output script wrapping this redeem script (not returned for types that should not be wrapped)",495{496{RPCResult::Type::STR, "asm", "Disassembly of the output script"},497{RPCResult::Type::STR_HEX, "hex", "The raw output script bytes, hex-encoded"},498{RPCResult::Type::STR, "type", "The type of the output script (e.g. witness_v0_keyhash or witness_v0_scripthash)"},499{RPCResult::Type::STR, "address", /*optional=*/true, "The Bitcoin address (only if a well-defined address exists)"},500{RPCResult::Type::STR, "desc", "Inferred descriptor for the script"},