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 GitHub
parent ef02893f2f
commit 9fec615dca
12 changed files with 222 additions and 197 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 = 76; static constexpr std::size_t numFeatures = 77;
/** 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
@@ -369,6 +369,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

@@ -496,6 +496,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

@@ -300,201 +300,214 @@ 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;
Env env{*this, envconfig(validator, "")};
Account const gw{"gateway"}; // Make sure fixInnerObjTemplate2 doesn't break amendments.
auto const USD = gw["USD"]; for (FeatureBitset const& features :
env.fund(XRP(100000), gw); {supported_amendments() - fixInnerObjTemplate2,
supported_amendments() | fixInnerObjTemplate2})
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::deposit_preauth})
{ {
auto const jrr = makeRequest(type); using namespace std::chrono;
BEAST_EXPECT(checkArraySize(jrr[jss::state], 0)); Env env{*this, envconfig(validator, ""), features};
}
int const num_accounts = 10; Account const gw{"gateway"};
auto const USD = gw["USD"];
env.fund(XRP(100000), gw);
for (auto i = 0; i < num_accounts; i++) auto makeRequest = [&env](Json::StaticString const& type) {
{ Json::Value jvParams;
Account const bob{std::string("bob") + std::to_string(i)}; jvParams[jss::ledger_index] = "current";
env.fund(XRP(1000), bob); jvParams[jss::type] = type;
} return env.rpc(
env(offer(Account{"bob0"}, USD(100), XRP(100))); "json",
env.trust(Account{"bob2"}["USD"](100), Account{"bob3"}); "ledger_data",
boost::lexical_cast<std::string>(jvParams))[jss::result];
};
auto majorities = getMajorityAmendments(*env.closed()); // Assert that state is an empty array.
for (int i = 0; i <= 256; ++i) 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::deposit_preauth})
{
auto const jrr = makeRequest(type);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 0));
}
int const num_accounts = 10;
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);
}
{
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);
}
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();
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));
{ // Now fetch each type
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);
}
{ { // jvParams[jss::type] = "account";
Json::Value jv; auto const jrr = makeRequest(jss::account);
jv[jss::TransactionType] = jss::PaymentChannelCreate; BEAST_EXPECT(checkArraySize(jrr[jss::state], 12));
jv[jss::Flags] = tfUniversal; for (auto const& j : jrr[jss::state])
jv[jss::Account] = Account{"bob6"}.human(); BEAST_EXPECT(j["LedgerEntryType"] == jss::AccountRoot);
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);
}
env(check::create("bob6", "bob7", XRP(100))); { // jvParams[jss::type] = "amendments";
auto const jrr = makeRequest(jss::amendments);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
for (auto const& j : jrr[jss::state])
BEAST_EXPECT(j["LedgerEntryType"] == jss::Amendments);
}
// bob9 DepositPreauths bob4 and bob8. { // jvParams[jss::type] = "check";
env(deposit::auth(Account{"bob9"}, Account{"bob4"})); auto const jrr = makeRequest(jss::check);
env(deposit::auth(Account{"bob9"}, Account{"bob8"})); BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
env.close(); for (auto const& j : jrr[jss::state])
BEAST_EXPECT(j["LedgerEntryType"] == jss::Check);
}
// Now fetch each type { // jvParams[jss::type] = "directory";
auto const jrr = makeRequest(jss::directory);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 9));
for (auto const& j : jrr[jss::state])
BEAST_EXPECT(j["LedgerEntryType"] == jss::DirectoryNode);
}
{ // jvParams[jss::type] = "account"; { // jvParams[jss::type] = "fee";
auto const jrr = makeRequest(jss::account); auto const jrr = makeRequest(jss::fee);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 12)); 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::FeeSettings);
} }
{ // jvParams[jss::type] = "amendments"; { // jvParams[jss::type] = "hashes";
auto const jrr = makeRequest(jss::amendments); 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::Amendments); BEAST_EXPECT(j["LedgerEntryType"] == jss::LedgerHashes);
} }
{ // jvParams[jss::type] = "check"; { // jvParams[jss::type] = "offer";
auto const jrr = makeRequest(jss::check); 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::Check); BEAST_EXPECT(j["LedgerEntryType"] == jss::Offer);
} }
{ // jvParams[jss::type] = "directory"; { // jvParams[jss::type] = "signer_list";
auto const jrr = makeRequest(jss::directory); auto const jrr = makeRequest(jss::signer_list);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 9)); 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::SignerList);
} }
{ // jvParams[jss::type] = "fee"; { // jvParams[jss::type] = "state";
auto const jrr = makeRequest(jss::fee); 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::FeeSettings); BEAST_EXPECT(j["LedgerEntryType"] == jss::RippleState);
} }
{ // jvParams[jss::type] = "hashes"; { // jvParams[jss::type] = "ticket";
auto const jrr = makeRequest(jss::hashes); auto const jrr = makeRequest(jss::ticket);
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::Ticket);
} }
{ // jvParams[jss::type] = "offer"; { // jvParams[jss::type] = "escrow";
auto const jrr = makeRequest(jss::offer); 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::Offer); BEAST_EXPECT(j["LedgerEntryType"] == jss::Escrow);
} }
{ // jvParams[jss::type] = "signer_list"; { // jvParams[jss::type] = "payment_channel";
auto const jrr = makeRequest(jss::signer_list); 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::SignerList); BEAST_EXPECT(j["LedgerEntryType"] == jss::PayChannel);
} }
{ // jvParams[jss::type] = "state"; { // jvParams[jss::type] = "deposit_preauth";
auto const jrr = makeRequest(jss::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::RippleState); BEAST_EXPECT(j["LedgerEntryType"] == jss::DepositPreauth);
} }
{ // jvParams[jss::type] = "ticket"; { // jvParams[jss::type] = "misspelling";
auto const jrr = makeRequest(jss::ticket); 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::Ticket); auto const jrr = env.rpc(
} "json",
"ledger_data",
{ // jvParams[jss::type] = "escrow"; boost::lexical_cast<std::string>(jvParams))[jss::result];
auto const jrr = makeRequest(jss::escrow); 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::Escrow); }
}
{ // jvParams[jss::type] = "payment_channel";
auto const jrr = makeRequest(jss::payment_channel);
BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
for (auto const& j : jrr[jss::state])
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'.");
} }
} }

View File

@@ -793,7 +793,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

@@ -300,11 +300,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

@@ -416,11 +416,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(