fixInnerObjTemplate2 amendment (#5047)

* fixInnerObjTemplate2 amendment:

Apply inner object templates to all remaining (non-AMM)
inner objects.

Adds a unit test for applying the template to sfMajorities.
Other remaining inner objects showed no problems having
templates applied.

* Move CMake directory

* Rearrange sources

* Rewrite includes

* Recompute loops

---------

Co-authored-by: Pretty Printer <cpp@ripple.com>
This commit is contained in:
Scott Schurr
2024-06-27 11:52:02 -07:00
committed by tequ
parent 95e16b0eed
commit 463dd92c9e
12 changed files with 347 additions and 321 deletions

View File

@@ -80,7 +80,7 @@ namespace detail {
// Feature.cpp. Because it's only used to reserve storage, and determine how // Feature.cpp. Because it's only used to reserve storage, and determine how
// large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than // large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than
// the actual number of amendments. A LogicError on startup will verify this. // the actual number of amendments. A LogicError on startup will verify this.
static constexpr std::size_t numFeatures = 99; static constexpr std::size_t numFeatures = 100;
/** Amendments that this server supports and the default voting behavior. /** Amendments that this server supports and the default voting behavior.
Whether they are enabled depends on the Rules defined in the validated Whether they are enabled depends on the Rules defined in the validated
@@ -393,6 +393,7 @@ extern uint256 const fixAMMv1_1;
extern uint256 const featureNFTokenMintOffer; extern uint256 const featureNFTokenMintOffer;
extern uint256 const fixReducedOffersV2; extern uint256 const fixReducedOffersV2;
extern uint256 const fixEnforceNFTokenTrustline; extern uint256 const fixEnforceNFTokenTrustline;
extern uint256 const fixInnerObjTemplate2;
} // namespace ripple } // namespace ripple

View File

@@ -44,7 +44,6 @@
namespace ripple { namespace ripple {
class STArray; class STArray;
class Rules;
inline void inline void
throwFieldNotFound(SField const& field) throwFieldNotFound(SField const& field)
@@ -105,7 +104,7 @@ public:
explicit STObject(SField const& name); explicit STObject(SField const& name);
static STObject static STObject
makeInnerObject(SField const& name, Rules const& rules); makeInnerObject(SField const& name);
iterator iterator
begin() const; begin() const;

View File

@@ -519,6 +519,7 @@ REGISTER_FIX (fixAMMv1_1, Supported::yes, VoteBehavior::De
REGISTER_FEATURE(NFTokenMintOffer, Supported::yes, VoteBehavior::DefaultNo); REGISTER_FEATURE(NFTokenMintOffer, Supported::yes, VoteBehavior::DefaultNo);
REGISTER_FIX (fixReducedOffersV2, Supported::yes, VoteBehavior::DefaultNo); REGISTER_FIX (fixReducedOffersV2, Supported::yes, VoteBehavior::DefaultNo);
REGISTER_FIX (fixEnforceNFTokenTrustline, Supported::yes, VoteBehavior::DefaultNo); REGISTER_FIX (fixEnforceNFTokenTrustline, Supported::yes, VoteBehavior::DefaultNo);
REGISTER_FIX (fixInnerObjTemplate2, Supported::yes, VoteBehavior::DefaultNo);
// The following amendments are obsolete, but must remain supported // The following amendments are obsolete, but must remain supported
// because they could potentially get enabled. // because they could potentially get enabled.

View File

@@ -61,10 +61,19 @@ STObject::STObject(SerialIter& sit, SField const& name, int depth) noexcept(
} }
STObject STObject
STObject::makeInnerObject(SField const& name, Rules const& rules) STObject::makeInnerObject(SField const& name)
{ {
STObject obj{name}; STObject obj{name};
if (rules.enabled(fixInnerObjTemplate))
// The if is complicated because inner object templates were added in
// two phases:
// 1. If there are no available Rules, then always apply the template.
// 2. fixInnerObjTemplate added templates to two AMM inner objects.
// 3. fixInnerObjTemplate2 added templates to all remaining inner objects.
std::optional<Rules> const& rules = getCurrentTransactionRules();
bool const isAMMObj = name == sfAuctionSlot || name == sfVoteEntry;
if (!rules || (rules->enabled(fixInnerObjTemplate) && isAMMObj) ||
(rules->enabled(fixInnerObjTemplate2) && !isAMMObj))
{ {
if (SOTemplate const* elements = if (SOTemplate const* elements =
InnerObjectFormats::getInstance().findSOTemplateBySField(name)) InnerObjectFormats::getInstance().findSOTemplateBySField(name))

View File

@@ -203,7 +203,8 @@ AttestationClaim::AttestationClaim(Json::Value const& v)
STObject STObject
AttestationClaim::toSTObject() const AttestationClaim::toSTObject() const
{ {
STObject o{sfXChainClaimAttestationCollectionElement}; STObject o =
STObject::makeInnerObject(sfXChainClaimAttestationCollectionElement);
addHelper(o); addHelper(o);
o[sfXChainClaimID] = claimID; o[sfXChainClaimID] = claimID;
if (dst) if (dst)
@@ -345,7 +346,8 @@ AttestationCreateAccount::AttestationCreateAccount(
STObject STObject
AttestationCreateAccount::toSTObject() const AttestationCreateAccount::toSTObject() const
{ {
STObject o{sfXChainCreateAccountAttestationCollectionElement}; STObject o = STObject::makeInnerObject(
sfXChainCreateAccountAttestationCollectionElement);
addHelper(o); addHelper(o);
o[sfXChainAccountCreateCount] = createCount; o[sfXChainAccountCreateCount] = createCount;
@@ -497,7 +499,7 @@ XChainClaimAttestation::XChainClaimAttestation(
STObject STObject
XChainClaimAttestation::toSTObject() const XChainClaimAttestation::toSTObject() const
{ {
STObject o{sfXChainClaimProofSig}; STObject o = STObject::makeInnerObject(sfXChainClaimProofSig);
o[sfAttestationSignerAccount] = o[sfAttestationSignerAccount] =
STAccount{sfAttestationSignerAccount, keyAccount}; STAccount{sfAttestationSignerAccount, keyAccount};
o[sfPublicKey] = publicKey; o[sfPublicKey] = publicKey;
@@ -609,7 +611,7 @@ XChainCreateAccountAttestation::XChainCreateAccountAttestation(
STObject STObject
XChainCreateAccountAttestation::toSTObject() const XChainCreateAccountAttestation::toSTObject() const
{ {
STObject o{sfXChainCreateAccountProofSig}; STObject o = STObject::makeInnerObject(sfXChainCreateAccountProofSig);
o[sfAttestationSignerAccount] = o[sfAttestationSignerAccount] =
STAccount{sfAttestationSignerAccount, keyAccount}; STAccount{sfAttestationSignerAccount, keyAccount};

View File

@@ -303,339 +303,353 @@ public:
{ {
// Put a bunch of different LedgerEntryTypes into a ledger // Put a bunch of different LedgerEntryTypes into a ledger
using namespace test::jtx; using namespace test::jtx;
using namespace std::chrono;
std::vector<std::string> const keys = { // Make sure fixInnerObjTemplate2 doesn't break amendments.
"ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1CDC" for (FeatureBitset const& features :
"1"}; {supported_amendments() - fixInnerObjTemplate2,
Env env{*this, network::makeNetworkVLConfig(21337, keys)}; supported_amendments() | fixInnerObjTemplate2})
Account const alice{"alice"};
Account const gw{"gateway"};
auto const USD = gw["USD"];
env.fund(XRP(100000), gw, alice);
auto makeRequest = [&env](Json::StaticString const& type) {
Json::Value jvParams;
jvParams[jss::ledger_index] = "current";
jvParams[jss::type] = type;
return env.rpc(
"json",
"ledger_data",
boost::lexical_cast<std::string>(jvParams))[jss::result];
};
// Assert that state is an empty array.
for (auto const& type :
{jss::amendments,
jss::check,
jss::directory,
jss::offer,
jss::signer_list,
jss::state,
jss::ticket,
jss::escrow,
jss::payment_channel,
jss::hook,
jss::hook_definition,
jss::hook_state,
jss::uri_token,
jss::deposit_preauth})
{ {
auto const jrr = makeRequest(type); using namespace std::chrono;
BEAST_EXPECT(checkArraySize(jrr[jss::state], 0));
}
int const num_accounts = 10; std::vector<std::string> const keys = {
for (auto i = 0; i < num_accounts; i++)
{
Account const bob{std::string("bob") + std::to_string(i)};
env.fund(XRP(1000), bob);
}
env(offer(Account{"bob0"}, USD(100), XRP(100)));
env.trust(Account{"bob2"}["USD"](100), Account{"bob3"});
auto majorities = getMajorityAmendments(*env.closed());
for (int i = 0; i <= 256; ++i)
{
env.close();
majorities = getMajorityAmendments(*env.closed());
if (!majorities.empty())
break;
}
env(signers(
Account{"bob0"}, 1, {{Account{"bob1"}, 1}, {Account{"bob2"}, 1}}));
env(ticket::create(env.master, 1));
{
Json::Value jv;
jv[jss::TransactionType] = jss::EscrowCreate;
jv[jss::Flags] = tfUniversal;
jv[jss::Account] = Account{"bob5"}.human();
jv[jss::Destination] = Account{"bob6"}.human();
jv[jss::Amount] = XRP(50).value().getJson(JsonOptions::none);
jv[sfFinishAfter.fieldName] = NetClock::time_point{env.now() + 10s}
.time_since_epoch()
.count();
env(jv);
}
{
std::string const createCodeHex =
"0061736D01000000011B0460027F7F017F60047F7F7F7F017E60037F7F7E01"
"7E60017F017E02270303656E76025F67000003656E760973746174655F7365"
"74000103656E76066163636570740002030201030503010002062B077F0141"
"9088040B7F004180080B7F00418A080B7F004180080B7F00419088040B7F00"
"41000B7F0041010B07080104686F6F6B00030AE7800001E3800002017F017E"
"230041106B220124002001200036020C41012200200010001A200141800828"
"0000360208200141046A410022002F0088083B010020012000280084083602"
"004100200020014106200141086A4104100110022102200141106A24002002"
"0B0B1001004180080B096B65790076616C7565";
std::string ns_str =
"CAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECA"
"FE";
Json::Value jv = ripple::test::jtx::hook(
Account{"bob3"}, {{hso(createCodeHex)}}, 0);
jv[jss::Hooks][0U][jss::Hook][jss::HookNamespace] = ns_str;
env(jv, fee(100'000'000));
env.close();
env(pay(Account{"bob2"}, Account{"bob3"}, XRP(1)), fee(XRP(1)));
env.close();
}
{
std::string const uri(maxTokenURILength, '?');
env(uritoken::mint(Account{"bob2"}, uri));
env.close();
}
{
Json::Value jv;
jv[jss::TransactionType] = jss::PaymentChannelCreate;
jv[jss::Flags] = tfUniversal;
jv[jss::Account] = Account{"bob6"}.human();
jv[jss::Destination] = Account{"bob7"}.human();
jv[jss::Amount] = XRP(100).value().getJson(JsonOptions::none);
jv[jss::SettleDelay] = NetClock::duration{10s}.count();
jv[sfPublicKey.fieldName] = strHex(Account{"bob6"}.pk().slice());
jv[sfCancelAfter.fieldName] = NetClock::time_point{env.now() + 300s}
.time_since_epoch()
.count();
env(jv);
}
{
auto const master = Account("masterpassphrase");
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
env.close();
env(import::import(
alice, import::loadXpop(test::ImportTCAccountSet::w_seed)),
fee(10 * 10),
ter(tesSUCCESS));
env.close();
}
{
// ADD UNL REPORT
std::vector<std::string> const _ivlKeys = {
"ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1" "ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1"
"CDC1", "CDC1"};
"ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1" Env env{*this, network::makeNetworkVLConfig(21337, keys), features};
"CDC2",
Account const alice{"alice"};
Account const gw{"gateway"};
auto const USD = gw["USD"];
env.fund(XRP(100000), gw, alice);
auto makeRequest = [&env](Json::StaticString const& type) {
Json::Value jvParams;
jvParams[jss::ledger_index] = "current";
jvParams[jss::type] = type;
return env.rpc(
"json",
"ledger_data",
boost::lexical_cast<std::string>(jvParams))[jss::result];
}; };
std::vector<PublicKey> ivlKeys; // Assert that state is an empty array.
for (auto const& strPk : _ivlKeys) for (auto const& type :
{jss::amendments,
jss::check,
jss::directory,
jss::offer,
jss::signer_list,
jss::state,
jss::ticket,
jss::escrow,
jss::payment_channel,
jss::hook,
jss::hook_definition,
jss::hook_state,
jss::uri_token,
jss::deposit_preauth})
{ {
auto pkHex = strUnHex(strPk); auto const jrr = makeRequest(type);
ivlKeys.emplace_back(makeSlice(*pkHex)); BEAST_EXPECT(checkArraySize(jrr[jss::state], 0));
} }
std::vector<std::string> const _vlKeys = { int const num_accounts = 10;
"ED8E43A943A174190BA2FAE91F44AC6E2D1D8202EFDCC2EA3DBB39814576D6"
"90F7",
"ED45D1840EE724BE327ABE9146503D5848EFD5F38B6D5FEDE71E80ACCE5E6E"
"738B"};
std::vector<PublicKey> vlKeys; for (auto i = 0; i < num_accounts; i++)
for (auto const& strPk : _vlKeys)
{ {
auto pkHex = strUnHex(strPk); Account const bob{std::string("bob") + std::to_string(i)};
vlKeys.emplace_back(makeSlice(*pkHex)); env.fund(XRP(1000), bob);
}
env(offer(Account{"bob0"}, USD(100), XRP(100)));
env.trust(Account{"bob2"}["USD"](100), Account{"bob3"});
auto majorities = getMajorityAmendments(*env.closed());
for (int i = 0; i <= 256; ++i)
{
env.close();
majorities = getMajorityAmendments(*env.closed());
if (!majorities.empty())
break;
} }
// insert a ttUNL_REPORT pseudo into the open ledger env(signers(
env.app().openLedger().modify( Account{"bob0"},
[&](OpenView& view, beast::Journal j) -> bool { 1,
STTx tx = test::unl::createUNLReportTx( {{Account{"bob1"}, 1}, {Account{"bob2"}, 1}}));
env.current()->seq() + 1, ivlKeys[0], vlKeys[0]); env(ticket::create(env.master, 1));
uint256 txID = tx.getTransactionID();
auto s = std::make_shared<ripple::Serializer>();
tx.add(*s);
env.app().getHashRouter().setFlags(txID, SF_PRIVATE2);
view.rawTxInsert(txID, std::move(s), nullptr);
return true;
});
// close the ledger {
Json::Value jv;
jv[jss::TransactionType] = jss::EscrowCreate;
jv[jss::Flags] = tfUniversal;
jv[jss::Account] = Account{"bob5"}.human();
jv[jss::Destination] = Account{"bob6"}.human();
jv[jss::Amount] = XRP(50).value().getJson(JsonOptions::none);
jv[sfFinishAfter.fieldName] =
NetClock::time_point{env.now() + 10s}
.time_since_epoch()
.count();
env(jv);
}
{
std::string const createCodeHex =
"0061736D01000000011B0460027F7F017F60047F7F7F7F017E60037F7F"
"7E017E60017F017E02270303656E76025F67000003656E760973746174"
"655F736574000103656E76066163636570740002030201030503010002"
"062B077F01419088040B7F004180080B7F00418A080B7F004180080B7F"
"00419088040B7F0041000B7F0041010B07080104686F6F6B00030AE780"
"0001E3800002017F017E230041106B220124002001200036020C410122"
"00200010001A2001418008280000360208200141046A410022002F0088"
"083B010020012000280084083602004100200020014106200141086A41"
"04100110022102200141106A240020020B0B1001004180080B096B6579"
"0076616C7565";
std::string ns_str =
"CAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECA"
"FECAFE";
Json::Value jv = ripple::test::jtx::hook(
Account{"bob3"}, {{hso(createCodeHex)}}, 0);
jv[jss::Hooks][0U][jss::Hook][jss::HookNamespace] = ns_str;
env(jv, fee(100'000'000));
env.close();
env(pay(Account{"bob2"}, Account{"bob3"}, XRP(1)), fee(XRP(1)));
env.close();
}
{
std::string const uri(maxTokenURILength, '?');
env(uritoken::mint(Account{"bob2"}, uri));
env.close();
}
{
Json::Value jv;
jv[jss::TransactionType] = jss::PaymentChannelCreate;
jv[jss::Flags] = tfUniversal;
jv[jss::Account] = Account{"bob6"}.human();
jv[jss::Destination] = Account{"bob7"}.human();
jv[jss::Amount] = XRP(100).value().getJson(JsonOptions::none);
jv[jss::SettleDelay] = NetClock::duration{10s}.count();
jv[sfPublicKey.fieldName] =
strHex(Account{"bob6"}.pk().slice());
jv[sfCancelAfter.fieldName] =
NetClock::time_point{env.now() + 300s}
.time_since_epoch()
.count();
env(jv);
}
{
auto const master = Account("masterpassphrase");
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
env.close();
env(import::import(
alice,
import::loadXpop(test::ImportTCAccountSet::w_seed)),
fee(10 * 10),
ter(tesSUCCESS));
env.close();
}
{
// ADD UNL REPORT
std::vector<std::string> const _ivlKeys = {
"ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9"
"D5A1CDC1",
"ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9"
"D5A1CDC2",
};
std::vector<PublicKey> ivlKeys;
for (auto const& strPk : _ivlKeys)
{
auto pkHex = strUnHex(strPk);
ivlKeys.emplace_back(makeSlice(*pkHex));
}
std::vector<std::string> const _vlKeys = {
"ED8E43A943A174190BA2FAE91F44AC6E2D1D8202EFDCC2EA3DBB398145"
"76D690F7",
"ED45D1840EE724BE327ABE9146503D5848EFD5F38B6D5FEDE71E80ACCE"
"5E6E738B"};
std::vector<PublicKey> vlKeys;
for (auto const& strPk : _vlKeys)
{
auto pkHex = strUnHex(strPk);
vlKeys.emplace_back(makeSlice(*pkHex));
}
// insert a ttUNL_REPORT pseudo into the open ledger
env.app().openLedger().modify(
[&](OpenView& view, beast::Journal j) -> bool {
STTx tx = test::unl::createUNLReportTx(
env.current()->seq() + 1, ivlKeys[0], vlKeys[0]);
uint256 txID = tx.getTransactionID();
auto s = std::make_shared<ripple::Serializer>();
tx.add(*s);
env.app().getHashRouter().setFlags(txID, SF_PRIVATE2);
view.rawTxInsert(txID, std::move(s), nullptr);
return true;
});
// close the ledger
env.close();
}
env(check::create("bob6", "bob7", XRP(100)));
// bob9 DepositPreauths bob4 and bob8.
env(deposit::auth(Account{"bob9"}, Account{"bob4"}));
env(deposit::auth(Account{"bob9"}, Account{"bob8"}));
env.close(); env.close();
}
env(check::create("bob6", "bob7", XRP(100))); // Now fetch each type
// bob9 DepositPreauths bob4 and bob8. { // jvParams[jss::type] = "account";
env(deposit::auth(Account{"bob9"}, Account{"bob4"})); auto const jrr = makeRequest(jss::account);
env(deposit::auth(Account{"bob9"}, Account{"bob8"})); BEAST_EXPECT(checkArraySize(jrr[jss::state], 13));
env.close(); for (auto const& j : jrr[jss::state])
BEAST_EXPECT(j["LedgerEntryType"] == jss::AccountRoot);
}
// Now fetch each type { // jvParams[jss::type] = "amendments";
auto const jrr = makeRequest(jss::amendments);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 0));
for (auto const& j : jrr[jss::state])
BEAST_EXPECT(j["LedgerEntryType"] == jss::Amendments);
}
{ // jvParams[jss::type] = "account"; { // jvParams[jss::type] = "unl_report";
auto const jrr = makeRequest(jss::account); auto const jrr = makeRequest(jss::unl_report);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 13)); BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
for (auto const& j : jrr[jss::state]) for (auto const& j : jrr[jss::state])
BEAST_EXPECT(j["LedgerEntryType"] == jss::AccountRoot); BEAST_EXPECT(j["LedgerEntryType"] == jss::UNLReport);
} }
{ // jvParams[jss::type] = "amendments"; { // jvParams[jss::type] = "check";
auto const jrr = makeRequest(jss::amendments); auto const jrr = makeRequest(jss::check);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 0)); BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
for (auto const& j : jrr[jss::state]) for (auto const& j : jrr[jss::state])
BEAST_EXPECT(j["LedgerEntryType"] == jss::Amendments); BEAST_EXPECT(j["LedgerEntryType"] == jss::Check);
} }
{ // jvParams[jss::type] = "unl_report"; { // jvParams[jss::type] = "directory";
auto const jrr = makeRequest(jss::unl_report); auto const jrr = makeRequest(jss::directory);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 1)); BEAST_EXPECT(checkArraySize(jrr[jss::state], 10));
for (auto const& j : jrr[jss::state])
BEAST_EXPECT(j["LedgerEntryType"] == jss::DirectoryNode);
}
for (auto const& j : jrr[jss::state]) { // jvParams[jss::type] = "fee";
BEAST_EXPECT(j["LedgerEntryType"] == jss::UNLReport); auto const jrr = makeRequest(jss::fee);
} BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
for (auto const& j : jrr[jss::state])
BEAST_EXPECT(j["LedgerEntryType"] == jss::FeeSettings);
}
{ // jvParams[jss::type] = "check"; { // jvParams[jss::type] = "hashes";
auto const jrr = makeRequest(jss::check); auto const jrr = makeRequest(jss::hashes);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 1)); BEAST_EXPECT(checkArraySize(jrr[jss::state], 2));
for (auto const& j : jrr[jss::state]) for (auto const& j : jrr[jss::state])
BEAST_EXPECT(j["LedgerEntryType"] == jss::Check); BEAST_EXPECT(j["LedgerEntryType"] == jss::LedgerHashes);
} }
{ // jvParams[jss::type] = "directory"; { // jvParams[jss::type] = "import_vlseq";
auto const jrr = makeRequest(jss::directory); auto const jrr = makeRequest(jss::import_vlseq);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 10)); BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
for (auto const& j : jrr[jss::state]) for (auto const& j : jrr[jss::state])
BEAST_EXPECT(j["LedgerEntryType"] == jss::DirectoryNode); BEAST_EXPECT(j["LedgerEntryType"] == jss::ImportVLSequence);
} }
{ // jvParams[jss::type] = "fee"; { // jvParams[jss::type] = "offer";
auto const jrr = makeRequest(jss::fee); auto const jrr = makeRequest(jss::offer);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 1)); BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
for (auto const& j : jrr[jss::state]) for (auto const& j : jrr[jss::state])
BEAST_EXPECT(j["LedgerEntryType"] == jss::FeeSettings); BEAST_EXPECT(j["LedgerEntryType"] == jss::Offer);
} }
{ // jvParams[jss::type] = "hashes"; { // jvParams[jss::type] = "signer_list";
auto const jrr = makeRequest(jss::hashes); auto const jrr = makeRequest(jss::signer_list);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 2)); BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
for (auto const& j : jrr[jss::state]) for (auto const& j : jrr[jss::state])
BEAST_EXPECT(j["LedgerEntryType"] == jss::LedgerHashes); BEAST_EXPECT(j["LedgerEntryType"] == jss::SignerList);
} }
{ // jvParams[jss::type] = "import_vlseq"; { // jvParams[jss::type] = "state";
auto const jrr = makeRequest(jss::import_vlseq); auto const jrr = makeRequest(jss::state);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 1)); BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
for (auto const& j : jrr[jss::state]) for (auto const& j : jrr[jss::state])
BEAST_EXPECT(j["LedgerEntryType"] == jss::ImportVLSequence); BEAST_EXPECT(j["LedgerEntryType"] == jss::RippleState);
} }
{ // jvParams[jss::type] = "offer"; { // jvParams[jss::type] = "ticket";
auto const jrr = makeRequest(jss::offer); auto const jrr = makeRequest(jss::ticket);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 1)); BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
for (auto const& j : jrr[jss::state]) for (auto const& j : jrr[jss::state])
BEAST_EXPECT(j["LedgerEntryType"] == jss::Offer); BEAST_EXPECT(j["LedgerEntryType"] == jss::Ticket);
} }
{ // jvParams[jss::type] = "signer_list"; { // jvParams[jss::type] = "escrow";
auto const jrr = makeRequest(jss::signer_list); auto const jrr = makeRequest(jss::escrow);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 1)); BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
for (auto const& j : jrr[jss::state]) for (auto const& j : jrr[jss::state])
BEAST_EXPECT(j["LedgerEntryType"] == jss::SignerList); BEAST_EXPECT(j["LedgerEntryType"] == jss::Escrow);
} }
{ // jvParams[jss::type] = "state"; { // jvParams[jss::type] = "hook";
auto const jrr = makeRequest(jss::state); auto const jrr = makeRequest(jss::hook);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 1)); BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
for (auto const& j : jrr[jss::state]) for (auto const& j : jrr[jss::state])
BEAST_EXPECT(j["LedgerEntryType"] == jss::RippleState); BEAST_EXPECT(j["LedgerEntryType"] == jss::Hook);
} }
{ // jvParams[jss::type] = "ticket"; { // jvParams[jss::type] = "hook_definition";
auto const jrr = makeRequest(jss::ticket); auto const jrr = makeRequest(jss::hook_definition);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 1)); BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
for (auto const& j : jrr[jss::state]) for (auto const& j : jrr[jss::state])
BEAST_EXPECT(j["LedgerEntryType"] == jss::Ticket); BEAST_EXPECT(j["LedgerEntryType"] == jss::HookDefinition);
} }
{ // jvParams[jss::type] = "escrow"; { // jvParams[jss::type] = "hook_state";
auto const jrr = makeRequest(jss::escrow); auto const jrr = makeRequest(jss::hook_state);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 1)); BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
for (auto const& j : jrr[jss::state]) for (auto const& j : jrr[jss::state])
BEAST_EXPECT(j["LedgerEntryType"] == jss::Escrow); BEAST_EXPECT(j["LedgerEntryType"] == jss::HookState);
} }
{ // jvParams[jss::type] = "hook"; { // jvParams[jss::type] = "uri_token";
auto const jrr = makeRequest(jss::hook); auto const jrr = makeRequest(jss::uri_token);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 1)); BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
for (auto const& j : jrr[jss::state]) for (auto const& j : jrr[jss::state])
BEAST_EXPECT(j["LedgerEntryType"] == jss::Hook); BEAST_EXPECT(j["LedgerEntryType"] == jss::URIToken);
} }
{ // jvParams[jss::type] = "hook_definition"; { // jvParams[jss::type] = "payment_channel";
auto const jrr = makeRequest(jss::hook_definition); auto const jrr = makeRequest(jss::payment_channel);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 1)); BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
for (auto const& j : jrr[jss::state]) for (auto const& j : jrr[jss::state])
BEAST_EXPECT(j["LedgerEntryType"] == jss::HookDefinition); BEAST_EXPECT(j["LedgerEntryType"] == jss::PayChannel);
} }
{ // jvParams[jss::type] = "hook_state"; { // jvParams[jss::type] = "deposit_preauth";
auto const jrr = makeRequest(jss::hook_state); auto const jrr = makeRequest(jss::deposit_preauth);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 1)); BEAST_EXPECT(checkArraySize(jrr[jss::state], 2));
for (auto const& j : jrr[jss::state]) for (auto const& j : jrr[jss::state])
BEAST_EXPECT(j["LedgerEntryType"] == jss::HookState); BEAST_EXPECT(j["LedgerEntryType"] == jss::DepositPreauth);
} }
{ // jvParams[jss::type] = "uri_token"; { // jvParams[jss::type] = "misspelling";
auto const jrr = makeRequest(jss::uri_token); Json::Value jvParams;
BEAST_EXPECT(checkArraySize(jrr[jss::state], 1)); jvParams[jss::ledger_index] = "current";
for (auto const& j : jrr[jss::state]) jvParams[jss::type] = "misspelling";
BEAST_EXPECT(j["LedgerEntryType"] == jss::URIToken); auto const jrr = env.rpc(
} "json",
"ledger_data",
{ // jvParams[jss::type] = "payment_channel"; boost::lexical_cast<std::string>(jvParams))[jss::result];
auto const jrr = makeRequest(jss::payment_channel); BEAST_EXPECT(jrr.isMember("error"));
BEAST_EXPECT(checkArraySize(jrr[jss::state], 1)); BEAST_EXPECT(jrr["error"] == "invalidParams");
for (auto const& j : jrr[jss::state]) BEAST_EXPECT(jrr["error_message"] == "Invalid field 'type'.");
BEAST_EXPECT(j["LedgerEntryType"] == jss::PayChannel); }
}
{ // jvParams[jss::type] = "deposit_preauth";
auto const jrr = makeRequest(jss::deposit_preauth);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 2));
for (auto const& j : jrr[jss::state])
BEAST_EXPECT(j["LedgerEntryType"] == jss::DepositPreauth);
}
{ // jvParams[jss::type] = "misspelling";
Json::Value jvParams;
jvParams[jss::ledger_index] = "current";
jvParams[jss::type] = "misspelling";
auto const jrr = env.rpc(
"json",
"ledger_data",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr.isMember("error"));
BEAST_EXPECT(jrr["error"] == "invalidParams");
BEAST_EXPECT(jrr["error_message"] == "Invalid field 'type'.");
} }
} }
@@ -650,7 +664,7 @@ public:
testLedgerHeader(); testLedgerHeader();
testLedgerType(); testLedgerType();
} }
}; }; // namespace ripple
BEAST_DEFINE_TESTSUITE_PRIO(LedgerData, app, ripple, 1); BEAST_DEFINE_TESTSUITE_PRIO(LedgerData, app, ripple, 1);

View File

@@ -831,7 +831,7 @@ Ledger::updateNegativeUNL()
if (hasToDisable) if (hasToDisable)
{ {
newNUnl.emplace_back(sfDisabledValidator); newNUnl.push_back(STObject::makeInnerObject(sfDisabledValidator));
newNUnl.back().setFieldVL( newNUnl.back().setFieldVL(
sfPublicKey, sle->getFieldVL(sfValidatorToDisable)); sfPublicKey, sle->getFieldVL(sfValidatorToDisable));
newNUnl.back().setFieldU32(sfFirstLedgerSequence, seq()); newNUnl.back().setFieldU32(sfFirstLedgerSequence, seq());

View File

@@ -312,7 +312,7 @@ initializeFeeAuctionVote(
auto const& rules = view.rules(); auto const& rules = view.rules();
// AMM creator gets the voting slot. // AMM creator gets the voting slot.
STArray voteSlots; STArray voteSlots;
STObject voteEntry = STObject::makeInnerObject(sfVoteEntry, rules); STObject voteEntry = STObject::makeInnerObject(sfVoteEntry);
if (tfee != 0) if (tfee != 0)
voteEntry.setFieldU16(sfTradingFee, tfee); voteEntry.setFieldU16(sfTradingFee, tfee);
voteEntry.setFieldU32(sfVoteWeight, VOTE_WEIGHT_SCALE_FACTOR); voteEntry.setFieldU32(sfVoteWeight, VOTE_WEIGHT_SCALE_FACTOR);
@@ -325,7 +325,7 @@ initializeFeeAuctionVote(
if (rules.enabled(fixInnerObjTemplate) && if (rules.enabled(fixInnerObjTemplate) &&
!ammSle->isFieldPresent(sfAuctionSlot)) !ammSle->isFieldPresent(sfAuctionSlot))
{ {
STObject auctionSlot = STObject::makeInnerObject(sfAuctionSlot, rules); STObject auctionSlot = STObject::makeInnerObject(sfAuctionSlot);
ammSle->set(std::move(auctionSlot)); ammSle->set(std::move(auctionSlot));
} }
STObject& auctionSlot = ammSle->peekFieldObject(sfAuctionSlot); STObject& auctionSlot = ammSle->peekFieldObject(sfAuctionSlot);

View File

@@ -104,7 +104,7 @@ applyVote(
Number den{0}; Number den{0};
// Account already has vote entry // Account already has vote entry
bool foundAccount = false; bool foundAccount = false;
auto const& rules = ctx_.view().rules();
// Iterate over the current vote entries and update each entry // Iterate over the current vote entries and update each entry
// per current total tokens balance and each LP tokens balance. // per current total tokens balance and each LP tokens balance.
// Find the entry with the least tokens and whether the account // Find the entry with the least tokens and whether the account
@@ -120,7 +120,7 @@ applyVote(
continue; continue;
} }
auto feeVal = entry[sfTradingFee]; auto feeVal = entry[sfTradingFee];
STObject newEntry = STObject::makeInnerObject(sfVoteEntry, rules); STObject newEntry = STObject::makeInnerObject(sfVoteEntry);
// The account already has the vote entry. // The account already has the vote entry.
if (account == account_) if (account == account_)
{ {
@@ -159,7 +159,7 @@ applyVote(
{ {
auto update = [&](std::optional<std::uint8_t> const& minPos = auto update = [&](std::optional<std::uint8_t> const& minPos =
std::nullopt) { std::nullopt) {
STObject newEntry = STObject::makeInnerObject(sfVoteEntry, rules); STObject newEntry = STObject::makeInnerObject(sfVoteEntry);
if (feeNew != 0) if (feeNew != 0)
newEntry.setFieldU16(sfTradingFee, feeNew); newEntry.setFieldU16(sfTradingFee, feeNew);
newEntry.setFieldU32( newEntry.setFieldU32(

View File

@@ -931,11 +931,11 @@ Change::applyAmendment()
if (gotMajority) if (gotMajority)
{ {
// This amendment now has a majority // This amendment now has a majority
newMajorities.push_back(STObject(sfMajority)); newMajorities.push_back(STObject::makeInnerObject(sfMajority));
auto& entry = newMajorities.back(); auto& entry = newMajorities.back();
entry.emplace_back(STUInt256(sfAmendment, amendment)); entry[sfAmendment] = amendment;
entry.emplace_back(STUInt32( entry[sfCloseTime] =
sfCloseTime, view().parentCloseTime().time_since_epoch().count())); view().parentCloseTime().time_since_epoch().count();
if (!ctx_.app.getAmendmentTable().isSupported(amendment)) if (!ctx_.app.getAmendmentTable().isSupported(amendment))
{ {

View File

@@ -359,11 +359,11 @@ SetSignerList::writeSignersToSLE(
STArray toLedger(signers.size()); STArray toLedger(signers.size());
for (auto const& entry : signers) for (auto const& entry : signers)
{ {
toLedger.emplace_back(sfSignerEntry); toLedger.push_back(STObject::makeInnerObject(sfSignerEntry));
STObject& obj = toLedger.back(); STObject& obj = toLedger.back();
obj.reserve(2); obj.reserve(2);
obj.setAccountID(sfAccount, entry.account); obj[sfAccount] = entry.account;
obj.setFieldU16(sfSignerWeight, entry.weight); obj[sfSignerWeight] = entry.weight;
// This is a defensive check to make absolutely sure we will never write // This is a defensive check to make absolutely sure we will never write
// a tag into the ledger while featureExpandedSignerList is not enabled // a tag into the ledger while featureExpandedSignerList is not enabled

View File

@@ -1051,7 +1051,7 @@ transactionSignFor(
auto& sttx = preprocResult.second; auto& sttx = preprocResult.second;
{ {
// Make the signer object that we'll inject. // Make the signer object that we'll inject.
STObject signer(sfSigner); STObject signer = STObject::makeInnerObject(sfSigner);
signer[sfAccount] = *signerAccountID; signer[sfAccount] = *signerAccountID;
signer.setFieldVL(sfTxnSignature, signForParams.getSignature()); signer.setFieldVL(sfTxnSignature, signForParams.getSignature());
signer.setFieldVL( signer.setFieldVL(