aboutsummaryrefslogtreecommitdiff
path: root/src/rpc/rawtransaction.cpp
diff options
context:
space:
mode:
authorMarcoFalke <falke.marco@gmail.com>2022-03-16 12:06:15 +0100
committerMarcoFalke <falke.marco@gmail.com>2022-03-17 08:42:14 +0100
commitfa2d176016683eac82dabfbfc276b8a7b07b7499 (patch)
treee0911bfe022cd05f7f4be7062d087a95d4d9172e /src/rpc/rawtransaction.cpp
parentbf2c0fb2a26432762bf98e19a98e252b7bdd7d30 (diff)
downloadbitcoin-fa2d176016683eac82dabfbfc276b8a7b07b7499.tar.xz
Move txoutproof RPCs to txoutproof.cpp
Diffstat (limited to 'src/rpc/rawtransaction.cpp')
-rw-r--r--src/rpc/rawtransaction.cpp153
1 files changed, 0 insertions, 153 deletions
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 1ef531b293..148734f31a 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -11,7 +11,6 @@
#include <core_io.h>
#include <index/txindex.h>
#include <key_io.h>
-#include <merkleblock.h>
#include <node/blockstorage.h>
#include <node/coin.h>
#include <node/context.h>
@@ -268,155 +267,6 @@ static RPCHelpMan getrawtransaction()
};
}
-static RPCHelpMan gettxoutproof()
-{
- return RPCHelpMan{"gettxoutproof",
- "\nReturns a hex-encoded proof that \"txid\" was included in a block.\n"
- "\nNOTE: By default this function only works sometimes. This is when there is an\n"
- "unspent output in the utxo for this transaction. To make it always work,\n"
- "you need to maintain a transaction index, using the -txindex command line option or\n"
- "specify the block in which the transaction is included manually (by blockhash).\n",
- {
- {"txids", RPCArg::Type::ARR, RPCArg::Optional::NO, "The txids to filter",
- {
- {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "A transaction hash"},
- },
- },
- {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED_NAMED_ARG, "If specified, looks for txid in the block with this hash"},
- },
- RPCResult{
- RPCResult::Type::STR, "data", "A string that is a serialized, hex-encoded data for the proof."
- },
- RPCExamples{""},
- [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
-{
- std::set<uint256> setTxids;
- UniValue txids = request.params[0].get_array();
- if (txids.empty()) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Parameter 'txids' cannot be empty");
- }
- for (unsigned int idx = 0; idx < txids.size(); idx++) {
- auto ret = setTxids.insert(ParseHashV(txids[idx], "txid"));
- if (!ret.second) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated txid: ") + txids[idx].get_str());
- }
- }
-
- const CBlockIndex* pblockindex = nullptr;
- uint256 hashBlock;
- ChainstateManager& chainman = EnsureAnyChainman(request.context);
- if (!request.params[1].isNull()) {
- LOCK(cs_main);
- hashBlock = ParseHashV(request.params[1], "blockhash");
- pblockindex = chainman.m_blockman.LookupBlockIndex(hashBlock);
- if (!pblockindex) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
- }
- } else {
- LOCK(cs_main);
- CChainState& active_chainstate = chainman.ActiveChainstate();
-
- // Loop through txids and try to find which block they're in. Exit loop once a block is found.
- for (const auto& tx : setTxids) {
- const Coin& coin = AccessByTxid(active_chainstate.CoinsTip(), tx);
- if (!coin.IsSpent()) {
- pblockindex = active_chainstate.m_chain[coin.nHeight];
- break;
- }
- }
- }
-
-
- // Allow txindex to catch up if we need to query it and before we acquire cs_main.
- if (g_txindex && !pblockindex) {
- g_txindex->BlockUntilSyncedToCurrentChain();
- }
-
- LOCK(cs_main);
-
- if (pblockindex == nullptr) {
- const CTransactionRef tx = GetTransaction(/* block_index */ nullptr, /* mempool */ nullptr, *setTxids.begin(), Params().GetConsensus(), hashBlock);
- if (!tx || hashBlock.IsNull()) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not yet in block");
- }
- pblockindex = chainman.m_blockman.LookupBlockIndex(hashBlock);
- if (!pblockindex) {
- throw JSONRPCError(RPC_INTERNAL_ERROR, "Transaction index corrupt");
- }
- }
-
- CBlock block;
- if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) {
- throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
- }
-
- unsigned int ntxFound = 0;
- for (const auto& tx : block.vtx) {
- if (setTxids.count(tx->GetHash())) {
- ntxFound++;
- }
- }
- if (ntxFound != setTxids.size()) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Not all transactions found in specified or retrieved block");
- }
-
- CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
- CMerkleBlock mb(block, setTxids);
- ssMB << mb;
- std::string strHex = HexStr(ssMB);
- return strHex;
-},
- };
-}
-
-static RPCHelpMan verifytxoutproof()
-{
- return RPCHelpMan{"verifytxoutproof",
- "\nVerifies that a proof points to a transaction in a block, returning the transaction it commits to\n"
- "and throwing an RPC error if the block is not in our best chain\n",
- {
- {"proof", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex-encoded proof generated by gettxoutproof"},
- },
- RPCResult{
- RPCResult::Type::ARR, "", "",
- {
- {RPCResult::Type::STR_HEX, "txid", "The txid(s) which the proof commits to, or empty array if the proof cannot be validated."},
- }
- },
- RPCExamples{""},
- [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
-{
- CDataStream ssMB(ParseHexV(request.params[0], "proof"), SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
- CMerkleBlock merkleBlock;
- ssMB >> merkleBlock;
-
- UniValue res(UniValue::VARR);
-
- std::vector<uint256> vMatch;
- std::vector<unsigned int> vIndex;
- if (merkleBlock.txn.ExtractMatches(vMatch, vIndex) != merkleBlock.header.hashMerkleRoot)
- return res;
-
- ChainstateManager& chainman = EnsureAnyChainman(request.context);
- LOCK(cs_main);
-
- const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(merkleBlock.header.GetHash());
- if (!pindex || !chainman.ActiveChain().Contains(pindex) || pindex->nTx == 0) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found in chain");
- }
-
- // Check if proof is valid, only add results if so
- if (pindex->nTx == merkleBlock.txn.GetNumTransactions()) {
- for (const uint256& hash : vMatch) {
- res.push_back(hash.GetHex());
- }
- }
-
- return res;
-},
- };
-}
-
static RPCHelpMan createrawtransaction()
{
return RPCHelpMan{"createrawtransaction",
@@ -2089,9 +1939,6 @@ static const CRPCCommand commands[] =
{ "rawtransactions", &utxoupdatepsbt, },
{ "rawtransactions", &joinpsbts, },
{ "rawtransactions", &analyzepsbt, },
-
- { "blockchain", &gettxoutproof, },
- { "blockchain", &verifytxoutproof, },
};
// clang-format on
for (const auto& c : commands) {