diff options
author | MarcoFalke <falke.marco@gmail.com> | 2022-03-28 08:53:29 +0200 |
---|---|---|
committer | MarcoFalke <falke.marco@gmail.com> | 2022-03-28 08:53:48 +0200 |
commit | 3d2f24bb388a65ed7b7af5995c3f65dcf184d2f4 (patch) | |
tree | 87cbc405960bd24a0ad1b0ea6387b76558136bf1 /src/rpc/rawtransaction.cpp | |
parent | 2f0f056e08cd5a1435120592a9ecd212fcdb915b (diff) | |
parent | fac5a51c47fba21678fb35805e40d00fe7c891a0 (diff) | |
download | bitcoin-3d2f24bb388a65ed7b7af5995c3f65dcf184d2f4.tar.xz |
Merge bitcoin/bitcoin#24656: refactor: Move mempool RPCs to rpc/mempool
fac5a51c47fba21678fb35805e40d00fe7c891a0 Move mempool RPCs to rpc/mempool (MarcoFalke)
fa0f666dd7b55a5a0250c5e35d2c3dfd565463b7 style: Add static keyword where possible in rpc/mempool (MarcoFalke)
Pull request description:
This moves the remaining mempool RPCs to `rpc/mempool`. Previously all mempool RPCs from the `blockchain` category have been moved. This patch moves the ones from the `rawtransactions` category.
In the future, as a follow-up to this refactoring patch, it could be considered whether a new `mempool` category should be introduced.
Beside a clearer code organization, this pull request should also reduce the compile time and space of the `rawtransactions.cpp` file.
ACKs for top commit:
promag:
Code review ACK fac5a51c47fba21678fb35805e40d00fe7c891a0.
Tree-SHA512: 5578b894b68d0595869a9b03ed8dceebe3366f73dec5f090ccc36ff4002b1bc4d58af77546c2d71537c1be03694d9a28c4b1bfbb3569560997879293c5c0301e
Diffstat (limited to 'src/rpc/rawtransaction.cpp')
-rw-r--r-- | src/rpc/rawtransaction.cpp | 208 |
1 files changed, 0 insertions, 208 deletions
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 8e60e82f35..7858cc4268 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -33,7 +33,6 @@ #include <script/standard.h> #include <uint256.h> #include <util/bip32.h> -#include <util/moneystr.h> #include <util/strencodings.h> #include <util/string.h> #include <validation.h> @@ -46,7 +45,6 @@ using node::AnalyzePSBT; using node::BroadcastTransaction; -using node::DEFAULT_MAX_RAW_TX_FEE_RATE; using node::FindCoins; using node::GetTransaction; using node::NodeContext; @@ -714,210 +712,6 @@ static RPCHelpMan signrawtransactionwithkey() }; } -static RPCHelpMan sendrawtransaction() -{ - return RPCHelpMan{"sendrawtransaction", - "\nSubmit a raw transaction (serialized, hex-encoded) to local node and network.\n" - "\nThe transaction will be sent unconditionally to all peers, so using sendrawtransaction\n" - "for manual rebroadcast may degrade privacy by leaking the transaction's origin, as\n" - "nodes will normally not rebroadcast non-wallet transactions already in their mempool.\n" - "\nA specific exception, RPC_TRANSACTION_ALREADY_IN_CHAIN, may throw if the transaction cannot be added to the mempool.\n" - "\nRelated RPCs: createrawtransaction, signrawtransactionwithkey\n", - { - {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex string of the raw transaction"}, - {"maxfeerate", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK())}, - "Reject transactions whose fee rate is higher than the specified value, expressed in " + CURRENCY_UNIT + - "/kvB.\nSet to 0 to accept any fee rate.\n"}, - }, - RPCResult{ - RPCResult::Type::STR_HEX, "", "The transaction hash in hex" - }, - RPCExamples{ - "\nCreate a transaction\n" - + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" \"{\\\"myaddress\\\":0.01}\"") + - "Sign the transaction, and get back the hex\n" - + HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") + - "\nSend the transaction (signed hex)\n" - + HelpExampleCli("sendrawtransaction", "\"signedhex\"") + - "\nAs a JSON-RPC call\n" - + HelpExampleRpc("sendrawtransaction", "\"signedhex\"") - }, - [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue -{ - RPCTypeCheck(request.params, { - UniValue::VSTR, - UniValueType(), // VNUM or VSTR, checked inside AmountFromValue() - }); - - CMutableTransaction mtx; - if (!DecodeHexTx(mtx, request.params[0].get_str())) { - throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed. Make sure the tx has at least one input."); - } - CTransactionRef tx(MakeTransactionRef(std::move(mtx))); - - const CFeeRate max_raw_tx_fee_rate = request.params[1].isNull() ? - DEFAULT_MAX_RAW_TX_FEE_RATE : - CFeeRate(AmountFromValue(request.params[1])); - - int64_t virtual_size = GetVirtualTransactionSize(*tx); - CAmount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size); - - std::string err_string; - AssertLockNotHeld(cs_main); - NodeContext& node = EnsureAnyNodeContext(request.context); - const TransactionError err = BroadcastTransaction(node, tx, err_string, max_raw_tx_fee, /*relay*/ true, /*wait_callback*/ true); - if (TransactionError::OK != err) { - throw JSONRPCTransactionError(err, err_string); - } - - return tx->GetHash().GetHex(); -}, - }; -} - -static RPCHelpMan testmempoolaccept() -{ - return RPCHelpMan{"testmempoolaccept", - "\nReturns result of mempool acceptance tests indicating if raw transaction(s) (serialized, hex-encoded) would be accepted by mempool.\n" - "\nIf multiple transactions are passed in, parents must come before children and package policies apply: the transactions cannot conflict with any mempool transactions or each other.\n" - "\nIf one transaction fails, other transactions may not be fully validated (the 'allowed' key will be blank).\n" - "\nThe maximum number of transactions allowed is " + ToString(MAX_PACKAGE_COUNT) + ".\n" - "\nThis checks if transactions violate the consensus or policy rules.\n" - "\nSee sendrawtransaction call.\n", - { - {"rawtxs", RPCArg::Type::ARR, RPCArg::Optional::NO, "An array of hex strings of raw transactions.", - { - {"rawtx", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""}, - }, - }, - {"maxfeerate", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK())}, - "Reject transactions whose fee rate is higher than the specified value, expressed in " + CURRENCY_UNIT + "/kvB\n"}, - }, - RPCResult{ - RPCResult::Type::ARR, "", "The result of the mempool acceptance test for each raw transaction in the input array.\n" - "Returns results for each transaction in the same order they were passed in.\n" - "Transactions that cannot be fully validated due to failures in other transactions will not contain an 'allowed' result.\n", - { - {RPCResult::Type::OBJ, "", "", - { - {RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"}, - {RPCResult::Type::STR_HEX, "wtxid", "The transaction witness hash in hex"}, - {RPCResult::Type::STR, "package-error", /*optional=*/true, "Package validation error, if any (only possible if rawtxs had more than 1 transaction)."}, - {RPCResult::Type::BOOL, "allowed", /*optional=*/true, "Whether this tx would be accepted to the mempool and pass client-specified maxfeerate. " - "If not present, the tx was not fully validated due to a failure in another tx in the list."}, - {RPCResult::Type::NUM, "vsize", /*optional=*/true, "Virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted (only present when 'allowed' is true)"}, - {RPCResult::Type::OBJ, "fees", /*optional=*/true, "Transaction fees (only present if 'allowed' is true)", - { - {RPCResult::Type::STR_AMOUNT, "base", "transaction fee in " + CURRENCY_UNIT}, - }}, - {RPCResult::Type::STR, "reject-reason", /*optional=*/true, "Rejection string (only present when 'allowed' is false)"}, - }}, - } - }, - RPCExamples{ - "\nCreate a transaction\n" - + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" \"{\\\"myaddress\\\":0.01}\"") + - "Sign the transaction, and get back the hex\n" - + HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") + - "\nTest acceptance of the transaction (signed hex)\n" - + HelpExampleCli("testmempoolaccept", R"('["signedhex"]')") + - "\nAs a JSON-RPC call\n" - + HelpExampleRpc("testmempoolaccept", "[\"signedhex\"]") - }, - [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue -{ - RPCTypeCheck(request.params, { - UniValue::VARR, - UniValueType(), // VNUM or VSTR, checked inside AmountFromValue() - }); - const UniValue raw_transactions = request.params[0].get_array(); - if (raw_transactions.size() < 1 || raw_transactions.size() > MAX_PACKAGE_COUNT) { - throw JSONRPCError(RPC_INVALID_PARAMETER, - "Array must contain between 1 and " + ToString(MAX_PACKAGE_COUNT) + " transactions."); - } - - const CFeeRate max_raw_tx_fee_rate = request.params[1].isNull() ? - DEFAULT_MAX_RAW_TX_FEE_RATE : - CFeeRate(AmountFromValue(request.params[1])); - - std::vector<CTransactionRef> txns; - txns.reserve(raw_transactions.size()); - for (const auto& rawtx : raw_transactions.getValues()) { - CMutableTransaction mtx; - if (!DecodeHexTx(mtx, rawtx.get_str())) { - throw JSONRPCError(RPC_DESERIALIZATION_ERROR, - "TX decode failed: " + rawtx.get_str() + " Make sure the tx has at least one input."); - } - txns.emplace_back(MakeTransactionRef(std::move(mtx))); - } - - NodeContext& node = EnsureAnyNodeContext(request.context); - CTxMemPool& mempool = EnsureMemPool(node); - ChainstateManager& chainman = EnsureChainman(node); - CChainState& chainstate = chainman.ActiveChainstate(); - const PackageMempoolAcceptResult package_result = [&] { - LOCK(::cs_main); - if (txns.size() > 1) return ProcessNewPackage(chainstate, mempool, txns, /* test_accept */ true); - return PackageMempoolAcceptResult(txns[0]->GetWitnessHash(), - chainman.ProcessTransaction(txns[0], /*test_accept=*/ true)); - }(); - - UniValue rpc_result(UniValue::VARR); - // We will check transaction fees while we iterate through txns in order. If any transaction fee - // exceeds maxfeerate, we will leave the rest of the validation results blank, because it - // doesn't make sense to return a validation result for a transaction if its ancestor(s) would - // not be submitted. - bool exit_early{false}; - for (const auto& tx : txns) { - UniValue result_inner(UniValue::VOBJ); - result_inner.pushKV("txid", tx->GetHash().GetHex()); - result_inner.pushKV("wtxid", tx->GetWitnessHash().GetHex()); - if (package_result.m_state.GetResult() == PackageValidationResult::PCKG_POLICY) { - result_inner.pushKV("package-error", package_result.m_state.GetRejectReason()); - } - auto it = package_result.m_tx_results.find(tx->GetWitnessHash()); - if (exit_early || it == package_result.m_tx_results.end()) { - // Validation unfinished. Just return the txid and wtxid. - rpc_result.push_back(result_inner); - continue; - } - const auto& tx_result = it->second; - // Package testmempoolaccept doesn't allow transactions to already be in the mempool. - CHECK_NONFATAL(tx_result.m_result_type != MempoolAcceptResult::ResultType::MEMPOOL_ENTRY); - if (tx_result.m_result_type == MempoolAcceptResult::ResultType::VALID) { - const CAmount fee = tx_result.m_base_fees.value(); - // Check that fee does not exceed maximum fee - const int64_t virtual_size = tx_result.m_vsize.value(); - const CAmount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size); - if (max_raw_tx_fee && fee > max_raw_tx_fee) { - result_inner.pushKV("allowed", false); - result_inner.pushKV("reject-reason", "max-fee-exceeded"); - exit_early = true; - } else { - // Only return the fee and vsize if the transaction would pass ATMP. - // These can be used to calculate the feerate. - result_inner.pushKV("allowed", true); - result_inner.pushKV("vsize", virtual_size); - UniValue fees(UniValue::VOBJ); - fees.pushKV("base", ValueFromAmount(fee)); - result_inner.pushKV("fees", fees); - } - } else { - result_inner.pushKV("allowed", false); - const TxValidationState state = tx_result.m_state; - if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) { - result_inner.pushKV("reject-reason", "missing-inputs"); - } else { - result_inner.pushKV("reject-reason", state.GetRejectReason()); - } - } - rpc_result.push_back(result_inner); - } - return rpc_result; -}, - }; -} - static RPCHelpMan decodepsbt() { return RPCHelpMan{ @@ -1928,10 +1722,8 @@ static const CRPCCommand commands[] = { "rawtransactions", &createrawtransaction, }, { "rawtransactions", &decoderawtransaction, }, { "rawtransactions", &decodescript, }, - { "rawtransactions", &sendrawtransaction, }, { "rawtransactions", &combinerawtransaction, }, { "rawtransactions", &signrawtransactionwithkey, }, - { "rawtransactions", &testmempoolaccept, }, { "rawtransactions", &decodepsbt, }, { "rawtransactions", &combinepsbt, }, { "rawtransactions", &finalizepsbt, }, |