Changeset View
Changeset View
Standalone View
Standalone View
src/rpc/rawtransaction.cpp
Show All 27 Lines | |||||
#include <script/script.h> | #include <script/script.h> | ||||
#include <script/script_error.h> | #include <script/script_error.h> | ||||
#include <script/sign.h> | #include <script/sign.h> | ||||
#include <script/standard.h> | #include <script/standard.h> | ||||
#include <txmempool.h> | #include <txmempool.h> | ||||
#include <uint256.h> | #include <uint256.h> | ||||
#include <util/bip32.h> | #include <util/bip32.h> | ||||
#include <util/error.h> | #include <util/error.h> | ||||
#include <util/moneystr.h> | |||||
#include <util/strencodings.h> | #include <util/strencodings.h> | ||||
#include <validation.h> | #include <validation.h> | ||||
#include <validationinterface.h> | #include <validationinterface.h> | ||||
#include <cstdint> | #include <cstdint> | ||||
#include <univalue.h> | #include <univalue.h> | ||||
▲ Show 20 Lines • Show All 858 Lines • ▼ Show 20 Lines | if (request.fHelp || request.params.size() < 1 || | ||||
"sendrawtransaction", | "sendrawtransaction", | ||||
"\nSubmits raw transaction (serialized, hex-encoded) to local node " | "\nSubmits raw transaction (serialized, hex-encoded) to local node " | ||||
"and network.\n" | "and network.\n" | ||||
"\nAlso see createrawtransaction and " | "\nAlso see createrawtransaction and " | ||||
"signrawtransactionwithkey calls.\n", | "signrawtransactionwithkey calls.\n", | ||||
{ | { | ||||
{"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | ||||
"The hex string of the raw transaction"}, | "The hex string of the raw transaction"}, | ||||
{"allowhighfees", RPCArg::Type::BOOL, /* default */ "false", | {"maxfeerate", RPCArg::Type::AMOUNT, | ||||
"Allow high fees"}, | /* default */ FormatMoney(maxTxFee), | ||||
"Reject transactions whose fee rate is higher than the " | |||||
"specified value, expressed in " + | |||||
CURRENCY_UNIT + "/kB\n"}, | |||||
}, | }, | ||||
RPCResult{ | RPCResult{ | ||||
"\"hex\" (string) The transaction hash in hex\n"}, | "\"hex\" (string) The transaction hash in hex\n"}, | ||||
RPCExamples{ | RPCExamples{ | ||||
"\nCreate a transaction\n" + | "\nCreate a transaction\n" + | ||||
HelpExampleCli( | HelpExampleCli( | ||||
"createrawtransaction", | "createrawtransaction", | ||||
"\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" " | "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" " | ||||
"\"{\\\"myaddress\\\":0.01}\"") + | "\"{\\\"myaddress\\\":0.01}\"") + | ||||
"Sign the transaction, and get back the hex\n" + | "Sign the transaction, and get back the hex\n" + | ||||
HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") + | HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") + | ||||
"\nSend the transaction (signed hex)\n" + | "\nSend the transaction (signed hex)\n" + | ||||
HelpExampleCli("sendrawtransaction", "\"signedhex\"") + | HelpExampleCli("sendrawtransaction", "\"signedhex\"") + | ||||
"\nAs a JSON-RPC call\n" + | "\nAs a JSON-RPC call\n" + | ||||
HelpExampleRpc("sendrawtransaction", "\"signedhex\"")}, | HelpExampleRpc("sendrawtransaction", "\"signedhex\"")}, | ||||
} | } | ||||
.ToString()); | .ToString()); | ||||
} | } | ||||
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL}); | RPCTypeCheck(request.params, { | ||||
UniValue::VSTR, | |||||
// NUM or BOOL, checked later | |||||
UniValueType(), | |||||
}); | |||||
// parse hex string from parameter | // parse hex string from parameter | ||||
CMutableTransaction mtx; | CMutableTransaction mtx; | ||||
if (!DecodeHexTx(mtx, request.params[0].get_str())) { | if (!DecodeHexTx(mtx, request.params[0].get_str())) { | ||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); | throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); | ||||
} | } | ||||
CTransactionRef tx(MakeTransactionRef(std::move(mtx))); | CTransactionRef tx(MakeTransactionRef(std::move(mtx))); | ||||
bool allowhighfees = false; | Amount max_raw_tx_fee = maxTxFee; | ||||
if (!request.params[1].isNull()) { | // TODO: temporary migration code for old clients. Remove in v0.22 | ||||
allowhighfees = request.params[1].get_bool(); | if (request.params[1].isBool()) { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | |||||
"Second argument must be numeric (maxfeerate) and " | |||||
"no longer supports a boolean. To allow a " | |||||
"transaction with high fees, set maxfeerate to 0."); | |||||
} else if (request.params[1].isNum()) { | |||||
size_t sz = tx->GetTotalSize(); | |||||
CFeeRate fr(AmountFromValue(request.params[1])); | |||||
max_raw_tx_fee = fr.GetFee(sz); | |||||
} else if (!request.params[1].isNull()) { | |||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | |||||
"second argument (maxfeerate) must be numeric"); | |||||
} | } | ||||
const Amount highfee{allowhighfees ? Amount::zero() : ::maxTxFee}; | |||||
TxId txid; | TxId txid; | ||||
std::string err_string; | std::string err_string; | ||||
const TransactionError err = | const TransactionError err = | ||||
BroadcastTransaction(config, tx, txid, err_string, highfee); | BroadcastTransaction(config, tx, txid, err_string, max_raw_tx_fee); | ||||
if (err != TransactionError::OK) { | if (err != TransactionError::OK) { | ||||
throw JSONRPCTransactionError(err, err_string); | throw JSONRPCTransactionError(err, err_string); | ||||
} | } | ||||
return txid.GetHex(); | return txid.GetHex(); | ||||
} | } | ||||
static UniValue testmempoolaccept(const Config &config, | static UniValue testmempoolaccept(const Config &config, | ||||
Show All 15 Lines | if (request.fHelp || request.params.size() < 1 || | ||||
"An array of hex strings of raw transactions.\n" | "An array of hex strings of raw transactions.\n" | ||||
" Length must be " | " Length must be " | ||||
"one for now.", | "one for now.", | ||||
{ | { | ||||
{"rawtx", RPCArg::Type::STR_HEX, | {"rawtx", RPCArg::Type::STR_HEX, | ||||
RPCArg::Optional::OMITTED, ""}, | RPCArg::Optional::OMITTED, ""}, | ||||
}, | }, | ||||
}, | }, | ||||
{"allowhighfees", RPCArg::Type::BOOL, /* default */ "false", | {"maxfeerate", RPCArg::Type::AMOUNT, | ||||
"Allow high fees"}, | /* default */ FormatMoney(maxTxFee), | ||||
"Reject transactions whose fee rate is higher than the " | |||||
"specified value, expressed in " + | |||||
CURRENCY_UNIT + "/kB\n"}, | |||||
}, | }, | ||||
RPCResult{ | RPCResult{ | ||||
"[ (array) The result of the mempool " | "[ (array) The result of the mempool " | ||||
"acceptance test for each raw transaction in the input array.\n" | "acceptance test for each raw transaction in the input array.\n" | ||||
" Length is exactly one for now.\n" | " Length is exactly one for now.\n" | ||||
" {\n" | " {\n" | ||||
" \"txid\" (string) The transaction hash in hex\n" | " \"txid\" (string) The transaction hash in hex\n" | ||||
" \"allowed\" (boolean) If the mempool allows this tx " | " \"allowed\" (boolean) If the mempool allows this tx " | ||||
Show All 13 Lines | if (request.fHelp || request.params.size() < 1 || | ||||
"\nTest acceptance of the transaction (signed hex)\n" + | "\nTest acceptance of the transaction (signed hex)\n" + | ||||
HelpExampleCli("testmempoolaccept", "[\"signedhex\"]") + | HelpExampleCli("testmempoolaccept", "[\"signedhex\"]") + | ||||
"\nAs a JSON-RPC call\n" + | "\nAs a JSON-RPC call\n" + | ||||
HelpExampleRpc("testmempoolaccept", "[\"signedhex\"]")}, | HelpExampleRpc("testmempoolaccept", "[\"signedhex\"]")}, | ||||
} | } | ||||
.ToString()); | .ToString()); | ||||
} | } | ||||
RPCTypeCheck(request.params, {UniValue::VARR, UniValue::VBOOL}); | RPCTypeCheck(request.params, { | ||||
UniValue::VARR, | |||||
// NUM or BOOL, checked later | |||||
UniValueType(), | |||||
}); | |||||
if (request.params[0].get_array().size() != 1) { | if (request.params[0].get_array().size() != 1) { | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_INVALID_PARAMETER, | RPC_INVALID_PARAMETER, | ||||
"Array must contain exactly one raw transaction for now"); | "Array must contain exactly one raw transaction for now"); | ||||
} | } | ||||
CMutableTransaction mtx; | CMutableTransaction mtx; | ||||
if (!DecodeHexTx(mtx, request.params[0].get_array()[0].get_str())) { | if (!DecodeHexTx(mtx, request.params[0].get_array()[0].get_str())) { | ||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); | throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); | ||||
} | } | ||||
CTransactionRef tx(MakeTransactionRef(std::move(mtx))); | CTransactionRef tx(MakeTransactionRef(std::move(mtx))); | ||||
const uint256 &txid = tx->GetId(); | const TxId &txid = tx->GetId(); | ||||
Amount max_raw_tx_fee = maxTxFee; | Amount max_raw_tx_fee = maxTxFee; | ||||
if (!request.params[1].isNull() && request.params[1].get_bool()) { | // TODO: temporary migration code for old clients. Remove in v0.20 | ||||
max_raw_tx_fee = Amount::zero(); | if (request.params[1].isBool()) { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | |||||
"Second argument must be numeric (maxfeerate) and " | |||||
"no longer supports a boolean. To allow a " | |||||
"transaction with high fees, set maxfeerate to 0."); | |||||
} else if (request.params[1].isNum()) { | |||||
size_t sz = tx->GetTotalSize(); | |||||
CFeeRate fr(AmountFromValue(request.params[1])); | |||||
max_raw_tx_fee = fr.GetFee(sz); | |||||
} else if (!request.params[1].isNull()) { | |||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | |||||
"second argument (maxfeerate) must be numeric"); | |||||
} | } | ||||
UniValue result(UniValue::VARR); | UniValue result(UniValue::VARR); | ||||
UniValue result_0(UniValue::VOBJ); | UniValue result_0(UniValue::VOBJ); | ||||
result_0.pushKV("txid", txid.GetHex()); | result_0.pushKV("txid", txid.GetHex()); | ||||
CValidationState state; | CValidationState state; | ||||
bool missing_inputs; | bool missing_inputs; | ||||
▲ Show 20 Lines • Show All 884 Lines • ▼ Show 20 Lines | |||||
// clang-format off | // clang-format off | ||||
static const CRPCCommand commands[] = { | static const CRPCCommand 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|maxfeerate"} }, | ||||
{ "rawtransactions", "combinerawtransaction", combinerawtransaction, {"txs"} }, | { "rawtransactions", "combinerawtransaction", combinerawtransaction, {"txs"} }, | ||||
{ "rawtransactions", "signrawtransactionwithkey", signrawtransactionwithkey, {"hexstring","privkeys","prevtxs","sighashtype"} }, | { "rawtransactions", "signrawtransactionwithkey", signrawtransactionwithkey, {"hexstring","privkeys","prevtxs","sighashtype"} }, | ||||
{ "rawtransactions", "testmempoolaccept", testmempoolaccept, {"rawtxs","allowhighfees"} }, | { "rawtransactions", "testmempoolaccept", testmempoolaccept, {"rawtxs","allowhighfees|maxfeerate"} }, | ||||
{ "rawtransactions", "decodepsbt", decodepsbt, {"psbt"} }, | { "rawtransactions", "decodepsbt", decodepsbt, {"psbt"} }, | ||||
{ "rawtransactions", "combinepsbt", combinepsbt, {"txs"} }, | { "rawtransactions", "combinepsbt", combinepsbt, {"txs"} }, | ||||
{ "rawtransactions", "finalizepsbt", finalizepsbt, {"psbt", "extract"} }, | { "rawtransactions", "finalizepsbt", finalizepsbt, {"psbt", "extract"} }, | ||||
{ "rawtransactions", "createpsbt", createpsbt, {"inputs","outputs","locktime"} }, | { "rawtransactions", "createpsbt", createpsbt, {"inputs","outputs","locktime"} }, | ||||
{ "rawtransactions", "converttopsbt", converttopsbt, {"hexstring","permitsigdata"} }, | { "rawtransactions", "converttopsbt", converttopsbt, {"hexstring","permitsigdata"} }, | ||||
{ "rawtransactions", "utxoupdatepsbt", utxoupdatepsbt, {"psbt"} }, | { "rawtransactions", "utxoupdatepsbt", utxoupdatepsbt, {"psbt"} }, | ||||
{ "rawtransactions", "joinpsbts", joinpsbts, {"txs"} }, | { "rawtransactions", "joinpsbts", joinpsbts, {"txs"} }, | ||||
{ "rawtransactions", "analyzepsbt", analyzepsbt, {"psbt"} }, | { "rawtransactions", "analyzepsbt", analyzepsbt, {"psbt"} }, | ||||
Show All 10 Lines |