rpc: Add testmempoolaccept

This commit is contained in:
MarcoFalke
2017-11-17 12:54:39 -05:00
parent b43aba89e3
commit b55555da3e
10 changed files with 399 additions and 14 deletions

View File

@@ -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"} },