aboutsummaryrefslogtreecommitdiff
path: root/src/rpc/rawtransaction.cpp
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2018-04-02 16:00:57 +0200
committerWladimir J. van der Laan <laanwj@gmail.com>2018-04-02 16:02:33 +0200
commit18815b4bfb20c9c1112e547217662529d81e4393 (patch)
tree65e21644eea8257d651d10dc8201df67221e3674 /src/rpc/rawtransaction.cpp
parent821980c00feef143a6ecf6af65926e18cfd30396 (diff)
parentb55555da3e25a47f1e7fced7f09d4f0bf8198624 (diff)
Merge #11742: rpc: Add testmempoolaccept
b55555d rpc: Add testmempoolaccept (MarcoFalke) Pull request description: To check if a single raw transaction makes it into the current transaction pool, one had to call `sendrawtransaction`. However, on success, this adds the transaction to the mempool with no easy way to undo. The call `testmempoolaccept` is introduced to provide a way to solely check the result without changing the mempool state. Tree-SHA512: 5afd9311190135cee8fc1f229c7d39bf893f1028f29e28d34f70df820198ff97b4bf86b41cbbd6e6c36a5c30073cefa92d541c74a4939c7a2a6fa283dfd41b63
Diffstat (limited to 'src/rpc/rawtransaction.cpp')
-rw-r--r--src/rpc/rawtransaction.cpp82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 77040f75fd..9d7aa58894 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -1134,6 +1134,87 @@ UniValue sendrawtransaction(const JSONRPCRequest& request)
return hashTx.GetHex();
}
+UniValue testmempoolaccept(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
+ throw std::runtime_error(
+ // clang-format off
+ "testmempoolaccept [\"rawtxs\"] ( allowhighfees )\n"
+ "\nReturns if raw transaction (serialized, hex-encoded) would be accepted by mempool.\n"
+ "\nThis checks if the transaction violates the consensus or policy rules.\n"
+ "\nSee sendrawtransaction call.\n"
+ "\nArguments:\n"
+ "1. [\"rawtxs\"] (array, required) An array of hex strings of raw transactions.\n"
+ " Length must be one for now.\n"
+ "2. allowhighfees (boolean, optional, default=false) Allow high fees\n"
+ "\nResult:\n"
+ "[ (array) The result of the mempool acceptance test for each raw transaction in the input array.\n"
+ " Length is exactly one for now.\n"
+ " {\n"
+ " \"txid\" (string) The transaction hash in hex\n"
+ " \"allowed\" (boolean) If the mempool allows this tx to be inserted\n"
+ " \"reject-reason\" (string) Rejection string (only present when 'allowed' is false)\n"
+ " }\n"
+ "]\n"
+ "\nExamples:\n"
+ "\nCreate a transaction\n"
+ + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" \"{\\\"myaddress\\\":0.01}\"") +
+ "Sign the transaction, and get back the hex\n"
+ + HelpExampleCli("signrawtransaction", "\"myhex\"") +
+ "\nTest acceptance of the transaction (signed hex)\n"
+ + HelpExampleCli("testmempoolaccept", "\"signedhex\"") +
+ "\nAs a json rpc call\n"
+ + HelpExampleRpc("testmempoolaccept", "[\"signedhex\"]")
+ // clang-format on
+ );
+ }
+
+ ObserveSafeMode();
+
+ RPCTypeCheck(request.params, {UniValue::VARR, UniValue::VBOOL});
+ if (request.params[0].get_array().size() != 1) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Array must contain exactly one raw transaction for now");
+ }
+
+ CMutableTransaction mtx;
+ if (!DecodeHexTx(mtx, request.params[0].get_array()[0].get_str())) {
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
+ }
+ CTransactionRef tx(MakeTransactionRef(std::move(mtx)));
+ const uint256& tx_hash = tx->GetHash();
+
+ CAmount max_raw_tx_fee = ::maxTxFee;
+ if (!request.params[1].isNull() && request.params[1].get_bool()) {
+ max_raw_tx_fee = 0;
+ }
+
+ UniValue result(UniValue::VARR);
+ UniValue result_0(UniValue::VOBJ);
+ result_0.pushKV("txid", tx_hash.GetHex());
+
+ CValidationState state;
+ bool missing_inputs;
+ bool test_accept_res;
+ {
+ LOCK(cs_main);
+ test_accept_res = AcceptToMemoryPool(mempool, state, std::move(tx), &missing_inputs,
+ nullptr /* plTxnReplaced */, false /* bypass_limits */, max_raw_tx_fee, /* test_accpet */ true);
+ }
+ result_0.pushKV("allowed", test_accept_res);
+ if (!test_accept_res) {
+ if (state.IsInvalid()) {
+ result_0.pushKV("reject-reason", strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
+ } else if (missing_inputs) {
+ result_0.pushKV("reject-reason", "missing-inputs");
+ } else {
+ result_0.pushKV("reject-reason", state.GetRejectReason());
+ }
+ }
+
+ result.push_back(std::move(result_0));
+ return result;
+}
+
static const CRPCCommand commands[] =
{ // category name actor (function) argNames
// --------------------- ------------------------ ----------------------- ----------
@@ -1145,6 +1226,7 @@ static const CRPCCommand commands[] =
{ "rawtransactions", "combinerawtransaction", &combinerawtransaction, {"txs"} },
{ "rawtransactions", "signrawtransaction", &signrawtransaction, {"hexstring","prevtxs","privkeys","sighashtype"} }, /* uses wallet if enabled */
{ "rawtransactions", "signrawtransactionwithkey", &signrawtransactionwithkey, {"hexstring","privkeys","prevtxs","sighashtype"} },
+ { "rawtransactions", "testmempoolaccept", &testmempoolaccept, {"rawtxs","allowhighfees"} },
{ "blockchain", "gettxoutproof", &gettxoutproof, {"txids", "blockhash"} },
{ "blockchain", "verifytxoutproof", &verifytxoutproof, {"proof"} },