Merge branch 'develop' into dangell7/batch-v1

This commit is contained in:
Denis Angell
2026-05-20 11:23:16 +02:00
1751 changed files with 116134 additions and 66228 deletions

View File

@@ -1,29 +1,53 @@
#include <test/jtx.h>
#include <test/jtx/Account.h>
#include <test/jtx/Env.h>
#include <test/jtx/TestHelpers.h>
#include <test/jtx/amount.h>
#include <test/jtx/batch.h>
#include <test/jtx/credentials.h>
#include <test/jtx/envconfig.h>
#include <test/jtx/flags.h>
#include <test/jtx/multisign.h>
#include <test/jtx/noop.h>
#include <test/jtx/pay.h>
#include <test/jtx/regkey.h>
#include <test/jtx/sig.h>
#include <test/jtx/token.h>
#include <xrpld/app/rdb/backend/SQLiteDatabase.h>
#include <xrpld/rpc/CTID.h>
#include <xrpl/basics/Slice.h>
#include <xrpl/basics/StringUtilities.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/basics/chrono.h>
#include <xrpl/basics/strHex.h>
#include <xrpl/beast/unit_test/suite.h>
#include <xrpl/json/json_value.h>
#include <xrpl/json/to_string.h>
#include <xrpl/protocol/ErrorCodes.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STBase.h>
#include <xrpl/protocol/STParsedJSON.h>
#include <xrpl/protocol/Serializer.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/protocol/XRPAmount.h>
#include <xrpl/protocol/jss.h>
#include <xrpl/protocol/serialize.h>
#include <chrono>
#include <cstdint>
#include <functional>
#include <memory>
#include <optional>
#include <tuple>
#include <string>
namespace xrpl {
namespace xrpl::test {
namespace test {
class Simulate_test : public beast::unit_test::suite
class Simulate_test : public beast::unit_test::Suite
{
void
checkBasicReturnValidity(
Json::Value const& result,
Json::Value const& tx,
json::Value const& result,
json::Value const& tx,
int const expectedSequence,
std::string const& expectedFee)
{
@@ -33,29 +57,29 @@ class Simulate_test : public beast::unit_test::suite
BEAST_EXPECT(result.isMember(jss::engine_result_message));
BEAST_EXPECT(result.isMember(jss::tx_json) || result.isMember(jss::tx_blob));
Json::Value tx_json;
json::Value txJson;
if (result.isMember(jss::tx_json))
{
tx_json = result[jss::tx_json];
txJson = result[jss::tx_json];
}
else
{
auto const unHexed = strUnHex(result[jss::tx_blob].asString());
SerialIter sitTrans(makeSlice(*unHexed)); // NOLINT(bugprone-unchecked-optional-access)
tx_json = STObject(std::ref(sitTrans), sfGeneric).getJson(JsonOptions::none);
txJson = STObject(std::ref(sitTrans), kSfGeneric).getJson(JsonOptions::Values::None);
}
BEAST_EXPECT(tx_json[jss::TransactionType] == tx[jss::TransactionType]);
BEAST_EXPECT(tx_json[jss::Account] == tx[jss::Account]);
BEAST_EXPECT(tx_json[jss::SigningPubKey] == tx.get(jss::SigningPubKey, ""));
BEAST_EXPECT(tx_json[jss::TxnSignature] == tx.get(jss::TxnSignature, ""));
BEAST_EXPECT(tx_json[jss::Fee] == tx.get(jss::Fee, expectedFee));
BEAST_EXPECT(tx_json[jss::Sequence] == tx.get(jss::Sequence, expectedSequence));
BEAST_EXPECT(txJson[jss::TransactionType] == tx[jss::TransactionType]);
BEAST_EXPECT(txJson[jss::Account] == tx[jss::Account]);
BEAST_EXPECT(txJson[jss::SigningPubKey] == tx.get(jss::SigningPubKey, ""));
BEAST_EXPECT(txJson[jss::TxnSignature] == tx.get(jss::TxnSignature, ""));
BEAST_EXPECT(txJson[jss::Fee] == tx.get(jss::Fee, expectedFee));
BEAST_EXPECT(txJson[jss::Sequence] == tx.get(jss::Sequence, expectedSequence));
}
void
checkBasicReturnValidity(
Json::Value const& result,
Json::Value const& tx,
json::Value const& result,
json::Value const& tx,
int const expectedSequence,
XRPAmount const& expectedFee)
{
@@ -66,13 +90,13 @@ class Simulate_test : public beast::unit_test::suite
void
testTx(
jtx::Env& env,
Json::Value const& tx,
std::function<void(Json::Value const&, Json::Value const&)> const& validate,
json::Value const& tx,
std::function<void(json::Value const&, json::Value const&)> const& validate,
bool testSerialized = true)
{
env.close();
Json::Value params;
json::Value params;
params[jss::tx_json] = tx;
validate(env.rpc("json", "simulate", to_string(params)), tx);
@@ -88,17 +112,17 @@ class Simulate_test : public beast::unit_test::suite
// will crash
STParsedJSONObject const parsed(std::string(jss::tx_json), tx);
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
auto const tx_blob = strHex(parsed.object->getSerializer().peekData());
auto const txBlob = strHex(parsed.object->getSerializer().peekData());
if (BEAST_EXPECT(parsed.object.has_value()))
{
Json::Value params;
params[jss::tx_blob] = tx_blob;
json::Value params;
params[jss::tx_blob] = txBlob;
validate(env.rpc("json", "simulate", to_string(params)), tx);
params[jss::binary] = true;
validate(env.rpc("json", "simulate", to_string(params)), tx);
}
validate(env.rpc("simulate", tx_blob), tx);
validate(env.rpc("simulate", tx_blob, "binary"), tx);
validate(env.rpc("simulate", txBlob), tx);
validate(env.rpc("simulate", txBlob, "binary"), tx);
}
BEAST_EXPECTS(env.current()->txCount() == 0, std::to_string(env.current()->txCount()));
@@ -107,18 +131,18 @@ class Simulate_test : public beast::unit_test::suite
void
testTxJsonMetadataField(
jtx::Env& env,
Json::Value const& tx,
json::Value const& tx,
std::function<void(
Json::Value const&,
Json::Value const&,
Json::Value const&,
Json::Value const&)> const& validate,
Json::Value const& expectedMetadataKey,
Json::Value const& expectedMetadataValue)
json::Value const&,
json::Value const&,
json::Value const&,
json::Value const&)> const& validate,
json::Value const& expectedMetadataKey,
json::Value const& expectedMetadataValue)
{
env.close();
Json::Value params;
json::Value params;
params[jss::tx_json] = tx;
validate(
env.rpc("json", "simulate", to_string(params)),
@@ -131,14 +155,14 @@ class Simulate_test : public beast::unit_test::suite
BEAST_EXPECTS(env.current()->txCount() == 0, std::to_string(env.current()->txCount()));
}
static Json::Value
getJsonMetadata(Json::Value txResult)
static json::Value
getJsonMetadata(json::Value txResult)
{
if (txResult.isMember(jss::meta_blob))
{
auto unHexed = strUnHex(txResult[jss::meta_blob].asString());
SerialIter sitTrans(makeSlice(*unHexed)); // NOLINT(bugprone-unchecked-optional-access)
return STObject(std::ref(sitTrans), sfGeneric).getJson(JsonOptions::none);
return STObject(std::ref(sitTrans), kSfGeneric).getJson(JsonOptions::Values::None);
}
return txResult[jss::meta];
@@ -155,7 +179,7 @@ class Simulate_test : public beast::unit_test::suite
{
// No params
Json::Value const params = Json::objectValue;
json::Value const params = json::ValueType::Object;
auto const resp = env.rpc("json", "simulate", to_string(params));
BEAST_EXPECT(
resp[jss::result][jss::error_message] ==
@@ -163,8 +187,8 @@ class Simulate_test : public beast::unit_test::suite
}
{
// Providing both `tx_json` and `tx_blob`
Json::Value params = Json::objectValue;
params[jss::tx_json] = Json::objectValue;
json::Value params = json::ValueType::Object;
params[jss::tx_json] = json::ValueType::Object;
params[jss::tx_blob] = "1200";
auto const resp = env.rpc("json", "simulate", to_string(params));
@@ -174,7 +198,7 @@ class Simulate_test : public beast::unit_test::suite
}
{
// `binary` isn't a boolean
Json::Value params = Json::objectValue;
json::Value params = json::ValueType::Object;
params[jss::tx_blob] = "1200";
params[jss::binary] = "100";
auto const resp = env.rpc("json", "simulate", to_string(params));
@@ -182,7 +206,7 @@ class Simulate_test : public beast::unit_test::suite
}
{
// Invalid `tx_blob`
Json::Value params = Json::objectValue;
json::Value params = json::ValueType::Object;
params[jss::tx_blob] = "12";
auto const resp = env.rpc("json", "simulate", to_string(params));
@@ -190,8 +214,8 @@ class Simulate_test : public beast::unit_test::suite
}
{
// Empty `tx_json`
Json::Value params = Json::objectValue;
params[jss::tx_json] = Json::objectValue;
json::Value params = json::ValueType::Object;
params[jss::tx_json] = json::ValueType::Object;
auto const resp = env.rpc("json", "simulate", to_string(params));
BEAST_EXPECT(
@@ -199,17 +223,17 @@ class Simulate_test : public beast::unit_test::suite
}
{
// No tx.Account
Json::Value params = Json::objectValue;
Json::Value tx_json = Json::objectValue;
tx_json[jss::TransactionType] = jss::Payment;
params[jss::tx_json] = tx_json;
json::Value params = json::ValueType::Object;
json::Value txJson = json::ValueType::Object;
txJson[jss::TransactionType] = jss::Payment;
params[jss::tx_json] = txJson;
auto const resp = env.rpc("json", "simulate", to_string(params));
BEAST_EXPECT(resp[jss::result][jss::error_message] == "Missing field 'tx.Account'.");
}
{
// Empty `tx_blob`
Json::Value params = Json::objectValue;
json::Value params = json::ValueType::Object;
params[jss::tx_blob] = "";
auto const resp = env.rpc("json", "simulate", to_string(params));
@@ -217,7 +241,7 @@ class Simulate_test : public beast::unit_test::suite
}
{
// Non-string `tx_blob`
Json::Value params;
json::Value params;
params[jss::tx_blob] = 1.1;
auto const resp = env.rpc("json", "simulate", to_string(params));
@@ -225,7 +249,7 @@ class Simulate_test : public beast::unit_test::suite
}
{
// Non-object `tx_json`
Json::Value params = Json::objectValue;
json::Value params = json::ValueType::Object;
params[jss::tx_json] = "";
auto const resp = env.rpc("json", "simulate", to_string(params));
@@ -234,55 +258,55 @@ class Simulate_test : public beast::unit_test::suite
}
{
// `seed` field included
Json::Value params = Json::objectValue;
json::Value params = json::ValueType::Object;
params[jss::seed] = "random_data";
Json::Value tx_json = Json::objectValue;
tx_json[jss::TransactionType] = jss::AccountSet;
tx_json[jss::Account] = env.master.human();
params[jss::tx_json] = tx_json;
json::Value txJson = json::ValueType::Object;
txJson[jss::TransactionType] = jss::AccountSet;
txJson[jss::Account] = env.master.human();
params[jss::tx_json] = txJson;
auto const resp = env.rpc("json", "simulate", to_string(params));
BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'seed'.");
}
{
// `secret` field included
Json::Value params = Json::objectValue;
json::Value params = json::ValueType::Object;
params[jss::secret] = "random_data";
Json::Value tx_json = Json::objectValue;
tx_json[jss::TransactionType] = jss::AccountSet;
tx_json[jss::Account] = env.master.human();
params[jss::tx_json] = tx_json;
json::Value txJson = json::ValueType::Object;
txJson[jss::TransactionType] = jss::AccountSet;
txJson[jss::Account] = env.master.human();
params[jss::tx_json] = txJson;
auto const resp = env.rpc("json", "simulate", to_string(params));
BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'secret'.");
}
{
// `seed_hex` field included
Json::Value params = Json::objectValue;
json::Value params = json::ValueType::Object;
params[jss::seed_hex] = "random_data";
Json::Value tx_json = Json::objectValue;
tx_json[jss::TransactionType] = jss::AccountSet;
tx_json[jss::Account] = env.master.human();
params[jss::tx_json] = tx_json;
json::Value txJson = json::ValueType::Object;
txJson[jss::TransactionType] = jss::AccountSet;
txJson[jss::Account] = env.master.human();
params[jss::tx_json] = txJson;
auto const resp = env.rpc("json", "simulate", to_string(params));
BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'seed_hex'.");
}
{
// `passphrase` field included
Json::Value params = Json::objectValue;
json::Value params = json::ValueType::Object;
params[jss::passphrase] = "random_data";
Json::Value tx_json = Json::objectValue;
tx_json[jss::TransactionType] = jss::AccountSet;
tx_json[jss::Account] = env.master.human();
params[jss::tx_json] = tx_json;
json::Value txJson = json::ValueType::Object;
txJson[jss::TransactionType] = jss::AccountSet;
txJson[jss::Account] = env.master.human();
params[jss::tx_json] = txJson;
auto const resp = env.rpc("json", "simulate", to_string(params));
BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'passphrase'.");
}
{
// Invalid transaction
Json::Value params = Json::objectValue;
Json::Value tx_json = Json::objectValue;
tx_json[jss::TransactionType] = jss::Payment;
tx_json[jss::Account] = env.master.human();
params[jss::tx_json] = tx_json;
json::Value params = json::ValueType::Object;
json::Value txJson = json::ValueType::Object;
txJson[jss::TransactionType] = jss::Payment;
txJson[jss::Account] = env.master.human();
params[jss::tx_json] = txJson;
auto const resp = env.rpc("json", "simulate", to_string(params));
BEAST_EXPECT(
@@ -291,11 +315,11 @@ class Simulate_test : public beast::unit_test::suite
}
{
// Bad account
Json::Value params;
Json::Value tx_json = Json::objectValue;
tx_json[jss::TransactionType] = jss::AccountSet;
tx_json[jss::Account] = "badAccount";
params[jss::tx_json] = tx_json;
json::Value params;
json::Value txJson = json::ValueType::Object;
txJson[jss::TransactionType] = jss::AccountSet;
txJson[jss::Account] = "badAccount";
params[jss::tx_json] = txJson;
auto const resp = env.rpc("json", "simulate", to_string(params));
BEAST_EXPECTS(
@@ -305,48 +329,48 @@ class Simulate_test : public beast::unit_test::suite
}
{
// Account doesn't exist for Sequence autofill
Json::Value params;
Json::Value tx_json = Json::objectValue;
tx_json[jss::TransactionType] = jss::AccountSet;
tx_json[jss::Account] = alice.human();
params[jss::tx_json] = tx_json;
json::Value params;
json::Value txJson = json::ValueType::Object;
txJson[jss::TransactionType] = jss::AccountSet;
txJson[jss::Account] = alice.human();
params[jss::tx_json] = txJson;
auto const resp = env.rpc("json", "simulate", to_string(params));
BEAST_EXPECT(resp[jss::result][jss::error_message] == "Source account not found.");
}
{
// Invalid Signers field
Json::Value params;
Json::Value tx_json = Json::objectValue;
tx_json[jss::TransactionType] = jss::AccountSet;
tx_json[jss::Account] = env.master.human();
tx_json[sfSigners] = "1";
params[jss::tx_json] = tx_json;
json::Value params;
json::Value txJson = json::ValueType::Object;
txJson[jss::TransactionType] = jss::AccountSet;
txJson[jss::Account] = env.master.human();
txJson[sfSigners] = "1";
params[jss::tx_json] = txJson;
auto const resp = env.rpc("json", "simulate", to_string(params));
BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'tx.Signers'.");
}
{
// Invalid Signers field
Json::Value params;
Json::Value tx_json = Json::objectValue;
tx_json[jss::TransactionType] = jss::AccountSet;
tx_json[jss::Account] = env.master.human();
tx_json[sfSigners] = Json::arrayValue;
tx_json[sfSigners].append("1");
params[jss::tx_json] = tx_json;
json::Value params;
json::Value txJson = json::ValueType::Object;
txJson[jss::TransactionType] = jss::AccountSet;
txJson[jss::Account] = env.master.human();
txJson[sfSigners] = json::ValueType::Array;
txJson[sfSigners].append("1");
params[jss::tx_json] = txJson;
auto const resp = env.rpc("json", "simulate", to_string(params));
BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'tx.Signers[0]'.");
}
{
// Invalid transaction
Json::Value params;
Json::Value tx_json = Json::objectValue;
tx_json[jss::TransactionType] = jss::AccountSet;
tx_json[jss::Account] = env.master.human();
tx_json["foo"] = "bar";
params[jss::tx_json] = tx_json;
json::Value params;
json::Value txJson = json::ValueType::Object;
txJson[jss::TransactionType] = jss::AccountSet;
txJson[jss::Account] = env.master.human();
txJson["foo"] = "bar";
params[jss::tx_json] = txJson;
auto const resp = env.rpc("json", "simulate", to_string(params));
BEAST_EXPECT(
@@ -354,20 +378,20 @@ class Simulate_test : public beast::unit_test::suite
}
{
// non-`"binary"` second param for CLI
Json::Value tx_json = Json::objectValue;
tx_json[jss::TransactionType] = jss::AccountSet;
tx_json[jss::Account] = alice.human();
auto const resp = env.rpc("simulate", to_string(tx_json), "1");
json::Value txJson = json::ValueType::Object;
txJson[jss::TransactionType] = jss::AccountSet;
txJson[jss::Account] = alice.human();
auto const resp = env.rpc("simulate", to_string(txJson), "1");
BEAST_EXPECT(resp[jss::error_message] == "Invalid parameters.");
}
{
// Signed transaction
Json::Value params;
Json::Value tx_json = Json::objectValue;
tx_json[jss::TransactionType] = jss::AccountSet;
tx_json[jss::Account] = env.master.human();
tx_json[jss::TxnSignature] = "1200ABCD";
params[jss::tx_json] = tx_json;
json::Value params;
json::Value txJson = json::ValueType::Object;
txJson[jss::TransactionType] = jss::AccountSet;
txJson[jss::Account] = env.master.human();
txJson[jss::TxnSignature] = "1200ABCD";
params[jss::tx_json] = txJson;
auto const resp = env.rpc("json", "simulate", to_string(params));
BEAST_EXPECT(
@@ -375,21 +399,21 @@ class Simulate_test : public beast::unit_test::suite
}
{
// Signed multisig transaction
Json::Value params;
Json::Value tx_json = Json::objectValue;
tx_json[jss::TransactionType] = jss::AccountSet;
tx_json[jss::Account] = env.master.human();
tx_json[sfSigners] = Json::arrayValue;
json::Value params;
json::Value txJson = json::ValueType::Object;
txJson[jss::TransactionType] = jss::AccountSet;
txJson[jss::Account] = env.master.human();
txJson[sfSigners] = json::ValueType::Array;
{
Json::Value signer;
json::Value signer;
signer[jss::Account] = alice.human();
signer[jss::SigningPubKey] = alice.human();
signer[jss::TxnSignature] = "1200ABCD";
Json::Value signerOuter;
json::Value signerOuter;
signerOuter[sfSigner] = signer;
tx_json[sfSigners].append(signerOuter);
txJson[sfSigners].append(signerOuter);
}
params[jss::tx_json] = tx_json;
params[jss::tx_json] = txJson;
auto const resp = env.rpc("json", "simulate", to_string(params));
BEAST_EXPECT(
@@ -433,7 +457,7 @@ class Simulate_test : public beast::unit_test::suite
env(noop(alice));
{
Json::Value params;
json::Value params;
params[jss::tx_json] = noop(alice);
auto const resp = env.rpc("json", "simulate", to_string(params));
@@ -441,7 +465,7 @@ class Simulate_test : public beast::unit_test::suite
if (BEAST_EXPECT(result.isMember(jss::error)))
{
BEAST_EXPECT(result[jss::error] == "highFee");
BEAST_EXPECT(result[jss::error_code] == rpcHIGH_FEE);
BEAST_EXPECT(result[jss::error_code] == RpcHighFee);
}
}
}
@@ -464,11 +488,11 @@ class Simulate_test : public beast::unit_test::suite
auto const seq = env.seq(alice);
auto jt = env.jtnofill(
batch::outer(alice, env.seq(alice), batchFee, tfAllOrNothing),
batch::inner(pay(alice, bob, XRP(10)), seq + 1),
batch::inner(pay(alice, bob, XRP(10)), seq + 2));
batch::Inner(pay(alice, bob, XRP(10)), seq + 1),
batch::Inner(pay(alice, bob, XRP(10)), seq + 2));
jt.jv.removeMember(jss::TxnSignature);
Json::Value params;
json::Value params;
params[jss::tx_json] = jt.jv;
auto const resp = env.rpc("json", "simulate", to_string(params));
BEAST_EXPECT(resp[jss::result][jss::error] == "notImpl");
@@ -485,10 +509,10 @@ class Simulate_test : public beast::unit_test::suite
cfg->NETWORK_ID = 0;
return cfg;
})};
static auto const newDomain = "123ABC";
static auto const kNewDomain = "123ABC";
{
auto validateOutput = [&](Json::Value const& resp, Json::Value const& tx) {
auto validateOutput = [&](json::Value const& resp, json::Value const& tx) {
auto result = resp[jss::result];
checkBasicReturnValidity(result, tx, 1, env.current()->fees().base);
@@ -500,7 +524,7 @@ class Simulate_test : public beast::unit_test::suite
if (BEAST_EXPECT(result.isMember(jss::meta) || result.isMember(jss::meta_blob)))
{
Json::Value const metadata = getJsonMetadata(result);
json::Value const metadata = getJsonMetadata(result);
if (BEAST_EXPECT(metadata.isMember(sfAffectedNodes.jsonName)))
{
@@ -511,7 +535,7 @@ class Simulate_test : public beast::unit_test::suite
auto modifiedNode = node[sfModifiedNode];
BEAST_EXPECT(modifiedNode[sfLedgerEntryType] == "AccountRoot");
auto finalFields = modifiedNode[sfFinalFields];
BEAST_EXPECT(finalFields[sfDomain] == newDomain);
BEAST_EXPECT(finalFields[sfDomain] == kNewDomain);
}
}
BEAST_EXPECT(metadata[sfTransactionIndex.jsonName] == 0);
@@ -519,11 +543,11 @@ class Simulate_test : public beast::unit_test::suite
}
};
Json::Value tx;
json::Value tx;
tx[jss::Account] = env.master.human();
tx[jss::TransactionType] = jss::AccountSet;
tx[sfDomain] = newDomain;
tx[sfDomain] = kNewDomain;
// test with autofill
testTx(env, tx, validateOutput);
@@ -548,8 +572,8 @@ class Simulate_test : public beast::unit_test::suite
Account const alice("alice");
{
std::function<void(Json::Value const&, Json::Value const&)> const& testSimulation =
[&](Json::Value const& resp, Json::Value const& tx) {
std::function<void(json::Value const&, json::Value const&)> const& testSimulation =
[&](json::Value const& resp, json::Value const& tx) {
auto result = resp[jss::result];
checkBasicReturnValidity(result, tx, 1, env.current()->fees().base);
@@ -560,7 +584,7 @@ class Simulate_test : public beast::unit_test::suite
BEAST_EXPECT(!result.isMember(jss::meta) && !result.isMember(jss::meta_blob));
};
Json::Value tx;
json::Value tx;
tx[jss::Account] = env.master.human();
tx[jss::TransactionType] = jss::Payment;
@@ -590,8 +614,8 @@ class Simulate_test : public beast::unit_test::suite
Account const alice("alice");
{
std::function<void(Json::Value const&, Json::Value const&)> const& testSimulation =
[&](Json::Value const& resp, Json::Value const& tx) {
std::function<void(json::Value const&, json::Value const&)> const& testSimulation =
[&](json::Value const& resp, json::Value const& tx) {
auto result = resp[jss::result];
checkBasicReturnValidity(result, tx, 1, env.current()->fees().base);
@@ -605,7 +629,7 @@ class Simulate_test : public beast::unit_test::suite
if (BEAST_EXPECT(result.isMember(jss::meta) || result.isMember(jss::meta_blob)))
{
Json::Value const metadata = getJsonMetadata(result);
json::Value const metadata = getJsonMetadata(result);
if (BEAST_EXPECT(metadata.isMember(sfAffectedNodes.jsonName)))
{
@@ -629,7 +653,7 @@ class Simulate_test : public beast::unit_test::suite
}
};
Json::Value tx;
json::Value tx;
tx[jss::Account] = env.master.human();
tx[jss::TransactionType] = jss::Payment;
@@ -656,7 +680,7 @@ class Simulate_test : public beast::unit_test::suite
using namespace jtx;
Env env(*this);
static auto const newDomain = "123ABC";
static auto const kNewDomain = "123ABC";
Account const alice("alice");
Account const becky("becky");
Account const carol("carol");
@@ -668,7 +692,7 @@ class Simulate_test : public beast::unit_test::suite
env.close();
{
auto validateOutput = [&](Json::Value const& resp, Json::Value const& tx) {
auto validateOutput = [&](json::Value const& resp, json::Value const& tx) {
auto result = resp[jss::result];
checkBasicReturnValidity(
result,
@@ -685,7 +709,7 @@ class Simulate_test : public beast::unit_test::suite
if (BEAST_EXPECT(result.isMember(jss::meta) || result.isMember(jss::meta_blob)))
{
Json::Value const metadata = getJsonMetadata(result);
json::Value const metadata = getJsonMetadata(result);
if (BEAST_EXPECT(metadata.isMember(sfAffectedNodes.jsonName)))
{
@@ -696,7 +720,7 @@ class Simulate_test : public beast::unit_test::suite
auto modifiedNode = node[sfModifiedNode];
BEAST_EXPECT(modifiedNode[sfLedgerEntryType] == "AccountRoot");
auto finalFields = modifiedNode[sfFinalFields];
BEAST_EXPECT(finalFields[sfDomain] == newDomain);
BEAST_EXPECT(finalFields[sfDomain] == kNewDomain);
}
}
BEAST_EXPECT(metadata[sfTransactionIndex.jsonName] == 0);
@@ -704,20 +728,20 @@ class Simulate_test : public beast::unit_test::suite
}
};
Json::Value tx;
json::Value tx;
tx[jss::Account] = alice.human();
tx[jss::TransactionType] = jss::AccountSet;
tx[sfDomain] = newDomain;
tx[sfDomain] = kNewDomain;
// test with autofill
testTx(env, tx, validateOutput, false);
tx[sfSigners] = Json::arrayValue;
tx[sfSigners] = json::ValueType::Array;
{
Json::Value signer;
json::Value signer;
signer[jss::Account] = becky.human();
Json::Value signerOuter;
json::Value signerOuter;
signerOuter[sfSigner] = signer;
tx[sfSigners].append(signerOuter);
}
@@ -745,15 +769,15 @@ class Simulate_test : public beast::unit_test::suite
using namespace jtx;
Env env(*this);
static auto const newDomain = "123ABC";
static auto const kNewDomain = "123ABC";
Account const alice{"alice"};
env(regkey(env.master, alice));
env(fset(env.master, asfDisableMaster), sig(env.master));
env(fset(env.master, asfDisableMaster), Sig(env.master));
env.close();
{
std::function<void(Json::Value const&, Json::Value const&)> const& testSimulation =
[&](Json::Value const& resp, Json::Value const& tx) {
std::function<void(json::Value const&, json::Value const&)> const& testSimulation =
[&](json::Value const& resp, json::Value const& tx) {
auto result = resp[jss::result];
checkBasicReturnValidity(
result, tx, env.seq(env.master), env.current()->fees().base);
@@ -765,11 +789,11 @@ class Simulate_test : public beast::unit_test::suite
BEAST_EXPECT(!result.isMember(jss::meta) && !result.isMember(jss::meta_blob));
};
Json::Value tx;
json::Value tx;
tx[jss::Account] = env.master.human();
tx[jss::TransactionType] = jss::AccountSet;
tx[sfDomain] = newDomain;
tx[sfDomain] = kNewDomain;
// master key is disabled, so this is invalid
tx[jss::SigningPubKey] = strHex(env.master.pk().slice());
@@ -794,7 +818,7 @@ class Simulate_test : public beast::unit_test::suite
using namespace jtx;
Env env(*this);
static auto const newDomain = "123ABC";
static auto const kNewDomain = "123ABC";
Account const alice("alice");
Account const becky("becky");
Account const carol("carol");
@@ -806,8 +830,8 @@ class Simulate_test : public beast::unit_test::suite
env.close();
{
std::function<void(Json::Value const&, Json::Value const&)> const& testSimulation =
[&](Json::Value const& resp, Json::Value const& tx) {
std::function<void(json::Value const&, json::Value const&)> const& testSimulation =
[&](json::Value const& resp, json::Value const& tx) {
auto result = resp[jss::result];
checkBasicReturnValidity(
result, tx, env.seq(env.master), env.current()->fees().base * 2);
@@ -820,18 +844,18 @@ class Simulate_test : public beast::unit_test::suite
BEAST_EXPECT(!result.isMember(jss::meta) && !result.isMember(jss::meta_blob));
};
Json::Value tx;
json::Value tx;
tx[jss::Account] = env.master.human();
tx[jss::TransactionType] = jss::AccountSet;
tx[sfDomain] = newDomain;
tx[sfDomain] = kNewDomain;
// master key is disabled, so this is invalid
tx[jss::SigningPubKey] = strHex(env.master.pk().slice());
tx[sfSigners] = Json::arrayValue;
tx[sfSigners] = json::ValueType::Array;
{
Json::Value signer;
json::Value signer;
signer[jss::Account] = becky.human();
Json::Value signerOuter;
json::Value signerOuter;
signerOuter[sfSigner] = signer;
tx[sfSigners].append(signerOuter);
}
@@ -857,7 +881,7 @@ class Simulate_test : public beast::unit_test::suite
using namespace jtx;
Env env(*this);
static auto const newDomain = "123ABC";
static auto const kNewDomain = "123ABC";
Account const alice("alice");
Account const becky("becky");
Account const carol("carol");
@@ -869,7 +893,7 @@ class Simulate_test : public beast::unit_test::suite
env(signers(alice, 1, {{becky, 1}, {carol, 1}}));
{
auto validateOutput = [&](Json::Value const& resp, Json::Value const& tx) {
auto validateOutput = [&](json::Value const& resp, json::Value const& tx) {
auto result = resp[jss::result];
checkBasicReturnValidity(
result, tx, env.seq(alice), env.current()->fees().base * 2);
@@ -885,17 +909,17 @@ class Simulate_test : public beast::unit_test::suite
BEAST_EXPECT(!result.isMember(jss::meta) && !result.isMember(jss::meta_blob));
};
Json::Value tx;
json::Value tx;
tx[jss::Account] = alice.human();
tx[jss::TransactionType] = jss::AccountSet;
tx[sfDomain] = newDomain;
tx[sfSigners] = Json::arrayValue;
tx[sfDomain] = kNewDomain;
tx[sfSigners] = json::ValueType::Array;
{
Json::Value signer;
json::Value signer;
signer[jss::Account] = becky.human();
signer[jss::SigningPubKey] = strHex(dylan.pk().slice());
Json::Value signerOuter;
json::Value signerOuter;
signerOuter[sfSigner] = signer;
tx[sfSigners].append(signerOuter);
}
@@ -940,7 +964,7 @@ class Simulate_test : public beast::unit_test::suite
env.close();
{
auto validateOutput = [&](Json::Value const& resp, Json::Value const& tx) {
auto validateOutput = [&](json::Value const& resp, json::Value const& tx) {
auto result = resp[jss::result];
checkBasicReturnValidity(result, tx, env.seq(subject), env.current()->fees().base);
@@ -950,7 +974,7 @@ class Simulate_test : public beast::unit_test::suite
if (BEAST_EXPECT(result.isMember(jss::meta) || result.isMember(jss::meta_blob)))
{
Json::Value const metadata = getJsonMetadata(result);
json::Value const metadata = getJsonMetadata(result);
if (BEAST_EXPECT(metadata.isMember(sfAffectedNodes.jsonName)))
{
@@ -986,7 +1010,7 @@ class Simulate_test : public beast::unit_test::suite
}
};
Json::Value tx = credentials::accept(subject, issuer, credType);
json::Value tx = credentials::accept(subject, issuer, credType);
// test with autofill
testTx(env, tx, validateOutput);
@@ -1025,10 +1049,10 @@ class Simulate_test : public beast::unit_test::suite
cfg->NETWORK_ID = 1025;
return cfg;
})};
static auto const newDomain = "123ABC";
static auto const kNewDomain = "123ABC";
{
auto validateOutput = [&](Json::Value const& resp, Json::Value const& tx) {
auto validateOutput = [&](json::Value const& resp, json::Value const& tx) {
auto result = resp[jss::result];
checkBasicReturnValidity(result, tx, 1, env.current()->fees().base);
@@ -1040,7 +1064,7 @@ class Simulate_test : public beast::unit_test::suite
if (BEAST_EXPECT(result.isMember(jss::meta) || result.isMember(jss::meta_blob)))
{
Json::Value const metadata = getJsonMetadata(result);
json::Value const metadata = getJsonMetadata(result);
if (BEAST_EXPECT(metadata.isMember(sfAffectedNodes.jsonName)))
{
@@ -1051,7 +1075,7 @@ class Simulate_test : public beast::unit_test::suite
auto modifiedNode = node[sfModifiedNode];
BEAST_EXPECT(modifiedNode[sfLedgerEntryType] == "AccountRoot");
auto finalFields = modifiedNode[sfFinalFields];
BEAST_EXPECT(finalFields[sfDomain] == newDomain);
BEAST_EXPECT(finalFields[sfDomain] == kNewDomain);
}
}
BEAST_EXPECT(metadata[sfTransactionIndex.jsonName] == 0);
@@ -1059,11 +1083,11 @@ class Simulate_test : public beast::unit_test::suite
}
};
Json::Value tx;
json::Value tx;
tx[jss::Account] = env.master.human();
tx[jss::TransactionType] = jss::AccountSet;
tx[sfDomain] = newDomain;
tx[sfDomain] = kNewDomain;
// test with autofill
testTx(env, tx, validateOutput);
@@ -1101,10 +1125,10 @@ class Simulate_test : public beast::unit_test::suite
env.close(NetClock::time_point{446000000s});
{
auto validateOutput = [&](Json::Value const& resp,
Json::Value const& tx,
Json::Value const& expectedMetadataKey,
Json::Value const& expectedMetadataValue) {
auto validateOutput = [&](json::Value const& resp,
json::Value const& tx,
json::Value const& expectedMetadataKey,
json::Value const& expectedMetadataValue) {
auto result = resp[jss::result];
BEAST_EXPECT(result[jss::engine_result] == "tesSUCCESS");
@@ -1115,7 +1139,7 @@ class Simulate_test : public beast::unit_test::suite
if (BEAST_EXPECT(result.isMember(jss::meta) || result.isMember(jss::meta_blob)))
{
Json::Value const metadata = getJsonMetadata(result);
json::Value const metadata = getJsonMetadata(result);
BEAST_EXPECT(metadata[sfTransactionIndex.jsonName] == 0);
BEAST_EXPECT(metadata[sfTransactionResult.jsonName] == "tesSUCCESS");
@@ -1125,7 +1149,7 @@ class Simulate_test : public beast::unit_test::suite
};
{
Json::Value tx;
json::Value tx;
tx[jss::Account] = alice.human();
tx[jss::TransactionType] = jss::Payment;
tx[sfDestination] = bob.human();
@@ -1136,22 +1160,22 @@ class Simulate_test : public beast::unit_test::suite
}
{
Json::Value tx;
json::Value tx;
tx[jss::Account] = alice.human();
tx[jss::TransactionType] = jss::NFTokenMint;
tx[sfNFTokenTaxon] = 1;
Json::Value const nftokenId = to_string(token::getNextID(env, alice, 1));
json::Value const nftokenId = to_string(token::getNextID(env, alice, 1));
// test nft synthetic
testTxJsonMetadataField(env, tx, validateOutput, jss::nftoken_id, nftokenId);
}
{
Json::Value tx;
json::Value tx;
tx[jss::Account] = alice.human();
tx[jss::TransactionType] = jss::MPTokenIssuanceCreate;
Json::Value const mptIssuanceId = to_string(makeMptID(env.seq(alice), alice));
json::Value const mptIssuanceId = to_string(makeMptID(env.seq(alice), alice));
// test mpt issuance id
testTxJsonMetadataField(
env, tx, validateOutput, jss::mpt_issuance_id, mptIssuanceId);
@@ -1181,6 +1205,4 @@ public:
BEAST_DEFINE_TESTSUITE(Simulate, rpc, xrpl);
} // namespace test
} // namespace xrpl
} // namespace xrpl::test