Skip to content

Commit

Permalink
[Refactoring][RPC] Decouple atmp/relay functions in sendrawtransaction
Browse files Browse the repository at this point in the history
  • Loading branch information
random-zebra committed May 4, 2021
1 parent 86dcf69 commit 4c50f7a
Showing 1 changed file with 56 additions and 48 deletions.
104 changes: 56 additions & 48 deletions src/rpc/rawtransaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -858,55 +858,23 @@ UniValue signrawtransaction(const JSONRPCRequest& request)
return result;
}

UniValue sendrawtransaction(const JSONRPCRequest& request)
void TryATMP(const CMutableTransaction& mtx, bool fOverrideFees)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
"sendrawtransaction \"hexstring\" ( allowhighfees )\n"
"\nSubmits raw transaction (serialized, hex-encoded) to local node and network.\n"
"\nAlso see createrawtransaction and signrawtransaction calls.\n"

"\nArguments:\n"
"1. \"hexstring\" (string, required) The hex string of the raw transaction)\n"
"2. allowhighfees (boolean, optional, default=false) Allow high fees\n"

"\nResult:\n"
"\"hex\" (string) The transaction hash in hex\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\"") +
"\nSend the transaction (signed hex)\n" + HelpExampleCli("sendrawtransaction", "\"signedhex\"") +
"\nAs a json rpc call\n" + HelpExampleRpc("sendrawtransaction", "\"signedhex\""));

std::promise<void> promise;

RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL});

// parse hex string from parameter
CMutableTransaction mtx;
if (!DecodeHexTx(mtx, request.params[0].get_str()))
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
const uint256& hashTx = mtx.GetHash();

bool fOverrideFees = false;
if (request.params.size() > 1)
fOverrideFees = request.params[1].get_bool();
std::promise<void> promise;

{ // cs_main scope
LOCK(cs_main);
CCoinsViewCache& view = *pcoinsTip;
bool fHaveChain = false;
for (size_t o = 0; !fHaveChain && o < mtx.vout.size(); o++) {
const Coin& existingCoin = view.AccessCoin(COutPoint(hashTx, o));
fHaveChain = !existingCoin.IsSpent();
}
bool fHaveMempool = mempool.exists(hashTx);
if (!fHaveMempool && !fHaveChain) {
CValidationState state;
bool fMissingInputs;
{
LOCK(cs_main);
CCoinsViewCache& view = *pcoinsTip;
bool fHaveChain = false;
for (size_t o = 0; !fHaveChain && o < mtx.vout.size(); o++) {
const Coin& existingCoin = view.AccessCoin(COutPoint(hashTx, o));
fHaveChain = !existingCoin.IsSpent();
}
bool fHaveMempool = mempool.exists(hashTx);
if (!fHaveMempool && !fHaveChain) {
CValidationState state;
bool fMissingInputs;
if (!AcceptToMemoryPool(mempool, state, MakeTransactionRef(std::move(mtx)), true, &fMissingInputs, false, !fOverrideFees)) {
if (state.IsInvalid()) {
throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%s: %s", state.GetRejectReason(), state.GetDebugMessage()));
Expand All @@ -926,15 +894,17 @@ UniValue sendrawtransaction(const JSONRPCRequest& request)
promise.set_value();
});
}
} else if (fHaveChain) {
throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain");
}
} else if (fHaveChain) {
throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain");
}

} // cs_main

promise.get_future().wait();
}

void RelayTx(const uint256& hashTx)
{
if(!g_connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");

Expand All @@ -943,6 +913,44 @@ UniValue sendrawtransaction(const JSONRPCRequest& request)
{
pnode->PushInventory(inv);
});
}

UniValue sendrawtransaction(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
"sendrawtransaction \"hexstring\" ( allowhighfees )\n"
"\nSubmits raw transaction (serialized, hex-encoded) to local node and network.\n"
"\nAlso see createrawtransaction and signrawtransaction calls.\n"

"\nArguments:\n"
"1. \"hexstring\" (string, required) The hex string of the raw transaction)\n"
"2. allowhighfees (boolean, optional, default=false) Allow high fees\n"

"\nResult:\n"
"\"hex\" (string) The transaction hash in hex\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\"") +
"\nSend the transaction (signed hex)\n" + HelpExampleCli("sendrawtransaction", "\"signedhex\"") +
"\nAs a json rpc call\n" + HelpExampleRpc("sendrawtransaction", "\"signedhex\""));

RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL});

// parse hex string from parameter
CMutableTransaction mtx;
if (!DecodeHexTx(mtx, request.params[0].get_str()))
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
const uint256& hashTx = mtx.GetHash();

bool fOverrideFees = false;
if (request.params.size() > 1)
fOverrideFees = request.params[1].get_bool();

TryATMP(mtx, fOverrideFees);
RelayTx(hashTx);

return hashTx.GetHex();
}
Expand Down

0 comments on commit 4c50f7a

Please sign in to comment.