aboutsummaryrefslogtreecommitdiff
path: root/src/rpc
diff options
context:
space:
mode:
authorMarcoFalke <falke.marco@gmail.com>2017-11-17 12:54:39 -0500
committerMarcoFalke <falke.marco@gmail.com>2018-03-24 11:17:08 -0400
commitb55555da3e25a47f1e7fced7f09d4f0bf8198624 (patch)
tree551e618067f55d5de6d4b05623202020ce1f626b /src/rpc
parentb43aba89e356ff95b706e80d4802f60fc46a569a (diff)
rpc: Add testmempoolaccept
Diffstat (limited to 'src/rpc')
-rw-r--r--src/rpc/client.cpp2
-rw-r--r--src/rpc/rawtransaction.cpp82
2 files changed, 84 insertions, 0 deletions
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index e12685da65..01f932dbb4 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -103,6 +103,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "signrawtransactionwithkey", 2, "prevtxs" },
{ "signrawtransactionwithwallet", 1, "prevtxs" },
{ "sendrawtransaction", 1, "allowhighfees" },
+ { "testmempoolaccept", 0, "rawtxs" },
+ { "testmempoolaccept", 1, "allowhighfees" },
{ "combinerawtransaction", 0, "txs" },
{ "fundrawtransaction", 1, "options" },
{ "fundrawtransaction", 2, "iswitness" },
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 20bfd3f355..3247c61242 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"} },