Changeset View
Changeset View
Standalone View
Standalone View
src/rpc/rawtransaction.cpp
Show First 20 Lines • Show All 1,337 Lines • ▼ Show 20 Lines | if (!g_connman) { | ||||
"Error: Peer-to-peer functionality missing or disabled"); | "Error: Peer-to-peer functionality missing or disabled"); | ||||
} | } | ||||
CInv inv(MSG_TX, txid); | CInv inv(MSG_TX, txid); | ||||
g_connman->ForEachNode([&inv](CNode *pnode) { pnode->PushInventory(inv); }); | g_connman->ForEachNode([&inv](CNode *pnode) { pnode->PushInventory(inv); }); | ||||
return txid.GetHex(); | return txid.GetHex(); | ||||
} | } | ||||
UniValue testmempoolaccept(const Config &config, | |||||
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 | |||||
); | |||||
} | |||||
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 &txid = tx->GetId(); | |||||
bool fLimitFree = false; | |||||
Amount max_raw_tx_fee = maxTxFee; | |||||
if (!request.params[1].isNull() && request.params[1].get_bool()) { | |||||
max_raw_tx_fee = Amount::zero(); | |||||
} | |||||
UniValue result(UniValue::VARR); | |||||
UniValue result_0(UniValue::VOBJ); | |||||
result_0.pushKV("txid", txid.GetHex()); | |||||
CValidationState state; | |||||
bool missing_inputs; | |||||
bool test_accept_res; | |||||
{ | |||||
LOCK(cs_main); | |||||
test_accept_res = AcceptToMemoryPool( | |||||
config, g_mempool, state, std::move(tx), fLimitFree, | |||||
&missing_inputs, /* bypass_limits */ false, max_raw_tx_fee, | |||||
/* test_accept */ 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; | |||||
} | |||||
// clang-format off | // clang-format off | ||||
static const ContextFreeRPCCommand commands[] = { | static const ContextFreeRPCCommand commands[] = { | ||||
// category name actor (function) argNames | // category name actor (function) argNames | ||||
// ------------------- ------------------------ ---------------------- ---------- | // ------------------- ------------------------ ---------------------- ---------- | ||||
{ "rawtransactions", "getrawtransaction", getrawtransaction, {"txid","verbose","blockhash"} }, | { "rawtransactions", "getrawtransaction", getrawtransaction, {"txid","verbose","blockhash"} }, | ||||
{ "rawtransactions", "createrawtransaction", createrawtransaction, {"inputs","outputs","locktime"} }, | { "rawtransactions", "createrawtransaction", createrawtransaction, {"inputs","outputs","locktime"} }, | ||||
{ "rawtransactions", "decoderawtransaction", decoderawtransaction, {"hexstring"} }, | { "rawtransactions", "decoderawtransaction", decoderawtransaction, {"hexstring"} }, | ||||
{ "rawtransactions", "decodescript", decodescript, {"hexstring"} }, | { "rawtransactions", "decodescript", decodescript, {"hexstring"} }, | ||||
{ "rawtransactions", "sendrawtransaction", sendrawtransaction, {"hexstring","allowhighfees"} }, | { "rawtransactions", "sendrawtransaction", sendrawtransaction, {"hexstring","allowhighfees"} }, | ||||
{ "rawtransactions", "combinerawtransaction", combinerawtransaction, {"txs"} }, | { "rawtransactions", "combinerawtransaction", combinerawtransaction, {"txs"} }, | ||||
{ "rawtransactions", "signrawtransaction", signrawtransaction, {"hexstring","prevtxs","privkeys","sighashtype"} }, /* uses wallet if enabled */ | { "rawtransactions", "signrawtransaction", signrawtransaction, {"hexstring","prevtxs","privkeys","sighashtype"} }, /* uses wallet if enabled */ | ||||
{ "rawtransactions", "signrawtransactionwithkey", signrawtransactionwithkey, {"hexstring","privkeys","prevtxs","sighashtype"} }, | { "rawtransactions", "signrawtransactionwithkey", signrawtransactionwithkey, {"hexstring","privkeys","prevtxs","sighashtype"} }, | ||||
{ "rawtransactions", "testmempoolaccept", testmempoolaccept, {"rawtxs","allowhighfees"} }, | |||||
{ "blockchain", "gettxoutproof", gettxoutproof, {"txids", "blockhash"} }, | { "blockchain", "gettxoutproof", gettxoutproof, {"txids", "blockhash"} }, | ||||
{ "blockchain", "verifytxoutproof", verifytxoutproof, {"proof"} }, | { "blockchain", "verifytxoutproof", verifytxoutproof, {"proof"} }, | ||||
}; | }; | ||||
// clang-format on | // clang-format on | ||||
void RegisterRawTransactionRPCCommands(CRPCTable &t) { | void RegisterRawTransactionRPCCommands(CRPCTable &t) { | ||||
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) { | for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) { | ||||
t.appendCommand(commands[vcidx].name, &commands[vcidx]); | t.appendCommand(commands[vcidx].name, &commands[vcidx]); | ||||
} | } | ||||
} | } |