Files
rippled/src/test/rpc/JSONRPC_test.cpp
Mayukha Vadari 07ff532d30 refactor: Fix spelling issues in all variables/functions (#6184)
This change fixes many typos in comments, variables, and public functions. There is no functionality change.
2026-01-07 21:30:35 +00:00

2924 lines
93 KiB
C++

#include <test/jtx.h>
#include <test/jtx/envconfig.h>
#include <xrpld/app/misc/LoadFeeTrack.h>
#include <xrpld/app/misc/TxQ.h>
#include <xrpld/core/ConfigSections.h>
#include <xrpld/rpc/detail/TransactionSign.h>
#include <xrpl/basics/contract.h>
#include <xrpl/beast/unit_test.h>
#include <xrpl/json/json_reader.h>
#include <xrpl/protocol/ErrorCodes.h>
namespace xrpl {
namespace RPC {
struct TxnTestData
{
char const* const description;
int const line;
char const* const json;
// The JSON is applied to four different interfaces:
// 1. sign,
// 2. submit,
// 3. sign_for, and
// 4. submit_multisigned.
// The JSON is not valid for all of these interfaces, but it should
// crash none of them, and should provide reliable error messages.
//
// The expMsg array contains the expected error string for the above cases.
std::array<char const* const, 4> const expMsg;
constexpr TxnTestData(
char const* description_,
int line_,
char const* json_,
std::array<char const* const, 4> const& expMsg_)
: description(description_), line(line_), json(json_), expMsg{expMsg_}
{
}
TxnTestData() = delete;
TxnTestData(TxnTestData const&) = delete;
TxnTestData(TxnTestData&&) = delete;
TxnTestData&
operator=(TxnTestData const&) = delete;
TxnTestData&
operator=(TxnTestData&&) = delete;
};
static constexpr TxnTestData txnTestArray[] = {
{"Minimal payment, no Amount only DeliverMax",
__LINE__,
R"({
"command": "dummy_command",
"secret": "masterpassphrase",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"DeliverMax": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"",
"",
"Missing field 'account'.",
"Missing field 'tx_json.Sequence'."}}},
{"Pass in Fee with minimal payment, both Amount and DeliverMax.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Fee": 10,
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"DeliverMax": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"",
"",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"Pass in Sequence, no Amount only DeliverMax",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Sequence": 0,
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"DeliverMax": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"",
"",
"Missing field 'tx_json.Fee'.",
"Missing field 'tx_json.SigningPubKey'."}}},
{"Pass in Sequence and Fee with minimal payment, both Amount and "
"DeliverMax.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Sequence": 0,
"Fee": 10,
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"DeliverMax": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"",
"",
"A Signer may not be the transaction's Account "
"(rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh).",
"Missing field 'tx_json.SigningPubKey'."}}},
{"Add 'fee_mult_max' field.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"fee_mult_max": 7,
"tx_json": {
"Sequence": 0,
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"",
"",
"Missing field 'tx_json.Fee'.",
"Missing field 'tx_json.SigningPubKey'."}}},
{"Add 'fee_mult_max' and 'fee_div_max' field.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"fee_mult_max": 7,
"fee_div_max": 4,
"tx_json": {
"Sequence": 0,
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"",
"",
"Missing field 'tx_json.Fee'.",
"Missing field 'tx_json.SigningPubKey'."}}},
{"fee_mult_max is ignored if 'Fee' is present.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"fee_mult_max": 0,
"tx_json": {
"Sequence": 0,
"Fee": 10,
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"",
"",
"A Signer may not be the transaction's Account "
"(rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh).",
"Missing field 'tx_json.SigningPubKey'."}}},
{"fee_div_max is ignored if 'Fee' is present.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"fee_mult_max": 100,
"fee_div_max": 1000,
"tx_json": {
"Sequence": 0,
"Fee": 10,
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"",
"",
"A Signer may not be the transaction's Account "
"(rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh).",
"Missing field 'tx_json.SigningPubKey'."}}},
{"Invalid 'fee_mult_max' field.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"fee_mult_max": "NotAFeeMultiplier",
"tx_json": {
"Sequence": 0,
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"Invalid field 'fee_mult_max', not a positive integer.",
"Invalid field 'fee_mult_max', not a positive integer.",
"Missing field 'tx_json.Fee'.",
"Missing field 'tx_json.SigningPubKey'."}}},
{"Invalid 'fee_div_max' field.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"fee_mult_max": 5,
"fee_div_max": "NotAFeeMultiplier",
"tx_json": {
"Sequence": 0,
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"Invalid field 'fee_div_max', not a positive integer.",
"Invalid field 'fee_div_max', not a positive integer.",
"Missing field 'tx_json.Fee'.",
"Missing field 'tx_json.SigningPubKey'."}}},
{"Invalid value for 'fee_mult_max' field.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"fee_mult_max": 0,
"tx_json": {
"Sequence": 0,
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"Fee of 10 exceeds the requested tx limit of 0",
"Fee of 10 exceeds the requested tx limit of 0",
"Missing field 'tx_json.Fee'.",
"Missing field 'tx_json.SigningPubKey'."}}},
{"Invalid value for 'fee_div_max' field.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"fee_mult_max": 4,
"fee_div_max": 7,
"tx_json": {
"Sequence": 0,
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"Fee of 10 exceeds the requested tx limit of 5",
"Fee of 10 exceeds the requested tx limit of 5",
"Missing field 'tx_json.Fee'.",
"Missing field 'tx_json.SigningPubKey'."}}},
{"Invalid zero value for 'fee_div_max' field.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"fee_mult_max": 4,
"fee_div_max": 0,
"tx_json": {
"Sequence": 0,
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"Invalid field 'fee_div_max', not a positive integer.",
"Invalid field 'fee_div_max', not a positive integer.",
"Missing field 'tx_json.Fee'.",
"Missing field 'tx_json.SigningPubKey'."}}},
{"Missing 'Amount'.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"Missing field 'tx_json.Amount'.",
"Missing field 'tx_json.Amount'.",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"Invalid 'Amount'.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "NotAnAmount",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"Invalid field 'tx_json.Amount'.",
"Invalid field 'tx_json.Amount'.",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"Missing 'Destination'.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"TransactionType": "Payment"
}
})",
{{"Missing field 'tx_json.Destination'.",
"Missing field 'tx_json.Destination'.",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"Invalid 'Destination'.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "NotADestination",
"TransactionType": "Payment"
}
})",
{{"Invalid field 'tx_json.Destination'.",
"Invalid field 'tx_json.Destination'.",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"Cannot create XRP to XRP paths.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"build_path": 1,
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"Cannot build XRP to XRP paths.",
"Cannot build XRP to XRP paths.",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"Successful 'build_path'.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"build_path": 1,
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": {
"value": "10",
"currency": "USD",
"issuer": "rLPwWB1itaUGMV8kbMLLysjGkEpTM2Soy4"
},
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"",
"",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"Not valid to include both 'Paths' and 'build_path'.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"build_path": 1,
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": {
"value": "10",
"currency": "USD",
"issuer": "rLPwWB1itaUGMV8kbMLLysjGkEpTM2Soy4"
},
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Paths": "",
"TransactionType": "Payment"
}
})",
{{"Cannot specify both 'tx_json.Paths' and 'build_path'",
"Cannot specify both 'tx_json.Paths' and 'build_path'",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"Successful 'SendMax'.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"build_path": 1,
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": {
"value": "10",
"currency": "USD",
"issuer": "rLPwWB1itaUGMV8kbMLLysjGkEpTM2Soy4"
},
"SendMax": {
"value": "5",
"currency": "USD",
"issuer": "rLPwWB1itaUGMV8kbMLLysjGkEpTM2Soy4"
},
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"",
"",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"'Amount' may not be XRP for pathfinding, but 'SendMax' may be XRP.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"build_path": 1,
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": {
"value": "10",
"currency": "USD",
"issuer": "rLPwWB1itaUGMV8kbMLLysjGkEpTM2Soy4"
},
"SendMax": 10000,
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"",
"",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"'secret' must be present.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"'secret' must be non-empty.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"Invalid field 'secret'.",
"Invalid field 'secret'.",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"Use 'seed' instead of 'secret'.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi",
"key_type": "ed25519",
"seed": "sh1yJfwoi98zCygwijUzuHmJDeVKd",
"tx_json": {
"Account": "rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"",
"",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"Malformed 'seed'.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi",
"key_type": "ed25519",
"seed": "not a seed",
"tx_json": {
"Account": "rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"Disallowed seed.",
"Disallowed seed.",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"'tx_json' must be present.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"rx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"Missing field 'tx_json'.",
"Missing field 'tx_json'.",
"Missing field 'tx_json'.",
"Missing field 'tx_json'."}}},
{"'TransactionType' must be present.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
}
})",
{{"Missing field 'tx_json.TransactionType'.",
"Missing field 'tx_json.TransactionType'.",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"The 'TransactionType' must be a pre-established transaction type.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "tt"
}
})",
{{"Field 'tx_json.TransactionType' has invalid data.",
"Field 'tx_json.TransactionType' has invalid data.",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"The 'TransactionType' may be represented with an integer.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": 0
}
})",
{{"",
"",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"'Account' must be present.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"Missing field 'tx_json.Account'.",
"Missing field 'tx_json.Account'.",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"'Account' must be well formed.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Account": "NotAnAccount",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"Invalid field 'tx_json.Account'.",
"Invalid field 'tx_json.Account'.",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"The 'offline' tag may be added to the transaction.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"offline": 0,
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"",
"",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"If 'offline' is true then a 'Sequence' field must be supplied.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"offline": 1,
"tx_json": {
"Fee": 10,
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"If 'offline' is true then a 'Fee' field must be supplied.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"offline": 1,
"tx_json": {
"Sequence": 0,
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"Missing field 'tx_json.Fee'.",
"Missing field 'tx_json.Fee'.",
"Missing field 'tx_json.Fee'.",
"Missing field 'tx_json.SigningPubKey'."}}},
{"Valid transaction if 'offline' is true.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"offline": 1,
"tx_json": {
"Sequence": 0,
"Fee": 10,
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"",
"",
"A Signer may not be the transaction's Account "
"(rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh).",
"Missing field 'tx_json.SigningPubKey'."}}},
{"'offline' and 'build_path' are mutually exclusive.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"offline": 1,
"build_path": 1,
"tx_json": {
"Sequence": 0,
"Fee": 10,
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"Field 'build_path' not allowed in this context.",
"Field 'build_path' not allowed in this context.",
"Field 'build_path' not allowed in this context.",
"Missing field 'tx_json.SigningPubKey'."}}},
{"A 'Flags' field may be specified.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Flags": 0,
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"",
"",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"The 'Flags' field must be numeric.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Flags": "NotGoodFlags",
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"Field 'tx_json.Flags' has invalid data.",
"Field 'tx_json.Flags' has invalid data.",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"It's okay to add a 'debug_signing' field.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"debug_signing": 0,
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"",
"",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"Single-sign a multisigned transaction.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"secret": "a",
"tx_json": {
"Account" : "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Amount" : "1000000000",
"Destination" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Fee" : "50",
"Sequence" : 0,
"Signers" : [
{
"Signer" : {
"Account" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"SigningPubKey" : "0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
"TxnSignature" : "304502210080EB23E78A841DDC5E3A4F10DE6EAF052207D6B519BF8954467ADB221B3F349002202CA458E8D4E4DE7176D27A91628545E7B295A5DFC8ADF0B5CD3E279B6FA02998"
}
}
],
"SigningPubKey" : "",
"TransactionType" : "Payment"
}
})",
{{"Already multisigned.",
"Already multisigned.",
"Secret does not match account.",
""}}},
{"Minimal sign_for.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Account": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Amount": "1000000000",
"Destination": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Fee": 50,
"Sequence": 0,
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Secret does not match account.",
"Secret does not match account.",
"",
"Missing field 'tx_json.Signers'."}}},
{"Minimal offline sign_for.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"offline": 1,
"tx_json": {
"Account": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Amount": "1000000000",
"Destination": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Fee": 50,
"Sequence": 0,
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"", "", "", "Missing field 'tx_json.Signers'."}}},
{"Offline sign_for using 'seed' instead of 'secret'.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi",
"key_type": "ed25519",
"seed": "sh1yJfwoi98zCygwijUzuHmJDeVKd",
"offline": 1,
"tx_json": {
"Account": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Amount": "1000000000",
"Destination": "rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi",
"Fee": 50,
"Sequence": 0,
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"", "", "", "Missing field 'tx_json.Signers'."}}},
{"Malformed seed in sign_for.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi",
"key_type": "ed25519",
"seed": "sh1yJfwoi98zCygwjUzuHmJDeVKd",
"offline": 1,
"tx_json": {
"Account": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Amount": "1000000000",
"Destination": "rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi",
"Fee": 50,
"Sequence": 0,
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Disallowed seed.",
"Disallowed seed.",
"Disallowed seed.",
"Missing field 'tx_json.Signers'."}}},
{"Missing 'Account' in sign_for.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Amount": "1000000000",
"Destination": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Fee": 50,
"Sequence": 0,
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'tx_json.Account'.",
"Missing field 'tx_json.Account'.",
"Missing field 'tx_json.Account'.",
"Missing field 'tx_json.Account'."}}},
{"Missing 'Amount' in sign_for.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Account": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Destination": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Fee": 50,
"Sequence": 0,
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'tx_json.Amount'.",
"Missing field 'tx_json.Amount'.",
"Missing field 'tx_json.Amount'.",
"Missing field 'tx_json.Amount'."}}},
{"Missing 'Destination' in sign_for.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Account": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Amount": "1000000000",
"Fee": 50,
"Sequence": 0,
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'tx_json.Destination'.",
"Missing field 'tx_json.Destination'.",
"Missing field 'tx_json.Destination'.",
"Missing field 'tx_json.Destination'."}}},
{"Missing 'Destination' in sign_for, use DeliverMax",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Account": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"DeliverMax": "1000000000",
"Fee": 50,
"Sequence": 0,
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'tx_json.Destination'.",
"Missing field 'tx_json.Destination'.",
"Missing field 'tx_json.Destination'.",
"Missing field 'tx_json.Destination'."}}},
{"Missing 'Fee' in sign_for.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Account": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Amount": "1000000000",
"Destination": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Sequence": 0,
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Secret does not match account.",
"Secret does not match account.",
"Missing field 'tx_json.Fee'.",
"Missing field 'tx_json.Fee'."}}},
{"Missing 'Sequence' in sign_for.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Account": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Amount": "1000000000",
"Destination": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Fee": 50,
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Secret does not match account.",
"Secret does not match account.",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"Missing 'SigningPubKey' in sign_for is automatically filled in.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Account": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Amount": "1000000000",
"Destination": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Fee": 50,
"Sequence": 0,
"TransactionType": "Payment"
}
})",
{{"Secret does not match account.",
"Secret does not match account.",
"",
"Missing field 'tx_json.SigningPubKey'."}}},
{"In sign_for, an account may not sign for itself.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"secret": "a",
"tx_json": {
"Account": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Amount": "1000000000",
"Destination": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Fee": 50,
"Sequence": 0,
"TransactionType": "Payment"
}
})",
{{"",
"",
"A Signer may not be the transaction's Account "
"(rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA).",
"Missing field 'tx_json.SigningPubKey'."}}},
{"Cannot put duplicate accounts in Signers array",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Account" : "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Amount" : "1000000000",
"Destination" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Fee" : "50",
"Sequence" : 0,
"Signers" : [
{
"Signer" : {
"Account" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"SigningPubKey" : "0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
"TxnSignature" : "304502210080EB23E78A841DDC5E3A4F10DE6EAF052207D6B519BF8954467ADB221B3F349002202CA458E8D4E4DE7176D27A91628545E7B295A5DFC8ADF0B5CD3E279B6FA02998"
}
}
],
"SigningPubKey" : "",
"TransactionType" : "Payment"
}
})",
{{"Already multisigned.",
"Already multisigned.",
"Duplicate Signers:Signer:Account entries "
"(rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh) are not allowed.",
""}}},
{"Correctly append to pre-established Signers array",
__LINE__,
R"({
"command": "dummy_command",
"account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"secret": "c",
"tx_json": {
"Account" : "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Amount" : "1000000000",
"Destination" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Fee" : "50",
"Sequence" : 0,
"Signers" : [
{
"Signer" : {
"Account" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"SigningPubKey" : "0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
"TxnSignature" : "304502210080EB23E78A841DDC5E3A4F10DE6EAF052207D6B519BF8954467ADB221B3F349002202CA458E8D4E4DE7176D27A91628545E7B295A5DFC8ADF0B5CD3E279B6FA02998"
}
}
],
"SigningPubKey" : "",
"TransactionType" : "Payment"
}
})",
{{"Already multisigned.", "Already multisigned.", "", ""}}},
{"Append to pre-established Signers array with bad signature",
__LINE__,
R"({
"command": "dummy_command",
"account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"secret": "c",
"tx_json": {
"Account" : "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Amount" : "1000000000",
"Destination" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Fee" : "50",
"Sequence" : 0,
"Signers" : [
{
"Signer" : {
"Account" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"SigningPubKey" : "0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
"TxnSignature" : "304502210080EB23E78A841DDC5E3A4F10DE6EAF052207D6B519BF8954467ACB221B3F349002202CA458E8D4E4DE7176D27A91628545E7B295A5DFC8ADF0B5CD3E279B6FA02998"
}
}
],
"SigningPubKey" : "",
"TransactionType" : "Payment"
}
})",
{{"Already multisigned.",
"Already multisigned.",
"Invalid signature.",
"Invalid signature."}}},
{"Non-empty 'SigningPubKey' in sign_for.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Account": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Amount": "1000000000",
"Destination": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Fee": 50,
"Sequence": 0,
"SigningPubKey": "1",
"TransactionType": "Payment"
}
})",
{{"Secret does not match account.",
"Secret does not match account.",
"When multi-signing 'tx_json.SigningPubKey' must be empty.",
"When multi-signing 'tx_json.SigningPubKey' must be empty."}}},
{"Missing 'TransactionType' in sign_for.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": {
"Account": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Amount": "1000000000",
"Destination": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Fee": 50,
"Sequence": 0,
"SigningPubKey": "",
}
})",
{{"Missing field 'tx_json.TransactionType'.",
"Missing field 'tx_json.TransactionType'.",
"Missing field 'tx_json.TransactionType'.",
"Missing field 'tx_json.TransactionType'."}}},
{"TxnSignature in sign_for.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"secret": "c",
"tx_json": {
"Account" : "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Amount" : "1000000000",
"Destination" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Fee" : "50",
"Sequence" : 0,
"Signers" : [
{
"Signer" : {
"Account" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"SigningPubKey" : "0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
"TxnSignature" : "304502210080EB23E78A841DDC5E3A4F10DE6EAF052207D6B519BF8954467ADB221B3F349002202CA458E8D4E4DE7176D27A91628545E7B295A5DFC8ADF0B5CD3E279B6FA02998"
}
}
],
"SigningPubKey" : "",
"TxnSignature" : "304502210080EB23E78A841DDC5E3A4F10DE6EAF052207D6B519BF8954467ADB221B3F349002202CA458E8D4E4DE7176D27A91628545E7B295A5DFC8ADF0B5CD3E279B6FA02998",
"TransactionType" : "Payment"
}
})",
{{"Already multisigned.",
"Already multisigned.",
"Already single-signed.",
"Signing of transaction is malformed."}}},
{"Invalid field 'tx_json': string instead of object",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": ""
})",
{{"Invalid field 'tx_json', not object.",
"Invalid field 'tx_json', not object.",
"Invalid field 'tx_json', not object.",
"Invalid field 'tx_json', not object."}}},
{"Invalid field 'tx_json': integer instead of object",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": 20160331
})",
{{"Invalid field 'tx_json', not object.",
"Invalid field 'tx_json', not object.",
"Invalid field 'tx_json', not object.",
"Invalid field 'tx_json', not object."}}},
{"Invalid field 'tx_json': array instead of object",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"tx_json": [ "hello", "world" ]
})",
{{"Invalid field 'tx_json', not object.",
"Invalid field 'tx_json', not object.",
"Invalid field 'tx_json', not object.",
"Invalid field 'tx_json', not object."}}},
{"Pass in Fee with minimal payment, both Amount and DeliverMax.",
__LINE__,
R"({
"command": "dummy_command",
"account": "r9zN9x52FiCFAcicCLMQKbj1nxYhxJbbSy",
"secret": "ssgN6zTvtM1q9XV8DvJpWm8LBYWiY",
"tx_json": {
"Fee": 10,
"Account": "r9zN9x52FiCFAcicCLMQKbj1nxYhxJbbSy",
"Amount": "1000000000",
"DeliverMax": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment"
}
})",
{{"Source account not found.",
"Source account not found.",
"Missing field 'tx_json.Sequence'.",
"Missing field 'tx_json.Sequence'."}}},
{"Minimal submit_multisigned.",
__LINE__,
R"({
"command": "submit_multisigned",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Fee": 50,
"Sequence": 0,
"Signers" : [
{
"Signer" : {
"Account" : "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"SigningPubKey" : "02FE36A690D6973D55F88553F5D2C4202DE75F2CF8A6D0E17C70AC223F044501F8",
"TxnSignature" : "3045022100909D01399AFFAD1E30D250CE61F93975B7F61E47B5244D78C3E86D9806535D95022012E389E0ACB016334052B7FE07FA6CEFDC8BE82CB410FA841D5049641C89DC8F"
}
}
],
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
""}}},
{"Minimal submit_multisigned with bad signature.",
__LINE__,
R"({
"command": "submit_multisigned",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Fee": 50,
"Sequence": 0,
"Signers": [
{
"Signer": {
"Account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"TxnSignature": "3045022100F9ED357606932697A4FAB2BE7F222C21DD93CA4CFDD90357AADD07465E8457D6022038173193E3DFFFB5D78DD738CC0905395F885DA65B98FDB9793901FE3FD26ECE",
"SigningPubKey": "02FE36A690D6973D55F88553F5D2C4202DE75F2CF8A6D0E17C70AC223F044501F8"
}
}
],
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"Invalid signature."}}},
{"Missing tx_json in submit_multisigned.",
__LINE__,
R"({
"command": "submit_multisigned",
"Signers": [
{
"Signer": {
"Account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"TxnSignature": "3045022100F9ED357606932697A4FAB2BE7F222C21DD93CA4CFDD90357AADD07465E8457D6022038173193E3DFFFB5D78DD738CC0905395F885DA65B98FDB9793901FE3FD26ECE",
"SigningPubKey": "02FE36A690D6973D55F88553F5D2C4202DE75F2CF8A6D0E17C70AC223F044501F8"
}
}
]
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"Missing field 'tx_json'."}}},
{"Missing sequence in submit_multisigned.",
__LINE__,
R"({
"command": "submit_multisigned",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Fee": 50,
"Signers": [
{
"Signer": {
"Account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"TxnSignature": "3045022100F9ED357606932697A4FAB2BE7F222C21DD93CA4CFDD90357AADD07465E8457D6022038173193E3DFFFB5D78DD738CC0905395F885DA65B98FDB9793901FE3FD26ECE",
"SigningPubKey": "02FE36A690D6973D55F88553F5D2C4202DE75F2CF8A6D0E17C70AC223F044501F8"
}
}
],
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"Missing field 'tx_json.Sequence'."}}},
{"Missing SigningPubKey in submit_multisigned.",
__LINE__,
R"({
"command": "submit_multisigned",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Fee": 50,
"Signers": [
{
"Signer": {
"Account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"TxnSignature": "3045022100F9ED357606932697A4FAB2BE7F222C21DD93CA4CFDD90357AADD07465E8457D6022038173193E3DFFFB5D78DD738CC0905395F885DA65B98FDB9793901FE3FD26ECE",
"SigningPubKey": "02FE36A690D6973D55F88553F5D2C4202DE75F2CF8A6D0E17C70AC223F044501F8"
}
}
],
"Sequence": 0,
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"Missing field 'tx_json.SigningPubKey'."}}},
{"Non-empty SigningPubKey in submit_multisigned.",
__LINE__,
R"({
"command": "submit_multisigned",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Fee": 50,
"Sequence": 0,
"Signers": [
{
"Signer": {
"Account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"TxnSignature": "3045022100F9ED357606932697A4FAB2BE7F222C21DD93CA4CFDD90357AADD07465E8457D6022038173193E3DFFFB5D78DD738CC0905395F885DA65B98FDB9793901FE3FD26ECE",
"SigningPubKey": "02FE36A690D6973D55F88553F5D2C4202DE75F2CF8A6D0E17C70AC223F044501F8"
}
}
],
"SigningPubKey": "02FE36A690D6973D55F88553F5D2C4202DE75F2CF8A6D0E17C70AC223F044501F8",
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"When multi-signing 'tx_json.SigningPubKey' must be empty."}}},
{"Missing TransactionType in submit_multisigned.",
__LINE__,
R"({
"command": "submit_multisigned",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Fee": 50,
"Signers": [
{
"Signer": {
"Account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"TxnSignature": "3045022100F9ED357606932697A4FAB2BE7F222C21DD93CA4CFDD90357AADD07465E8457D6022038173193E3DFFFB5D78DD738CC0905395F885DA65B98FDB9793901FE3FD26ECE",
"SigningPubKey": "02FE36A690D6973D55F88553F5D2C4202DE75F2CF8A6D0E17C70AC223F044501F8"
}
}
],
"Sequence": 0,
"SigningPubKey": "",
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"Missing field 'tx_json.TransactionType'."}}},
{"Missing Account in submit_multisigned.",
__LINE__,
R"({
"command": "submit_multisigned",
"tx_json": {
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Fee": 50,
"Sequence": 0,
"Signers": [
{
"Signer": {
"Account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"TxnSignature": "3045022100F9ED357606932697A4FAB2BE7F222C21DD93CA4CFDD90357AADD07465E8457D6022038173193E3DFFFB5D78DD738CC0905395F885DA65B98FDB9793901FE3FD26ECE",
"SigningPubKey": "02FE36A690D6973D55F88553F5D2C4202DE75F2CF8A6D0E17C70AC223F044501F8"
}
}
],
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"Missing field 'tx_json.Account'."}}},
{"Malformed Account in submit_multisigned.",
__LINE__,
R"({
"command": "submit_multisigned",
"tx_json": {
"Account": "NotAnAccount",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Fee": 50,
"Sequence": 0,
"Signers": [
{
"Signer": {
"Account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"TxnSignature": "3045022100F9ED357606932697A4FAB2BE7F222C21DD93CA4CFDD90357AADD07465E8457D6022038173193E3DFFFB5D78DD738CC0905395F885DA65B98FDB9793901FE3FD26ECE",
"SigningPubKey": "02FE36A690D6973D55F88553F5D2C4202DE75F2CF8A6D0E17C70AC223F044501F8"
}
}
],
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"Invalid field 'tx_json.Account'."}}},
{"Account not in ledger in submit_multisigned.",
__LINE__,
R"({
"command": "submit_multisigned",
"tx_json": {
"Account": "rDg53Haik2475DJx8bjMDSDPj4VX7htaMd",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Fee": 50,
"Sequence": 0,
"Signers": [
{
"Signer": {
"Account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"TxnSignature": "3045022100F9ED357606932697A4FAB2BE7F222C21DD93CA4CFDD90357AADD07465E8457D6022038173193E3DFFFB5D78DD738CC0905395F885DA65B98FDB9793901FE3FD26ECE",
"SigningPubKey": "02FE36A690D6973D55F88553F5D2C4202DE75F2CF8A6D0E17C70AC223F044501F8"
}
}
],
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"Source account not found."}}},
{"Missing Fee in submit_multisigned.",
__LINE__,
R"({
"command": "submit_multisigned",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Sequence": 0,
"Signers": [
{
"Signer": {
"Account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"TxnSignature": "3045022100F9ED357606932697A4FAB2BE7F222C21DD93CA4CFDD90357AADD07465E8457D6022038173193E3DFFFB5D78DD738CC0905395F885DA65B98FDB9793901FE3FD26ECE",
"SigningPubKey": "02FE36A690D6973D55F88553F5D2C4202DE75F2CF8A6D0E17C70AC223F044501F8"
}
}
],
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"Missing field 'tx_json.Fee'."}}},
{"Non-numeric Fee in submit_multisigned.",
__LINE__,
R"({
"command": "submit_multisigned",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Fee": 50.1,
"Sequence": 0,
"Signers": [
{
"Signer": {
"Account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"TxnSignature": "3045022100F9ED357606932697A4FAB2BE7F222C21DD93CA4CFDD90357AADD07465E8457D6022038173193E3DFFFB5D78DD738CC0905395F885DA65B98FDB9793901FE3FD26ECE",
"SigningPubKey": "02FE36A690D6973D55F88553F5D2C4202DE75F2CF8A6D0E17C70AC223F044501F8"
}
}
],
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"Field 'tx_json.Fee' has invalid data."}}},
{"Missing Amount in submit_multisigned Payment.",
__LINE__,
R"({
"command": "submit_multisigned",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Fee": 50000000,
"Sequence": 0,
"Signers": [
{
"Signer": {
"Account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"TxnSignature": "3045022100F9ED357606932697A4FAB2BE7F222C21DD93CA4CFDD90357AADD07465E8457D6022038173193E3DFFFB5D78DD738CC0905395F885DA65B98FDB9793901FE3FD26ECE",
"SigningPubKey": "02FE36A690D6973D55F88553F5D2C4202DE75F2CF8A6D0E17C70AC223F044501F8"
}
}
],
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"Missing field 'tx_json.Amount'."}}},
{"Invalid Amount in submit_multisigned Payment.",
__LINE__,
R"({
"command": "submit_multisigned",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "NotANumber",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Fee": 50,
"Sequence": 0,
"Signers": [
{
"Signer": {
"Account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"TxnSignature": "3045022100F9ED357606932697A4FAB2BE7F222C21DD93CA4CFDD90357AADD07465E8457D6022038173193E3DFFFB5D78DD738CC0905395F885DA65B98FDB9793901FE3FD26ECE",
"SigningPubKey": "02FE36A690D6973D55F88553F5D2C4202DE75F2CF8A6D0E17C70AC223F044501F8"
}
}
],
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"Invalid field 'tx_json.Amount'."}}},
{"Invalid DeliverMax in submit_multisigned Payment.",
__LINE__,
R"({
"command": "submit_multisigned",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"DeliverMax": "NotANumber",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Fee": 50,
"Sequence": 0,
"Signers": [
{
"Signer": {
"Account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"TxnSignature": "3045022100F9ED357606932697A4FAB2BE7F222C21DD93CA4CFDD90357AADD07465E8457D6022038173193E3DFFFB5D78DD738CC0905395F885DA65B98FDB9793901FE3FD26ECE",
"SigningPubKey": "02FE36A690D6973D55F88553F5D2C4202DE75F2CF8A6D0E17C70AC223F044501F8"
}
}
],
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"Invalid field 'tx_json.Amount'."}}},
{"No build_path in submit_multisigned.",
__LINE__,
R"({
"command": "submit_multisigned",
"build_path": 1,
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Fee": 50,
"Sequence": 0,
"Signers": [
{
"Signer": {
"Account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"TxnSignature": "3045022100F9ED357606932697A4FAB2BE7F222C21DD93CA4CFDD90357AADD07465E8457D6022038173193E3DFFFB5D78DD738CC0905395F885DA65B98FDB9793901FE3FD26ECE",
"SigningPubKey": "02FE36A690D6973D55F88553F5D2C4202DE75F2CF8A6D0E17C70AC223F044501F8"
}
}
],
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"Field 'build_path' not allowed in this context."}}},
{"Missing Destination in submit_multisigned Payment.",
__LINE__,
R"({
"command": "submit_multisigned",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Fee": 50,
"Sequence": 0,
"Signers": [
{
"Signer": {
"Account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"TxnSignature": "3045022100F9ED357606932697A4FAB2BE7F222C21DD93CA4CFDD90357AADD07465E8457D6022038173193E3DFFFB5D78DD738CC0905395F885DA65B98FDB9793901FE3FD26ECE",
"SigningPubKey": "02FE36A690D6973D55F88553F5D2C4202DE75F2CF8A6D0E17C70AC223F044501F8"
}
}
],
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"Missing field 'tx_json.Destination'."}}},
{"Malformed Destination in submit_multisigned Payment.",
__LINE__,
R"({
"command": "submit_multisigned",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "NotADestination",
"Fee": 50,
"Sequence": 0,
"Signers": [
{
"Signer": {
"Account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"TxnSignature": "3045022100F9ED357606932697A4FAB2BE7F222C21DD93CA4CFDD90357AADD07465E8457D6022038173193E3DFFFB5D78DD738CC0905395F885DA65B98FDB9793901FE3FD26ECE",
"SigningPubKey": "02FE36A690D6973D55F88553F5D2C4202DE75F2CF8A6D0E17C70AC223F044501F8"
}
}
],
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"Invalid field 'tx_json.Destination'."}}},
{"Missing Signers field in submit_multisigned.",
__LINE__,
R"({
"command": "submit_multisigned",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Fee": 50,
"Sequence": 0,
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"Missing field 'tx_json.Signers'."}}},
{"Signers not an array in submit_multisigned.",
__LINE__,
R"({
"command": "submit_multisigned",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Fee": 50,
"Sequence": 0,
"Signers": {
"Account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"TxnSignature": "3045022100F9ED357606932697A4FAB2BE7F222C21DD93CA4CFDD90357AADD07465E8457D6022038173193E3DFFFB5D78DD738CC0905395F885DA65B98FDB9793901FE3FD26ECE",
"SigningPubKey": "02FE36A690D6973D55F88553F5D2C4202DE75F2CF8A6D0E17C70AC223F044501F8"
},
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"Field 'tx_json.Signers' is not a JSON array."}}},
{"Empty Signers array in submit_multisigned.",
__LINE__,
R"({
"command": "submit_multisigned",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Fee": 50,
"Sequence": 0,
"Signers": [
],
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"tx_json.Signers array may not be empty."}}},
{"Duplicate Signer in submit_multisigned.",
__LINE__,
R"({
"command": "submit_multisigned",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Fee": 50,
"Sequence": 0,
"Signers": [
{
"Signer": {
"Account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"TxnSignature": "3045022100F9ED357606932697A4FAB2BE7F222C21DD93CA4CFDD90357AADD07465E8457D6022038173193E3DFFFB5D78DD738CC0905395F885DA65B98FDB9793901FE3FD26ECE",
"SigningPubKey": "02FE36A690D6973D55F88553F5D2C4202DE75F2CF8A6D0E17C70AC223F044501F8"
}
},
{
"Signer": {
"Account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
"TxnSignature": "3045022100F9ED357606932697A4FAB2BE7F222C21DD93CA4CFDD90357AADD07465E8457D6022038173193E3DFFFB5D78DD738CC0905395F885DA65B98FDB9793901FE3FD26ECE",
"SigningPubKey": "02FE36A690D6973D55F88553F5D2C4202DE75F2CF8A6D0E17C70AC223F044501F8"
}
}
],
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"Duplicate Signers:Signer:Account entries "
"(rPcNzota6B8YBokhYtcTNqQVCngtbnWfux) are not allowed."}}},
{"Signer is tx_json Account in submit_multisigned.",
__LINE__,
R"({
"command": "submit_multisigned",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Fee": 50,
"Sequence": 0,
"Signers": [
{
"Signer": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"TxnSignature": "3045022100F9ED357606932697A4FAB2BE7F222C21DD93CA4CFDD90357AADD07465E8457D6022038173193E3DFFFB5D78DD738CC0905395F885DA65B98FDB9793901FE3FD26ECE",
"SigningPubKey": "02FE36A690D6973D55F88553F5D2C4202DE75F2CF8A6D0E17C70AC223F044501F8"
}
}
],
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"A Signer may not be the transaction's Account "
"(rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh)."}}},
{"Empty Signers array in submit_multisigned, use DeliverMax",
__LINE__,
R"({
"command": "submit_multisigned",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"DeliverMax": "10000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Fee": 50,
"Sequence": 0,
"Signers": [
],
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"tx_json.Signers array may not be empty."}}},
{"Empty Signers array in submit_multisigned, use DeliverMax and Amount",
__LINE__,
R"({
"command": "submit_multisigned",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "10000000",
"DeliverMax": "10000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Fee": 50,
"Sequence": 0,
"Signers": [
],
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Missing field 'secret'.",
"Missing field 'secret'.",
"Missing field 'account'.",
"tx_json.Signers array may not be empty."}}},
{"Payment cannot specify different DeliverMax and Amount.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"debug_signing": 0,
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"DeliverMax": "1000000020",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Fee": 50,
"Sequence": 0,
"SigningPubKey": "",
"TransactionType": "Payment"
}
})",
{{"Cannot specify differing 'Amount' and 'DeliverMax'",
"Cannot specify differing 'Amount' and 'DeliverMax'",
"Cannot specify differing 'Amount' and 'DeliverMax'",
"Cannot specify differing 'Amount' and 'DeliverMax'"}}},
{"Payment cannot specify bad DomainID.",
__LINE__,
R"({
"command": "dummy_command",
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"secret": "masterpassphrase",
"debug_signing": 0,
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"Fee": 50,
"Sequence": 0,
"SigningPubKey": "",
"TransactionType": "Payment",
"DomainID": "invalid",
}
})",
{{"Unable to parse 'DomainID'.",
"Unable to parse 'DomainID'.",
"Unable to parse 'DomainID'.",
"Unable to parse 'DomainID'."}}},
{"Minimal delegated transaction.",
__LINE__,
R"({
"command": "dummy_command",
"secret": "a",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"TransactionType": "Payment",
"Delegate": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA"
}
})",
{{"",
"",
"Missing field 'account'.",
"Missing field 'tx_json.Sequence'."}}},
{"Delegate not well formed.",
__LINE__,
R"({
"command": "dummy_command",
"secret": "a",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi",
"TransactionType": "Payment",
"Delegate": "NotAnAccount"
}
})",
{{"Invalid field 'tx_json.Delegate'.",
"Invalid field 'tx_json.Delegate'.",
"Missing field 'account'.",
"Missing field 'tx_json.Sequence'."}}},
{"Delegate not in ledger.",
__LINE__,
R"({
"command": "dummy_command",
"secret": "a",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi",
"TransactionType": "Payment",
"Delegate": "rDg53Haik2475DJx8bjMDSDPj4VX7htaMd"
}
})",
{{"Delegate account not found.",
"Delegate account not found.",
"Missing field 'account'.",
"Missing field 'tx_json.Sequence'."}}},
{"Delegate and secret not match.",
__LINE__,
R"({
"command": "dummy_command",
"secret": "aa",
"tx_json": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount": "1000000000",
"Destination": "rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi",
"TransactionType": "Payment",
"Delegate": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA"
}
})",
{{"Secret does not match account.",
"Secret does not match account.",
"Missing field 'account'.",
"Missing field 'tx_json.Sequence'."}}},
};
class JSONRPC_test : public beast::unit_test::suite
{
public:
void
testBadRpcCommand()
{
testcase("bad RPC command");
test::jtx::Env env(*this);
Json::Value const result{
env.rpc("bad_command", R"({"MakingThisUp": 0})")};
BEAST_EXPECT(result[jss::result][jss::error] == "unknownCmd");
BEAST_EXPECT(
result[jss::result][jss::request][jss::command] == "bad_command");
}
void
testAutoFillFails()
{
testcase("autofill fails");
using namespace test::jtx;
// test batch raw transactions max size
{
Env env(*this);
auto ledger = env.current();
auto const& feeTrack = env.app().getFeeTrack();
Json::Value req;
Account const alice("alice");
Account const bob("bob");
env.fund(XRP(100000), alice);
env.close();
auto const batchFee = batch::calcBatchFee(env, 0, 2);
auto const seq = env.seq(alice);
auto jt = env.jtnofill(
batch::outer(alice, env.seq(alice), batchFee, tfAllOrNothing),
batch::inner(pay(alice, bob, XRP(1)), seq + 1),
batch::inner(pay(alice, bob, XRP(2)), seq + 2),
batch::inner(pay(alice, bob, XRP(3)), seq + 3),
batch::inner(pay(alice, bob, XRP(4)), seq + 4),
batch::inner(pay(alice, bob, XRP(5)), seq + 5),
batch::inner(pay(alice, bob, XRP(6)), seq + 6),
batch::inner(pay(alice, bob, XRP(7)), seq + 7),
batch::inner(pay(alice, bob, XRP(8)), seq + 8),
batch::inner(pay(alice, bob, XRP(9)), seq + 9));
jt.jv.removeMember(jss::Fee);
jt.jv.removeMember(jss::TxnSignature);
req[jss::tx_json] = jt.jv;
Json::Value result = checkFee(
req,
Role::ADMIN,
true,
env.app().config(),
feeTrack,
env.app().getTxQ(),
env.app());
BEAST_EXPECT(result.size() == 0);
BEAST_EXPECT(
req[jss::tx_json].isMember(jss::Fee) &&
req[jss::tx_json][jss::Fee] ==
env.current()->fees().base.jsonClipped());
}
// test signers max size
{
Env env(*this);
auto ledger = env.current();
auto const& feeTrack = env.app().getFeeTrack();
Json::Value req;
Account const alice("alice");
Account const bob("bob");
env.fund(XRP(100000), alice, bob);
env.close();
auto jt = env.jtnofill(
noop(alice),
msig(
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice,
alice));
req[jss::tx_json] = jt.jv;
Json::Value result = checkFee(
req,
Role::ADMIN,
true,
env.app().config(),
feeTrack,
env.app().getTxQ(),
env.app());
BEAST_EXPECT(result.size() == 0);
BEAST_EXPECT(
req[jss::tx_json].isMember(jss::Fee) &&
req[jss::tx_json][jss::Fee] ==
env.current()->fees().base.jsonClipped());
}
}
void
testAutoFillFees()
{
testcase("autofill fees");
test::jtx::Env env(*this);
auto const baseFee =
static_cast<int>(env.current()->fees().base.drops());
auto ledger = env.current();
auto const& feeTrack = env.app().getFeeTrack();
{
Json::Value req;
Json::Reader().parse(
"{ \"fee_mult_max\" : 1, \"tx_json\" : { } } ", req);
Json::Value result = checkFee(
req,
Role::ADMIN,
true,
env.app().config(),
feeTrack,
env.app().getTxQ(),
env.app());
BEAST_EXPECT(!RPC::contains_error(result));
BEAST_EXPECT(
req[jss::tx_json].isMember(jss::Fee) &&
req[jss::tx_json][jss::Fee] == baseFee);
}
{
Json::Value req;
Json::Reader().parse(
"{ \"fee_mult_max\" : 3, \"fee_div_max\" : 2, "
"\"tx_json\" : { } } ",
req);
Json::Value result = checkFee(
req,
Role::ADMIN,
true,
env.app().config(),
feeTrack,
env.app().getTxQ(),
env.app());
BEAST_EXPECT(!RPC::contains_error(result));
BEAST_EXPECT(
req[jss::tx_json].isMember(jss::Fee) &&
req[jss::tx_json][jss::Fee] == baseFee);
}
{
Json::Value req;
Json::Reader().parse(
"{ \"fee_mult_max\" : 0, \"tx_json\" : { } } ", req);
Json::Value result = checkFee(
req,
Role::ADMIN,
true,
env.app().config(),
feeTrack,
env.app().getTxQ(),
env.app());
BEAST_EXPECT(RPC::contains_error(result));
BEAST_EXPECT(!req[jss::tx_json].isMember(jss::Fee));
}
{
// 3/6 = 1/2, but use the bigger number make sure
// we're dividing.
Json::Value req;
Json::Reader().parse(
"{ \"fee_mult_max\" : 3, \"fee_div_max\" : 6, "
"\"tx_json\" : { } } ",
req);
Json::Value result = checkFee(
req,
Role::ADMIN,
true,
env.app().config(),
feeTrack,
env.app().getTxQ(),
env.app());
BEAST_EXPECT(RPC::contains_error(result));
BEAST_EXPECT(!req[jss::tx_json].isMember(jss::Fee));
}
{
Json::Value req;
Json::Reader().parse(
"{ \"fee_mult_max\" : 0, \"fee_div_max\" : 2, "
"\"tx_json\" : { } } ",
req);
Json::Value result = checkFee(
req,
Role::ADMIN,
true,
env.app().config(),
feeTrack,
env.app().getTxQ(),
env.app());
BEAST_EXPECT(RPC::contains_error(result));
BEAST_EXPECT(!req[jss::tx_json].isMember(jss::Fee));
}
{
Json::Value req;
Json::Reader().parse(
"{ \"fee_mult_max\" : 10, \"fee_div_max\" : 0, "
"\"tx_json\" : { } } ",
req);
Json::Value result = checkFee(
req,
Role::ADMIN,
true,
env.app().config(),
feeTrack,
env.app().getTxQ(),
env.app());
BEAST_EXPECT(RPC::contains_error(result));
BEAST_EXPECT(!req[jss::tx_json].isMember(jss::Fee));
}
{
// transaction with a higher base fee
Json::Value req;
test::jtx::Account const alice("alice");
req[jss::tx_json] =
test::jtx::acctdelete(env.master.human(), alice.human());
Json::Value result = checkFee(
req,
Role::ADMIN,
true,
env.app().config(),
feeTrack,
env.app().getTxQ(),
env.app());
BEAST_EXPECT(result.size() == 0);
BEAST_EXPECT(
req[jss::tx_json].isMember(jss::Fee) &&
req[jss::tx_json][jss::Fee] ==
env.current()->fees().increment.jsonClipped());
}
}
void
testAutoFillEscalatedFees()
{
testcase("autofill escalated fees");
using namespace test::jtx;
Env env{*this, envconfig([](std::unique_ptr<Config> cfg) {
cfg->loadFromString("[" SECTION_SIGNING_SUPPORT "]\ntrue");
cfg->section("transaction_queue")
.set("minimum_txn_in_ledger_standalone", "3");
return cfg;
})};
LoadFeeTrack const& feeTrackOuter = env.app().getFeeTrack();
{
// high mult, no tx
Json::Value req;
Json::Reader().parse(
R"({
"fee_mult_max" : 1000,
"tx_json" : { }
})",
req);
Json::Value result = checkFee(
req,
Role::ADMIN,
true,
env.app().config(),
feeTrackOuter,
env.app().getTxQ(),
env.app());
BEAST_EXPECT(!RPC::contains_error(result));
BEAST_EXPECT(
req[jss::tx_json].isMember(jss::Fee) &&
req[jss::tx_json][jss::Fee] == 10);
}
{
// low mult, no tx
Json::Value req;
Json::Reader().parse(
R"({
"fee_mult_max" : 5,
"tx_json" : { }
})",
req);
Json::Value result = checkFee(
req,
Role::ADMIN,
true,
env.app().config(),
feeTrackOuter,
env.app().getTxQ(),
env.app());
BEAST_EXPECT(!RPC::contains_error(result));
BEAST_EXPECT(
req[jss::tx_json].isMember(jss::Fee) &&
req[jss::tx_json][jss::Fee] == 10);
}
// put 4 transactions into the open ledger
for (auto i = 0; i < 4; ++i)
{
env(noop(env.master));
}
{
// high mult, 4 txs
Json::Value req;
Json::Reader().parse(
R"({
"fee_mult_max" : 1000,
"tx_json" : { }
})",
req);
Json::Value result = checkFee(
req,
Role::ADMIN,
true,
env.app().config(),
feeTrackOuter,
env.app().getTxQ(),
env.app());
BEAST_EXPECT(!RPC::contains_error(result));
BEAST_EXPECT(
req[jss::tx_json].isMember(jss::Fee) &&
req[jss::tx_json][jss::Fee] == 8889);
}
{
// low mult, 4 tx
Json::Value req;
Json::Reader().parse(
R"({
"fee_mult_max" : 5,
"tx_json" : { }
})",
req);
Json::Value result = checkFee(
req,
Role::ADMIN,
true,
env.app().config(),
feeTrackOuter,
env.app().getTxQ(),
env.app());
BEAST_EXPECT(RPC::contains_error(result));
BEAST_EXPECT(!req[jss::tx_json].isMember(jss::Fee));
}
{
// different low mult, 4 tx
Json::Value req;
Json::Reader().parse(
R"({
"fee_mult_max" : 1000,
"fee_div_max" : 3,
"tx_json" : { }
})",
req);
Json::Value result = checkFee(
req,
Role::ADMIN,
true,
env.app().config(),
feeTrackOuter,
env.app().getTxQ(),
env.app());
BEAST_EXPECT(RPC::contains_error(result));
BEAST_EXPECT(!req[jss::tx_json].isMember(jss::Fee));
}
{
// high mult, 4 tx
Json::Value req;
Json::Reader().parse(
R"({
"fee_mult_max" : 8000,
"fee_div_max" : 3,
"tx_json" : { }
})",
req);
Json::Value result = checkFee(
req,
Role::ADMIN,
true,
env.app().config(),
feeTrackOuter,
env.app().getTxQ(),
env.app());
BEAST_EXPECT(!RPC::contains_error(result));
BEAST_EXPECT(
req[jss::tx_json].isMember(jss::Fee) &&
req[jss::tx_json][jss::Fee] == 8889);
}
{
// negative mult
Json::Value req;
Json::Reader().parse(
R"({
"fee_mult_max" : -5,
"tx_json" : { }
})",
req);
Json::Value result = checkFee(
req,
Role::ADMIN,
true,
env.app().config(),
feeTrackOuter,
env.app().getTxQ(),
env.app());
BEAST_EXPECT(RPC::contains_error(result));
}
{
// negative div
Json::Value req;
Json::Reader().parse(
R"({
"fee_div_max" : -2,
"tx_json" : { }
})",
req);
Json::Value result = checkFee(
req,
Role::ADMIN,
true,
env.app().config(),
feeTrackOuter,
env.app().getTxQ(),
env.app());
BEAST_EXPECT(RPC::contains_error(result));
}
{
// negative mult & div
Json::Value req;
Json::Reader().parse(
R"({
"fee_mult_max" : -2,
"fee_div_max" : -3,
"tx_json" : { }
})",
req);
Json::Value result = checkFee(
req,
Role::ADMIN,
true,
env.app().config(),
feeTrackOuter,
env.app().getTxQ(),
env.app());
BEAST_EXPECT(RPC::contains_error(result));
}
env.close();
{
// Call "sign" with nothing in the open ledger
Json::Value toSign;
toSign[jss::tx_json] = noop(env.master);
toSign[jss::secret] = "masterpassphrase";
auto rpcResult = env.rpc("json", "sign", to_string(toSign));
auto result = rpcResult[jss::result];
BEAST_EXPECT(!RPC::contains_error(result));
BEAST_EXPECT(
result[jss::tx_json].isMember(jss::Fee) &&
result[jss::tx_json][jss::Fee] == "10");
BEAST_EXPECT(
result[jss::tx_json].isMember(jss::Sequence) &&
result[jss::tx_json][jss::Sequence].isConvertibleTo(
Json::ValueType::uintValue));
}
{
// Call "sign" with enough transactions in the open ledger
// to escalate the fee.
for (;;)
{
auto metrics = env.app().getTxQ().getMetrics(*env.current());
if (metrics.openLedgerFeeLevel > metrics.minProcessingFeeLevel)
break;
env(noop(env.master));
}
Json::Value toSign;
toSign[jss::tx_json] = noop(env.master);
toSign[jss::secret] = "masterpassphrase";
toSign[jss::fee_mult_max] = 900;
auto rpcResult = env.rpc("json", "sign", to_string(toSign));
auto result = rpcResult[jss::result];
BEAST_EXPECT(!RPC::contains_error(result));
BEAST_EXPECT(
result[jss::tx_json].isMember(jss::Fee) &&
result[jss::tx_json][jss::Fee] == "7813");
BEAST_EXPECT(
result[jss::tx_json].isMember(jss::Sequence) &&
result[jss::tx_json][jss::Sequence].isConvertibleTo(
Json::ValueType::uintValue));
env.close();
}
{
// Call "sign" with higher server load
{
auto& feeTrack = env.app().getFeeTrack();
BEAST_EXPECT(feeTrack.getLoadFactor() == 256);
for (int i = 0; i < 8; ++i)
feeTrack.raiseLocalFee();
BEAST_EXPECT(feeTrack.getLoadFactor() == 1220);
}
Json::Value toSign;
toSign[jss::tx_json] = noop(env.master);
toSign[jss::secret] = "masterpassphrase";
auto rpcResult = env.rpc("json", "sign", to_string(toSign));
auto result = rpcResult[jss::result];
BEAST_EXPECT(!RPC::contains_error(result));
BEAST_EXPECT(
result[jss::tx_json].isMember(jss::Fee) &&
result[jss::tx_json][jss::Fee] == "47");
BEAST_EXPECT(
result[jss::tx_json].isMember(jss::Sequence) &&
result[jss::tx_json][jss::Sequence].isConvertibleTo(
Json::ValueType::uintValue));
}
{
// Call "sign" with higher server load and
// enough transactions to escalate the fee
BEAST_EXPECT(feeTrackOuter.getLoadFactor() == 1220);
for (;;)
{
auto metrics = env.app().getTxQ().getMetrics(*env.current());
if (metrics.openLedgerFeeLevel > metrics.minProcessingFeeLevel)
break;
env(noop(env.master), fee(47));
}
Env_ss envs(env);
Json::Value toSign;
toSign[jss::tx_json] = noop(env.master);
toSign[jss::secret] = "masterpassphrase";
// Max fee = 7000 drops
toSign[jss::fee_mult_max] = 700;
auto rpcResult = env.rpc("json", "sign", to_string(toSign));
auto result = rpcResult[jss::result];
BEAST_EXPECT(!RPC::contains_error(result));
BEAST_EXPECT(
result[jss::tx_json].isMember(jss::Fee) &&
result[jss::tx_json][jss::Fee] == "6806");
BEAST_EXPECT(
result[jss::tx_json].isMember(jss::Sequence) &&
result[jss::tx_json][jss::Sequence].isConvertibleTo(
Json::ValueType::uintValue));
}
}
void
testAutoFillNetworkID()
{
testcase("autofill NetworkID");
using namespace test::jtx;
Env env{*this, envconfig([&](std::unique_ptr<Config> cfg) {
cfg->NETWORK_ID = 1025;
return cfg;
})};
{
Json::Value toSign;
toSign[jss::tx_json] = noop(env.master);
BEAST_EXPECT(!toSign[jss::tx_json].isMember(jss::NetworkID));
toSign[jss::secret] = "masterpassphrase";
auto rpcResult = env.rpc("json", "sign", to_string(toSign));
auto result = rpcResult[jss::result];
BEAST_EXPECT(!RPC::contains_error(result));
BEAST_EXPECT(
result[jss::tx_json].isMember(jss::NetworkID) &&
result[jss::tx_json][jss::NetworkID] == 1025);
}
}
// A function that can be called as though it would process a transaction.
static void
fakeProcessTransaction(
std::shared_ptr<Transaction>&,
bool,
bool,
NetworkOPs::FailHard)
{
;
}
void
testTransactionRPC()
{
testcase("sign/submit RPCs");
using namespace std::chrono_literals;
using namespace test::jtx;
// Use jtx to set up a ledger so the tests will do the right thing.
Account const a{"a"}; // rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA
Account const g{"g"}; // rLPwWB1itaUGMV8kbMLLysjGkEpTM2Soy4
auto const USD = g["USD"];
// Account: rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi
// seed: sh1yJfwoi98zCygwijUzuHmJDeVKd
Account const ed{"ed", KeyType::ed25519};
// master is rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh.
// "b" (not in the ledger) is rDg53Haik2475DJx8bjMDSDPj4VX7htaMd.
// "c" (phantom signer) is rPcNzota6B8YBokhYtcTNqQVCngtbnWfux.
Env env(*this, envconfig([](std::unique_ptr<Config> cfg) {
cfg->FEES.reference_fee = 10;
return cfg;
}));
env.fund(XRP(100000), a, ed, g);
env.close();
env(trust(a, USD(1000)));
env(trust(env.master, USD(1000)));
env(pay(g, a, USD(50)));
env(pay(g, env.master, USD(50)));
env.close();
ProcessTransactionFn processTxn = fakeProcessTransaction;
// A list of all the functions we want to test.
using signFunc = Json::Value (*)(
Json::Value params,
unsigned int apiVersion,
NetworkOPs::FailHard failType,
Role role,
std::chrono::seconds validatedLedgerAge,
Application& app);
using submitFunc = Json::Value (*)(
Json::Value params,
unsigned int apiVersion,
NetworkOPs::FailHard failType,
Role role,
std::chrono::seconds validatedLedgerAge,
Application& app,
ProcessTransactionFn const& processTransaction);
using TestStuff =
std::tuple<signFunc, submitFunc, char const*, unsigned int>;
static TestStuff const testFuncs[] = {
TestStuff{transactionSign, nullptr, "sign", 0},
TestStuff{nullptr, transactionSubmit, "submit", 1},
TestStuff{transactionSignFor, nullptr, "sign_for", 2},
TestStuff{
nullptr,
transactionSubmitMultiSigned,
"submit_multisigned",
3}};
for (auto testFunc : testFuncs)
{
// For each JSON test.
for (auto const& txnTest : txnTestArray)
{
Json::Value req;
Json::Reader().parse(txnTest.json, req);
if (RPC::contains_error(req))
Throw<std::runtime_error>(
"Internal JSONRPC_test error. Bad test JSON.");
static Role const testedRoles[] = {
Role::GUEST, Role::USER, Role::ADMIN, Role::FORBID};
for (Role testRole : testedRoles)
{
Json::Value result;
auto const signFn = get<0>(testFunc);
if (signFn != nullptr)
{
assert(get<1>(testFunc) == nullptr);
result = signFn(
req,
1,
NetworkOPs::FailHard::yes,
testRole,
1s,
env.app());
}
else
{
auto const submitFn = get<1>(testFunc);
assert(submitFn != nullptr);
result = submitFn(
req,
1,
NetworkOPs::FailHard::yes,
testRole,
1s,
env.app(),
processTxn);
}
std::string errStr;
if (RPC::contains_error(result))
errStr = result["error_message"].asString();
if (errStr == txnTest.expMsg[get<3>(testFunc)])
{
pass();
}
else
{
std::ostringstream description;
description << txnTest.description << " Called "
<< get<2>(testFunc) << "(). Got \'"
<< errStr << "\'";
fail(description.str(), __FILE__, txnTest.line);
}
}
}
}
}
void
run() override
{
testBadRpcCommand();
testAutoFillFails();
testAutoFillFees();
testAutoFillEscalatedFees();
testAutoFillNetworkID();
testTransactionRPC();
}
};
BEAST_DEFINE_TESTSUITE(JSONRPC, rpc, xrpl);
} // namespace RPC
} // namespace xrpl