From 42c0ab0704e69d8c9ea84ef4fc80f2772c7334bd Mon Sep 17 00:00:00 2001 From: Ed Hennis Date: Fri, 9 Sep 2022 13:55:29 -0700 Subject: [PATCH] Refactor fee initialization and configuration (#4319): * Create the FeeSettings object in genesis ledger. * Initialize with default values from the config. Removes the need to pass a Config down into the Ledger initialization functions, including setup(). * Drop the undocumented fee config settings in favor of the [voting] section. * Because old mainnet ledgers (prior to 562177 - yes, I looked it up), don't have FeeSettings, some of the other ctors will default them to the config values before setup() tries to load the object. * Update default Config fee values to match mainnet. * Fix unit tests: * Updated fees: Some tests are converted to use computed values of fee object, but the default Env config was also updated to fix the rest. * Unit tests that check the structure of the ledger have updated hashes and counts. --- cfg/rippled-example.cfg | 4 +- cfg/rippled-reporting.cfg | 4 +- src/ripple/app/ledger/Ledger.cpp | 68 +++++++++++---- src/ripple/app/ledger/Ledger.h | 10 ++- src/ripple/app/ledger/impl/BuildLedger.cpp | 6 +- src/ripple/app/ledger/impl/InboundLedger.cpp | 15 +++- src/ripple/app/main/Application.cpp | 17 +++- src/ripple/app/misc/FeeVote.h | 24 +---- src/ripple/app/misc/FeeVoteImpl.cpp | 28 +----- src/ripple/app/reporting/ReportingETL.cpp | 5 +- src/ripple/core/Config.h | 27 +++++- src/ripple/core/ConfigSections.h | 2 - src/ripple/core/impl/Config.cpp | 32 +++++-- src/ripple/ledger/ReadView.h | 3 + src/ripple/ledger/impl/ReadView.cpp | 6 ++ src/ripple/nodestore/impl/Shard.cpp | 5 +- src/ripple/protocol/Rules.h | 8 ++ src/ripple/protocol/SystemParameters.h | 4 + src/ripple/protocol/impl/Rules.cpp | 13 +++ src/ripple/rpc/impl/TransactionSign.cpp | 2 +- src/test/app/FeeVote_test.cpp | 2 +- src/test/app/LedgerHistory_test.cpp | 3 +- src/test/app/LedgerLoad_test.cpp | 4 +- src/test/app/LoadFeeTrack_test.cpp | 6 +- src/test/app/NFToken_test.cpp | 13 +-- src/test/app/Offer_test.cpp | 9 +- src/test/app/RCLValidations_test.cpp | 3 +- src/test/app/TxQ_test.cpp | 24 ++--- src/test/jtx/impl/envconfig.cpp | 11 ++- src/test/rpc/LedgerClosed_test.cpp | 4 +- src/test/rpc/LedgerData_test.cpp | 2 +- src/test/rpc/LedgerRPC_test.cpp | 30 +++---- src/test/rpc/LedgerRequestRPC_test.cpp | 92 ++++++++------------ src/test/rpc/ReportingETL_test.cpp | 2 +- 34 files changed, 289 insertions(+), 199 deletions(-) diff --git a/cfg/rippled-example.cfg b/cfg/rippled-example.cfg index 02ef02e920f..0a669313066 100644 --- a/cfg/rippled-example.cfg +++ b/cfg/rippled-example.cfg @@ -1441,7 +1441,7 @@ # default. Don't change this without understanding the consequences. # # Example: -# account_reserve = 20000000 # 20 XRP +# account_reserve = 10000000 # 10 XRP # # owner_reserve = # @@ -1453,7 +1453,7 @@ # default. Don't change this without understanding the consequences. # # Example: -# owner_reserve = 5000000 # 5 XRP +# owner_reserve = 2000000 # 2 XRP # #------------------------------------------------------------------------------- # diff --git a/cfg/rippled-reporting.cfg b/cfg/rippled-reporting.cfg index 7e69d76f4f5..dbafdd497fa 100644 --- a/cfg/rippled-reporting.cfg +++ b/cfg/rippled-reporting.cfg @@ -1401,7 +1401,7 @@ # default. Don't change this without understanding the consequences. # # Example: -# account_reserve = 20000000 # 20 XRP +# account_reserve = 10000000 # 10 XRP # # owner_reserve = # @@ -1413,7 +1413,7 @@ # default. Don't change this without understanding the consequences. # # Example: -# owner_reserve = 5000000 # 5 XRP +# owner_reserve = 2000000 # 2 XRP # #------------------------------------------------------------------------------- # diff --git a/src/ripple/app/ledger/Ledger.cpp b/src/ripple/app/ledger/Ledger.cpp index 7552f755c6e..4de01cc909e 100644 --- a/src/ripple/app/ledger/Ledger.cpp +++ b/src/ripple/app/ledger/Ledger.cpp @@ -209,8 +209,34 @@ Ledger::Ledger( rawInsert(sle); } + { + auto sle = std::make_shared(keylet::fees()); + // Whether featureXRPFees is supported will depend on startup options. + if (std::find(amendments.begin(), amendments.end(), featureXRPFees) != + amendments.end()) + { + sle->at(sfBaseFeeDrops) = config.FEES.reference_fee; + sle->at(sfReserveBaseDrops) = config.FEES.account_reserve; + sle->at(sfReserveIncrementDrops) = config.FEES.owner_reserve; + } + else + { + if (auto const f = + config.FEES.reference_fee.dropsAs()) + sle->at(sfBaseFee) = *f; + if (auto const f = + config.FEES.account_reserve.dropsAs()) + sle->at(sfReserveBase) = *f; + if (auto const f = + config.FEES.owner_reserve.dropsAs()) + sle->at(sfReserveIncrement) = *f; + sle->at(sfReferenceFeeUnits) = Config::FEE_UNITS_DEPRECATED; + } + rawInsert(sle); + } + stateMap_->flushDirty(hotACCOUNT_NODE); - setImmutable(config); + setImmutable(); } Ledger::Ledger( @@ -259,7 +285,8 @@ Ledger::Ledger( txMap_->setImmutable(); stateMap_->setImmutable(); - if (!setup(config)) + defaultFees(config); + if (!setup()) loaded = false; if (!loaded) @@ -329,11 +356,12 @@ Ledger::Ledger( info_.seq = ledgerSeq; info_.closeTime = closeTime; info_.closeTimeResolution = ledgerDefaultTimeResolution; - setup(config); + defaultFees(config); + setup(); } void -Ledger::setImmutable(Config const& config, bool rehash) +Ledger::setImmutable(bool rehash) { // Force update, since this is the only // place the hash transitions to valid @@ -349,15 +377,14 @@ Ledger::setImmutable(Config const& config, bool rehash) mImmutable = true; txMap_->setImmutable(); stateMap_->setImmutable(); - setup(config); + setup(); } void Ledger::setAccepted( NetClock::time_point closeTime, NetClock::duration closeResolution, - bool correctCloseTime, - Config const& config) + bool correctCloseTime) { // Used when we witnessed the consensus. assert(!open()); @@ -365,7 +392,7 @@ Ledger::setAccepted( info_.closeTime = closeTime; info_.closeTimeResolution = closeResolution; info_.closeFlags = correctCloseTime ? 0 : sLCF_NoConsensusTime; - setImmutable(config); + setImmutable(); } bool @@ -587,13 +614,13 @@ Ledger::rawTxInsertWithHash( } bool -Ledger::setup(Config const& config) +Ledger::setup() { bool ret = true; try { - rules_ = makeRulesGivenLedger(*this, config.features); + rules_ = makeRulesGivenLedger(*this, rules_); } catch (SHAMapMissingNode const&) { @@ -604,10 +631,6 @@ Ledger::setup(Config const& config) Rethrow(); } - fees_.base = config.FEE_DEFAULT; - fees_.reserve = config.FEE_ACCOUNT_RESERVE; - fees_.increment = config.FEE_OWNER_RESERVE; - try { if (auto const sle = read(keylet::fees())) @@ -667,6 +690,18 @@ Ledger::setup(Config const& config) return ret; } +void +Ledger::defaultFees(Config const& config) +{ + assert(fees_.base == 0 && fees_.reserve == 0 && fees_.increment == 0); + if (fees_.base == 0) + fees_.base = config.FEES.reference_fee; + if (fees_.reserve == 0) + fees_.reserve = config.FEES.account_reserve; + if (fees_.increment == 0) + fees_.increment = config.FEES.owner_reserve; +} + std::shared_ptr Ledger::peek(Keylet const& k) const { @@ -1071,7 +1106,10 @@ finishLoadByIndexOrHash( if (!ledger) return; - ledger->setImmutable(config); + assert( + ledger->info().seq < XRP_LEDGER_EARLIEST_FEES || + ledger->read(keylet::fees())); + ledger->setImmutable(); JLOG(j.trace()) << "Loaded ledger: " << to_string(ledger->info().hash); diff --git a/src/ripple/app/ledger/Ledger.h b/src/ripple/app/ledger/Ledger.h index caf68b3eac8..0b0830df9d9 100644 --- a/src/ripple/app/ledger/Ledger.h +++ b/src/ripple/app/ledger/Ledger.h @@ -266,11 +266,10 @@ class Ledger final : public std::enable_shared_from_this, setAccepted( NetClock::time_point closeTime, NetClock::duration closeResolution, - bool correctCloseTime, - Config const& config); + bool correctCloseTime); void - setImmutable(Config const& config, bool rehash = true); + setImmutable(bool rehash = true); bool isImmutable() const @@ -395,7 +394,10 @@ class Ledger final : public std::enable_shared_from_this, class txs_iter_impl; bool - setup(Config const& config); + setup(); + + void + defaultFees(Config const& config); bool mImmutable; diff --git a/src/ripple/app/ledger/impl/BuildLedger.cpp b/src/ripple/app/ledger/impl/BuildLedger.cpp index f70b754ab7c..87960d16eac 100644 --- a/src/ripple/app/ledger/impl/BuildLedger.cpp +++ b/src/ripple/app/ledger/impl/BuildLedger.cpp @@ -75,8 +75,10 @@ buildLedgerImpl( built->unshare(); // Accept ledger - built->setAccepted( - closeTime, closeResolution, closeTimeCorrect, app.config()); + assert( + built->info().seq < XRP_LEDGER_EARLIEST_FEES || + built->read(keylet::fees())); + built->setAccepted(closeTime, closeResolution, closeTimeCorrect); return built; } diff --git a/src/ripple/app/ledger/impl/InboundLedger.cpp b/src/ripple/app/ledger/impl/InboundLedger.cpp index 3ecba97b199..af3ba8a7a9b 100644 --- a/src/ripple/app/ledger/impl/InboundLedger.cpp +++ b/src/ripple/app/ledger/impl/InboundLedger.cpp @@ -155,7 +155,10 @@ InboundLedger::init(ScopedLockType& collectionLock) JLOG(journal_.debug()) << "Acquiring ledger we already have in " << " local store. " << hash_; - mLedger->setImmutable(app_.config()); + assert( + mLedger->info().seq < XRP_LEDGER_EARLIEST_FEES || + mLedger->read(keylet::fees())); + mLedger->setImmutable(); if (mReason == Reason::HISTORY || mReason == Reason::SHARD) return; @@ -416,7 +419,10 @@ InboundLedger::tryDB(NodeStore::Database& srcDB) { JLOG(journal_.debug()) << "Had everything locally"; complete_ = true; - mLedger->setImmutable(app_.config()); + assert( + mLedger->info().seq < XRP_LEDGER_EARLIEST_FEES || + mLedger->read(keylet::fees())); + mLedger->setImmutable(); } } @@ -513,7 +519,10 @@ InboundLedger::done() if (complete_ && !failed_ && mLedger) { - mLedger->setImmutable(app_.config()); + assert( + mLedger->info().seq < XRP_LEDGER_EARLIEST_FEES || + mLedger->read(keylet::fees())); + mLedger->setImmutable(); switch (mReason) { case Reason::SHARD: diff --git a/src/ripple/app/main/Application.cpp b/src/ripple/app/main/Application.cpp index dce11bc38f0..16781ac09d4 100644 --- a/src/ripple/app/main/Application.cpp +++ b/src/ripple/app/main/Application.cpp @@ -1699,7 +1699,7 @@ ApplicationImp::fdRequired() const void ApplicationImp::startGenesisLedger() { - std::vector initialAmendments = + std::vector const initialAmendments = (config_->START_UP == Config::FRESH) ? m_amendmentTable->getDesired() : std::vector{}; @@ -1710,7 +1710,10 @@ ApplicationImp::startGenesisLedger() auto const next = std::make_shared(*genesis, timeKeeper().closeTime()); next->updateSkipList(); - next->setImmutable(*config_); + assert( + next->info().seq < XRP_LEDGER_EARLIEST_FEES || + next->read(keylet::fees())); + next->setImmutable(); openLedger_.emplace(next, cachedSLEs_, logs_->journal("OpenLedger")); m_ledgerMaster->storeLedger(next); m_ledgerMaster->switchLCL(next); @@ -1728,7 +1731,10 @@ ApplicationImp::getLastFullLedger() if (!ledger) return ledger; - ledger->setImmutable(*config_); + assert( + ledger->info().seq < XRP_LEDGER_EARLIEST_FEES || + ledger->read(keylet::fees())); + ledger->setImmutable(); if (getLedgerMaster().haveLedger(seq)) ledger->setValidated(); @@ -1879,8 +1885,11 @@ ApplicationImp::loadLedgerFromFile(std::string const& name) loadLedger->stateMap().flushDirty(hotACCOUNT_NODE); + assert( + loadLedger->info().seq < XRP_LEDGER_EARLIEST_FEES || + loadLedger->read(keylet::fees())); loadLedger->setAccepted( - closeTime, closeTimeResolution, !closeTimeEstimated, *config_); + closeTime, closeTimeResolution, !closeTimeEstimated); return loadLedger; } diff --git a/src/ripple/app/misc/FeeVote.h b/src/ripple/app/misc/FeeVote.h index 4fff64f7de3..a90f82efb35 100644 --- a/src/ripple/app/misc/FeeVote.h +++ b/src/ripple/app/misc/FeeVote.h @@ -32,23 +32,6 @@ namespace ripple { class FeeVote { public: - /** Fee schedule to vote for. - During voting ledgers, the FeeVote logic will try to move towards - these values when injecting fee-setting transactions. - A default-constructed Setup contains recommended values. - */ - struct Setup - { - /** The cost of a reference transaction in drops. */ - XRPAmount reference_fee{10}; - - /** The account reserve requirement in drops. */ - XRPAmount account_reserve{10 * DROPS_PER_XRP}; - - /** The per-owned item reserve requirement in drops. */ - XRPAmount owner_reserve{2 * DROPS_PER_XRP}; - }; - virtual ~FeeVote() = default; /** Add local fee preference to validation. @@ -74,16 +57,13 @@ class FeeVote std::shared_ptr const& initialPosition) = 0; }; -/** Build FeeVote::Setup from a config section. */ -FeeVote::Setup -setup_FeeVote(Section const& section); - +struct FeeSetup; /** Create an instance of the FeeVote logic. @param setup The fee schedule to vote for. @param journal Where to log. */ std::unique_ptr -make_FeeVote(FeeVote::Setup const& setup, beast::Journal journal); +make_FeeVote(FeeSetup const& setup, beast::Journal journal); } // namespace ripple diff --git a/src/ripple/app/misc/FeeVoteImpl.cpp b/src/ripple/app/misc/FeeVoteImpl.cpp index 73d98fbd58a..048f5a3fc61 100644 --- a/src/ripple/app/misc/FeeVoteImpl.cpp +++ b/src/ripple/app/misc/FeeVoteImpl.cpp @@ -93,11 +93,11 @@ VotableValue::getVotes() const -> std::pair class FeeVoteImpl : public FeeVote { private: - Setup target_; + FeeSetup target_; beast::Journal const journal_; public: - FeeVoteImpl(Setup const& setup, beast::Journal journal); + FeeVoteImpl(FeeSetup const& setup, beast::Journal journal); void doValidation(Fees const& lastFees, Rules const& rules, STValidation& val) @@ -112,7 +112,7 @@ class FeeVoteImpl : public FeeVote //-------------------------------------------------------------------------- -FeeVoteImpl::FeeVoteImpl(Setup const& setup, beast::Journal journal) +FeeVoteImpl::FeeVoteImpl(FeeSetup const& setup, beast::Journal journal) : target_(setup), journal_(journal) { } @@ -335,28 +335,8 @@ FeeVoteImpl::doVoting( //------------------------------------------------------------------------------ -FeeVote::Setup -setup_FeeVote(Section const& section) -{ - FeeVote::Setup setup; - { - std::uint64_t temp; - if (set(temp, "reference_fee", section) && - temp <= std::numeric_limits::max()) - setup.reference_fee = temp; - } - { - std::uint32_t temp; - if (set(temp, "account_reserve", section)) - setup.account_reserve = temp; - if (set(temp, "owner_reserve", section)) - setup.owner_reserve = temp; - } - return setup; -} - std::unique_ptr -make_FeeVote(FeeVote::Setup const& setup, beast::Journal journal) +make_FeeVote(FeeSetup const& setup, beast::Journal journal) { return std::make_unique(setup, journal); } diff --git a/src/ripple/app/reporting/ReportingETL.cpp b/src/ripple/app/reporting/ReportingETL.cpp index 7e15d242a72..d8d6af36881 100644 --- a/src/ripple/app/reporting/ReportingETL.cpp +++ b/src/ripple/app/reporting/ReportingETL.cpp @@ -189,7 +189,10 @@ ReportingETL::flushLedger(std::shared_ptr& ledger) auto& txHash = ledger->info().txHash; auto& ledgerHash = ledger->info().hash; - ledger->setImmutable(app_.config(), false); + assert( + ledger->info().seq < XRP_LEDGER_EARLIEST_FEES || + ledger->read(keylet::fees())); + ledger->setImmutable(false); auto start = std::chrono::system_clock::now(); auto numFlushed = ledger->stateMap().flushDirty(hotACCOUNT_NODE); diff --git a/src/ripple/core/Config.h b/src/ripple/core/Config.h index 1e91f49263b..e805faad989 100644 --- a/src/ripple/core/Config.h +++ b/src/ripple/core/Config.h @@ -61,6 +61,26 @@ enum class SizedItem : std::size_t { accountIdCacheSize, }; +/** Fee schedule for startup / standalone, and to vote for. +During voting ledgers, the FeeVote logic will try to move towards +these values when injecting fee-setting transactions. +A default-constructed Setup contains recommended values. +*/ +struct FeeSetup +{ + /** The cost of a reference transaction in drops. */ + XRPAmount reference_fee{10}; + + /** The account reserve requirement in drops. */ + XRPAmount account_reserve{10 * DROPS_PER_XRP}; + + /** The per-owned item reserve requirement in drops. */ + XRPAmount owner_reserve{2 * DROPS_PER_XRP}; + + /* (Remember to update the example cfg files when changing any of these + * values.) */ +}; + // This entire derived class is deprecated. // For new config information use the style implied // in the base class. For existing config information @@ -185,9 +205,7 @@ class Config : public BasicConfig std::optional VALIDATION_QUORUM; // validations to consider ledger authoritative - XRPAmount FEE_DEFAULT{10}; - XRPAmount FEE_ACCOUNT_RESERVE{200 * DROPS_PER_XRP}; - XRPAmount FEE_OWNER_RESERVE{50 * DROPS_PER_XRP}; + FeeSetup FEES; // Node storage configuration std::uint32_t LEDGER_HISTORY = 256; @@ -366,6 +384,9 @@ class Config : public BasicConfig const; }; +FeeSetup +setup_FeeVote(Section const& section); + } // namespace ripple #endif diff --git a/src/ripple/core/ConfigSections.h b/src/ripple/core/ConfigSections.h index ba0f209c0e9..6fd59680d8b 100644 --- a/src/ripple/core/ConfigSections.h +++ b/src/ripple/core/ConfigSections.h @@ -54,8 +54,6 @@ struct ConfigSection #define SECTION_DEBUG_LOGFILE "debug_logfile" #define SECTION_ELB_SUPPORT "elb_support" #define SECTION_FEE_DEFAULT "fee_default" -#define SECTION_FEE_ACCOUNT_RESERVE "fee_account_reserve" -#define SECTION_FEE_OWNER_RESERVE "fee_owner_reserve" #define SECTION_FETCH_DEPTH "fetch_depth" #define SECTION_HISTORICAL_SHARD_PATHS "historical_shard_paths" #define SECTION_INSIGHT "insight" diff --git a/src/ripple/core/impl/Config.cpp b/src/ripple/core/impl/Config.cpp index 12374972866..4e25552cb8b 100644 --- a/src/ripple/core/impl/Config.cpp +++ b/src/ripple/core/impl/Config.cpp @@ -611,14 +611,12 @@ Config::loadFromString(std::string const& fileContents) if (getSingleSection(secConfig, SECTION_NETWORK_QUORUM, strTemp, j_)) NETWORK_QUORUM = beast::lexicalCastThrow(strTemp); - if (getSingleSection(secConfig, SECTION_FEE_ACCOUNT_RESERVE, strTemp, j_)) - FEE_ACCOUNT_RESERVE = beast::lexicalCastThrow(strTemp); - - if (getSingleSection(secConfig, SECTION_FEE_OWNER_RESERVE, strTemp, j_)) - FEE_OWNER_RESERVE = beast::lexicalCastThrow(strTemp); - + FEES = setup_FeeVote(section("voting")); + /* [fee_default] is documented in the example config files as useful for + * things like offline transaction signing. Until that's completely + * deprecated, allow it to override the [voting] section. */ if (getSingleSection(secConfig, SECTION_FEE_DEFAULT, strTemp, j_)) - FEE_DEFAULT = beast::lexicalCastThrow(strTemp); + FEES.reference_fee = beast::lexicalCastThrow(strTemp); if (getSingleSection(secConfig, SECTION_LEDGER_HISTORY, strTemp, j_)) { @@ -1017,4 +1015,24 @@ Config::getValueFor(SizedItem item, std::optional node) const return sizedItems.at(index).second.at(node.value_or(NODE_SIZE)); } +FeeSetup +setup_FeeVote(Section const& section) +{ + FeeSetup setup; + { + std::uint64_t temp; + if (set(temp, "reference_fee", section) && + temp <= std::numeric_limits::max()) + setup.reference_fee = temp; + } + { + std::uint32_t temp; + if (set(temp, "account_reserve", section)) + setup.account_reserve = temp; + if (set(temp, "owner_reserve", section)) + setup.owner_reserve = temp; + } + return setup; +} + } // namespace ripple diff --git a/src/ripple/ledger/ReadView.h b/src/ripple/ledger/ReadView.h index fb9e37c7458..e019d602f07 100644 --- a/src/ripple/ledger/ReadView.h +++ b/src/ripple/ledger/ReadView.h @@ -356,6 +356,9 @@ getCloseAgree(LedgerInfo const& info) void addRaw(LedgerInfo const&, Serializer&, bool includeHash = false); +Rules +makeRulesGivenLedger(DigestAwareReadView const& ledger, Rules const& current); + Rules makeRulesGivenLedger( DigestAwareReadView const& ledger, diff --git a/src/ripple/ledger/impl/ReadView.cpp b/src/ripple/ledger/impl/ReadView.cpp index 57af008b47c..1ce21777297 100644 --- a/src/ripple/ledger/impl/ReadView.cpp +++ b/src/ripple/ledger/impl/ReadView.cpp @@ -65,6 +65,12 @@ ReadView::txs_type::end() const -> iterator return iterator(view_, view_->txsEnd()); } +Rules +makeRulesGivenLedger(DigestAwareReadView const& ledger, Rules const& current) +{ + return makeRulesGivenLedger(ledger, current.presets()); +} + Rules makeRulesGivenLedger( DigestAwareReadView const& ledger, diff --git a/src/ripple/nodestore/impl/Shard.cpp b/src/ripple/nodestore/impl/Shard.cpp index 030fbf4aa12..14bfe487303 100644 --- a/src/ripple/nodestore/impl/Shard.cpp +++ b/src/ripple/nodestore/impl/Shard.cpp @@ -688,7 +688,10 @@ Shard::finalize(bool writeSQLite, std::optional const& referenceHash) ledger->stateMap().setLedgerSeq(ledgerSeq); ledger->txMap().setLedgerSeq(ledgerSeq); - ledger->setImmutable(config); + assert( + ledger->info().seq < XRP_LEDGER_EARLIEST_FEES || + ledger->read(keylet::fees())); + ledger->setImmutable(); if (!ledger->stateMap().fetchRoot( SHAMapHash{ledger->info().accountHash}, nullptr)) { diff --git a/src/ripple/protocol/Rules.h b/src/ripple/protocol/Rules.h index d8190e86a71..52d01c6f589 100644 --- a/src/ripple/protocol/Rules.h +++ b/src/ripple/protocol/Rules.h @@ -56,6 +56,11 @@ class Rules private: // Allow a friend function to construct Rules. + friend Rules + makeRulesGivenLedger( + DigestAwareReadView const& ledger, + Rules const& current); + friend Rules makeRulesGivenLedger( DigestAwareReadView const& ledger, @@ -66,6 +71,9 @@ class Rules std::optional const& digest, STVector256 const& amendments); + std::unordered_set> const& + presets() const; + public: /** Returns `true` if a feature is enabled. */ bool diff --git a/src/ripple/protocol/SystemParameters.h b/src/ripple/protocol/SystemParameters.h index db0c15dcad7..bc2f7136ff9 100644 --- a/src/ripple/protocol/SystemParameters.h +++ b/src/ripple/protocol/SystemParameters.h @@ -68,6 +68,10 @@ systemCurrencyCode() /** The XRP ledger network's earliest allowed sequence */ static constexpr std::uint32_t XRP_LEDGER_EARLIEST_SEQ{32570u}; +/** The XRP Ledger mainnet's earliest ledger with a FeeSettings object. Only + * used in asserts and tests. */ +static constexpr std::uint32_t XRP_LEDGER_EARLIEST_FEES{562177u}; + /** The number of ledgers in a shard */ static constexpr std::uint32_t DEFAULT_LEDGERS_PER_SHARD{16384u}; diff --git a/src/ripple/protocol/impl/Rules.cpp b/src/ripple/protocol/impl/Rules.cpp index 35a09b85658..c8f4720bd6c 100644 --- a/src/ripple/protocol/impl/Rules.cpp +++ b/src/ripple/protocol/impl/Rules.cpp @@ -45,6 +45,12 @@ class Rules::Impl set_.insert(amendments.begin(), amendments.end()); } + std::unordered_set> const& + presets() const + { + return presets_; + } + bool enabled(uint256 const& feature) const { @@ -60,6 +66,7 @@ class Rules::Impl return true; if (!digest_ || !other.digest_) return false; + assert(presets_ == other.presets_); return *digest_ == *other.digest_; } }; @@ -77,6 +84,12 @@ Rules::Rules( { } +std::unordered_set> const& +Rules::presets() const +{ + return impl_->presets(); +} + bool Rules::enabled(uint256 const& feature) const { diff --git a/src/ripple/rpc/impl/TransactionSign.cpp b/src/ripple/rpc/impl/TransactionSign.cpp index 4cf372e6b63..c903c26f8e3 100644 --- a/src/ripple/rpc/impl/TransactionSign.cpp +++ b/src/ripple/rpc/impl/TransactionSign.cpp @@ -720,7 +720,7 @@ checkFee( } } - XRPAmount const feeDefault = config.FEE_DEFAULT; + XRPAmount const feeDefault = config.FEES.reference_fee; auto ledger = app.openLedger().current(); // Administrative and identified endpoints are exempt from local fees. diff --git a/src/test/app/FeeVote_test.cpp b/src/test/app/FeeVote_test.cpp index 90dd8fa3dfc..ad38aefb20a 100644 --- a/src/test/app/FeeVote_test.cpp +++ b/src/test/app/FeeVote_test.cpp @@ -29,7 +29,7 @@ class FeeVote_test : public beast::unit_test::suite void testSetup() { - FeeVote::Setup const defaultSetup; + FeeSetup const defaultSetup; { // defaults Section config; diff --git a/src/test/app/LedgerHistory_test.cpp b/src/test/app/LedgerHistory_test.cpp index ba4faa9da05..880cbea5980 100644 --- a/src/test/app/LedgerHistory_test.cpp +++ b/src/test/app/LedgerHistory_test.cpp @@ -81,8 +81,7 @@ class LedgerHistory_test : public beast::unit_test::suite res->setAccepted( res->info().closeTime, res->info().closeTimeResolution, - true /* close time correct*/, - env.app().config()); + true /* close time correct*/); lh.insert(res, false); return res; } diff --git a/src/test/app/LedgerLoad_test.cpp b/src/test/app/LedgerLoad_test.cpp index d78d25ea05a..2685014e474 100644 --- a/src/test/app/LedgerLoad_test.cpp +++ b/src/test/app/LedgerLoad_test.cpp @@ -82,7 +82,7 @@ class LedgerLoad_test : public beast::unit_test::suite retval.ledger = env.rpc("ledger", "current", "full")[jss::result]; BEAST_EXPECT( - retval.ledger[jss::ledger][jss::accountState].size() == 101); + retval.ledger[jss::ledger][jss::accountState].size() == 102); retval.hashes = [&] { for (auto const& it : retval.ledger[jss::ledger][jss::accountState]) @@ -193,7 +193,7 @@ class LedgerLoad_test : public beast::unit_test::suite nullptr, beast::severities::kDisabled); auto jrb = env.rpc("ledger", "current", "full")[jss::result]; - BEAST_EXPECT(jrb[jss::ledger][jss::accountState].size() == 97); + BEAST_EXPECT(jrb[jss::ledger][jss::accountState].size() == 98); BEAST_EXPECT( jrb[jss::ledger][jss::accountState].size() <= sd.ledger[jss::ledger][jss::accountState].size()); diff --git a/src/test/app/LoadFeeTrack_test.cpp b/src/test/app/LoadFeeTrack_test.cpp index cc0b1c19529..f8e73cebd16 100644 --- a/src/test/app/LoadFeeTrack_test.cpp +++ b/src/test/app/LoadFeeTrack_test.cpp @@ -35,7 +35,7 @@ class LoadFeeTrack_test : public beast::unit_test::suite { Fees const fees = [&]() { Fees f; - f.base = d.FEE_DEFAULT; + f.base = d.FEES.reference_fee; f.reserve = 200 * DROPS_PER_XRP; f.increment = 50 * DROPS_PER_XRP; return f; @@ -52,7 +52,7 @@ class LoadFeeTrack_test : public beast::unit_test::suite { Fees const fees = [&]() { Fees f; - f.base = d.FEE_DEFAULT * 10; + f.base = d.FEES.reference_fee * 10; f.reserve = 200 * DROPS_PER_XRP; f.increment = 50 * DROPS_PER_XRP; return f; @@ -69,7 +69,7 @@ class LoadFeeTrack_test : public beast::unit_test::suite { Fees const fees = [&]() { Fees f; - f.base = d.FEE_DEFAULT; + f.base = d.FEES.reference_fee; f.reserve = 200 * DROPS_PER_XRP; f.increment = 50 * DROPS_PER_XRP; return f; diff --git a/src/test/app/NFToken_test.cpp b/src/test/app/NFToken_test.cpp index 81abee34b07..d050579b1e7 100644 --- a/src/test/app/NFToken_test.cpp +++ b/src/test/app/NFToken_test.cpp @@ -215,12 +215,13 @@ class NFToken_test : public beast::unit_test::suite Account const minter{"minter"}; // Fund alice and minter enough to exist, but not enough to meet - // the reserve for creating their first NFT. Account reserve for - // unit tests is 200 XRP, not 20. - env.fund(XRP(200), alice, minter); + // the reserve for creating their first NFT. + auto const acctReserve = env.current()->fees().accountReserve(0); + auto const incReserve = env.current()->fees().increment; + env.fund(acctReserve, alice, minter); env.close(); - BEAST_EXPECT(env.balance(alice) == XRP(200)); - BEAST_EXPECT(env.balance(minter) == XRP(200)); + BEAST_EXPECT(env.balance(alice) == acctReserve); + BEAST_EXPECT(env.balance(minter) == acctReserve); BEAST_EXPECT(ownerCount(env, alice) == 0); BEAST_EXPECT(ownerCount(env, minter) == 0); @@ -233,7 +234,7 @@ class NFToken_test : public beast::unit_test::suite BEAST_EXPECT(burnedCount(env, alice) == 0); // Pay alice almost enough to make the reserve for an NFT page. - env(pay(env.master, alice, XRP(50) + drops(9))); + env(pay(env.master, alice, incReserve + drops(9))); env.close(); // A lambda that checks alice's ownerCount, mintedCount, and diff --git a/src/test/app/Offer_test.cpp b/src/test/app/Offer_test.cpp index 1162612b733..0d1a4326440 100644 --- a/src/test/app/Offer_test.cpp +++ b/src/test/app/Offer_test.cpp @@ -2079,7 +2079,8 @@ class Offer_test : public beast::unit_test::suite BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "100"); jrr = ledgerEntryRoot(env, alice); BEAST_EXPECT( - jrr[jss::node][sfBalance.fieldName] == XRP(350).value().getText()); + jrr[jss::node][sfBalance.fieldName] == + STAmount(env.current()->fees().accountReserve(3)).getText()); jrr = ledgerEntryState(env, bob, gw1, "USD"); BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "-400"); @@ -2176,7 +2177,8 @@ class Offer_test : public beast::unit_test::suite BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "-100"); jrr = ledgerEntryRoot(env, alice); BEAST_EXPECT( - jrr[jss::node][sfBalance.fieldName] == XRP(250).value().getText()); + jrr[jss::node][sfBalance.fieldName] == + STAmount(env.current()->fees().accountReserve(1)).getText()); jrr = ledgerEntryState(env, bob, gw, "USD"); BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "-400"); @@ -2219,7 +2221,8 @@ class Offer_test : public beast::unit_test::suite BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "-200"); jrr = ledgerEntryRoot(env, alice); BEAST_EXPECT( - jrr[jss::node][sfBalance.fieldName] == XRP(250).value().getText()); + jrr[jss::node][sfBalance.fieldName] == + STAmount(env.current()->fees().accountReserve(1)).getText()); jrr = ledgerEntryState(env, bob, gw, "USD"); BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "-300"); diff --git a/src/test/app/RCLValidations_test.cpp b/src/test/app/RCLValidations_test.cpp index 14a54a1492f..0380795a8ae 100644 --- a/src/test/app/RCLValidations_test.cpp +++ b/src/test/app/RCLValidations_test.cpp @@ -106,9 +106,10 @@ class RCLValidations_test : public beast::unit_test::suite *prev, env.app().timeKeeper().closeTime()); // Force a different hash on the first iteration next->updateSkipList(); + BEAST_EXPECT(next->read(keylet::fees())); if (forceHash) { - next->setImmutable(config); + next->setImmutable(); forceHash = false; } diff --git a/src/test/app/TxQ_test.cpp b/src/test/app/TxQ_test.cpp index e25c9f60de1..8bf359e101c 100644 --- a/src/test/app/TxQ_test.cpp +++ b/src/test/app/TxQ_test.cpp @@ -1448,7 +1448,7 @@ class TxQ1_test : public beast::unit_test::suite // These tests may change if TxQ ordering is changed using namespace std::string_literals; BEAST_EXPECTS( - aliceSeq + 1 == env.seq(alice), + aliceSeq == env.seq(alice), "alice: "s + std::to_string(aliceSeq) + ", " + std::to_string(env.seq(alice))); BEAST_EXPECTS( @@ -1460,7 +1460,7 @@ class TxQ1_test : public beast::unit_test::suite "charlie: "s + std::to_string(charlieSeq) + ", " + std::to_string(env.seq(charlie))); BEAST_EXPECTS( - dariaSeq == env.seq(daria), + dariaSeq + 1 == env.seq(daria), "daria: "s + std::to_string(dariaSeq) + ", " + std::to_string(env.seq(daria))); BEAST_EXPECTS( @@ -1472,24 +1472,24 @@ class TxQ1_test : public beast::unit_test::suite "fred: "s + std::to_string(fredSeq) + ", " + std::to_string(env.seq(fred))); BEAST_EXPECTS( - gwenSeq + 1 == env.seq(gwen), + gwenSeq == env.seq(gwen), "gwen: "s + std::to_string(gwenSeq) + ", " + std::to_string(env.seq(gwen))); BEAST_EXPECTS( - hankSeq == env.seq(hank), + hankSeq + 1 == env.seq(hank), "hank: "s + std::to_string(hankSeq) + ", " + std::to_string(env.seq(hank))); // Which sequences get incremented may change if TxQ ordering is // changed - ++aliceSeq; + //++aliceSeq; ++bobSeq; ++(++charlieSeq); - // ++dariaSeq; + ++dariaSeq; ++elmoSeq; // ++fredSeq; - ++gwenSeq; - // ++hankSeq; + //++gwenSeq; + ++hankSeq; auto getTxsQueued = [&]() { auto const txs = env.app().getTxQ().getTxs(); @@ -2939,12 +2939,12 @@ class TxQ1_test : public beast::unit_test::suite // Verify that nothing can be added now that the gap is filled. env(noop(alice), seq(aliceSeq + 20), ter(telCAN_NOT_QUEUE_FULL)); - // Close ledger 6. That removes 6 of alice's transactions, - // but alice adds one more transaction at seq(aliceSeq + 20) so - // we only see a reduction by 5. + // Close ledger 6. That removes some of alice's transactions, + // but alice adds some more transaction(s) so expectedCount + // may not reduce to 8. env.close(); checkMetrics(__LINE__, env, 9, 50, 6, 5, 256); - BEAST_EXPECT(env.seq(alice) == aliceSeq + 15); + BEAST_EXPECT(env.seq(alice) == aliceSeq + 13); // Close ledger 7. That should remove 7 more of alice's transactions. env.close(); diff --git a/src/test/jtx/impl/envconfig.cpp b/src/test/jtx/impl/envconfig.cpp index f34a444fa5f..77c43f5e40a 100644 --- a/src/test/jtx/impl/envconfig.cpp +++ b/src/test/jtx/impl/envconfig.cpp @@ -17,9 +17,11 @@ */ //============================================================================== +#include + #include #include -#include +#include namespace ripple { namespace test { @@ -40,6 +42,13 @@ setupConfigForUnitTests(Config& cfg) std::string port_rpc = std::to_string(port_base + 1); std::string port_ws = std::to_string(port_base + 2); + using namespace jtx; + // Default fees to old values, so tests don't have to worry about changes in + // Config.h + cfg.FEES.reference_fee = 10; + cfg.FEES.account_reserve = XRP(200).value().xrp().drops(); + cfg.FEES.owner_reserve = XRP(50).value().xrp().drops(); + cfg.overwrite(ConfigSection::nodeDatabase(), "type", "memory"); cfg.overwrite(ConfigSection::nodeDatabase(), "path", "main"); cfg.deprecatedClearSection(ConfigSection::importNodeDatabase()); diff --git a/src/test/rpc/LedgerClosed_test.cpp b/src/test/rpc/LedgerClosed_test.cpp index c5073db328e..2f81031f85c 100644 --- a/src/test/rpc/LedgerClosed_test.cpp +++ b/src/test/rpc/LedgerClosed_test.cpp @@ -37,7 +37,7 @@ class LedgerClosed_test : public beast::unit_test::suite auto lc_result = env.rpc("ledger_closed")[jss::result]; BEAST_EXPECT( lc_result[jss::ledger_hash] == - "A15F7FBE0B06286915D971BF9802C9431CD7DE40E2AC7D07C409EDB1C0715C60"); + "CCC3B3E88CCAC17F1BE6B4A648A55999411F19E3FE55EB721960EB0DF28EDDA5"); BEAST_EXPECT(lc_result[jss::ledger_index] == 2); env.close(); @@ -52,7 +52,7 @@ class LedgerClosed_test : public beast::unit_test::suite lc_result = env.rpc("ledger_closed")[jss::result]; BEAST_EXPECT( lc_result[jss::ledger_hash] == - "2E81FC6EC0DD943197E0C7E3FBE9AE307F2775F2F7485BB37307984C3C0F2340"); + "E86DE7F3D7A4D9CE17EF7C8BA08A8F4D8F643B9552F0D895A31CDA78F541DE4E"); BEAST_EXPECT(lc_result[jss::ledger_index] == 3); } diff --git a/src/test/rpc/LedgerData_test.cpp b/src/test/rpc/LedgerData_test.cpp index 1c55e907062..ab520181c05 100644 --- a/src/test/rpc/LedgerData_test.cpp +++ b/src/test/rpc/LedgerData_test.cpp @@ -123,7 +123,7 @@ class LedgerData_test : public beast::unit_test::suite jrr[jss::ledger_current_index].isIntegral() && jrr[jss::ledger_current_index].asInt() > 0); BEAST_EXPECT(!jrr.isMember(jss::marker)); - BEAST_EXPECT(checkArraySize(jrr[jss::state], num_accounts + 3)); + BEAST_EXPECT(checkArraySize(jrr[jss::state], num_accounts + 4)); } void diff --git a/src/test/rpc/LedgerRPC_test.cpp b/src/test/rpc/LedgerRPC_test.cpp index 5494a81da63..6644e15e959 100644 --- a/src/test/rpc/LedgerRPC_test.cpp +++ b/src/test/rpc/LedgerRPC_test.cpp @@ -237,7 +237,7 @@ class LedgerRPC_test : public beast::unit_test::suite env.rpc("json", "ledger", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState)); BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray()); - BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 2u); + BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 3u); } void @@ -276,7 +276,7 @@ class LedgerRPC_test : public beast::unit_test::suite env.rpc("json", "ledger", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState)); BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray()); - BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 2u); + BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 3u); } void @@ -1315,11 +1315,12 @@ class LedgerRPC_test : public beast::unit_test::suite } { + std::string const hash3{ + "E86DE7F3D7A4D9CE17EF7C8BA08A8F4D" + "8F643B9552F0D895A31CDA78F541DE4E"}; // access via the ledger_hash field Json::Value jvParams; - jvParams[jss::ledger_hash] = - "2E81FC6EC0DD943197E0C7E3FBE9AE30" - "7F2775F2F7485BB37307984C3C0F2340"; + jvParams[jss::ledger_hash] = hash3; auto jrr = env.rpc( "json", "ledger", @@ -1328,11 +1329,8 @@ class LedgerRPC_test : public beast::unit_test::suite BEAST_EXPECT(jrr.isMember(jss::ledger_hash)); BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == "3"); - // extra leading hex chars in hash will be ignored - jvParams[jss::ledger_hash] = - "DEADBEEF" - "2E81FC6EC0DD943197E0C7E3FBE9AE30" - "7F2775F2F7485BB37307984C3C0F2340"; + // extra leading hex chars in hash are not allowed + jvParams[jss::ledger_hash] = "DEADBEEF" + hash3; jrr = env.rpc( "json", "ledger", @@ -1535,7 +1533,7 @@ class LedgerRPC_test : public beast::unit_test::suite env.close(); jrr = env.rpc("json", "ledger", to_string(jv))[jss::result]; - const std::string txid1 = [&]() { + const std::string txid0 = [&]() { auto const& parentHash = env.current()->info().parentHash; if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2)) { @@ -1579,22 +1577,22 @@ class LedgerRPC_test : public beast::unit_test::suite if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2)) { auto const& parentHash = env.current()->info().parentHash; - auto const txid0 = [&]() { - auto const& txj = jrr[jss::queue_data][0u]; + auto const txid1 = [&]() { + auto const& txj = jrr[jss::queue_data][1u]; BEAST_EXPECT(txj[jss::account] == alice.human()); BEAST_EXPECT(txj[jss::fee_level] == "256"); BEAST_EXPECT(txj["preflight_result"] == "tesSUCCESS"); BEAST_EXPECT(txj.isMember(jss::tx)); return txj[jss::tx].asString(); }(); - auto const& txj = jrr[jss::queue_data][1u]; + auto const& txj = jrr[jss::queue_data][0u]; BEAST_EXPECT(txj[jss::account] == alice.human()); BEAST_EXPECT(txj[jss::fee_level] == "256"); BEAST_EXPECT(txj["preflight_result"] == "tesSUCCESS"); BEAST_EXPECT(txj["retries_remaining"] == 9); BEAST_EXPECT(txj["last_result"] == "terPRE_SEQ"); BEAST_EXPECT(txj.isMember(jss::tx)); - BEAST_EXPECT(txj[jss::tx] == txid1); + BEAST_EXPECT(txj[jss::tx] == txid0); uint256 tx0, tx1; BEAST_EXPECT(tx0.parseHex(txid0)); BEAST_EXPECT(tx1.parseHex(txid1)); @@ -1647,7 +1645,7 @@ class LedgerRPC_test : public beast::unit_test::suite BEAST_EXPECT(txj["retries_remaining"] == 1); BEAST_EXPECT(txj["last_result"] == "terPRE_SEQ"); BEAST_EXPECT(txj.isMember(jss::tx)); - BEAST_EXPECT(txj[jss::tx] != txid1); + BEAST_EXPECT(txj[jss::tx] != txid0); return txj[jss::tx].asString(); } return std::string{}; diff --git a/src/test/rpc/LedgerRequestRPC_test.cpp b/src/test/rpc/LedgerRequestRPC_test.cpp index de2ddeff8e4..14d06e9234b 100644 --- a/src/test/rpc/LedgerRequestRPC_test.cpp +++ b/src/test/rpc/LedgerRequestRPC_test.cpp @@ -30,6 +30,14 @@ namespace RPC { class LedgerRequestRPC_test : public beast::unit_test::suite { + static constexpr char const* hash1 = + "3020EB9E7BE24EF7D7A060CB051583EC117384636D1781AFB5B87F3E348DA489"; + static constexpr char const* accounthash1 = + "BD8A3D72CA73DDE887AD63666EC2BAD07875CBA997A102579B5B95ECDFFEAED8"; + + static constexpr char const* zerohash = + "0000000000000000000000000000000000000000000000000000000000000000"; + public: void testLedgerRequest() @@ -181,87 +189,69 @@ class LedgerRequestRPC_test : public beast::unit_test::suite BEAST_EXPECT( result[jss::ledger][jss::total_coins] == "100000000000000000"); BEAST_EXPECT(result[jss::ledger][jss::closed] == true); - BEAST_EXPECT( - result[jss::ledger][jss::ledger_hash] == - "E9BB323980D202EC7E51BAB2AA8E35353F9C7BDAB59BF17378EADD4D0486EF9F"); - BEAST_EXPECT( - result[jss::ledger][jss::parent_hash] == - "0000000000000000000000000000000000000000000000000000000000000000"); - BEAST_EXPECT( - result[jss::ledger][jss::account_hash] == - "A21ED30C04C88046FC61DB9DC19375EEDBD365FD8C17286F27127DF804E9CAA6"); - BEAST_EXPECT( - result[jss::ledger][jss::transaction_hash] == - "0000000000000000000000000000000000000000000000000000000000000000"); + BEAST_EXPECT(result[jss::ledger][jss::ledger_hash] == hash1); + BEAST_EXPECT(result[jss::ledger][jss::parent_hash] == zerohash); + BEAST_EXPECT(result[jss::ledger][jss::account_hash] == accounthash1); + BEAST_EXPECT(result[jss::ledger][jss::transaction_hash] == zerohash); result = env.rpc("ledger_request", "2")[jss::result]; + constexpr char const* hash2 = + "CCC3B3E88CCAC17F1BE6B4A648A55999411F19E3FE55EB721960EB0DF28EDDA5"; BEAST_EXPECT(result[jss::ledger][jss::ledger_index] == "2"); BEAST_EXPECT( result[jss::ledger][jss::total_coins] == "100000000000000000"); BEAST_EXPECT(result[jss::ledger][jss::closed] == true); - BEAST_EXPECT( - result[jss::ledger][jss::ledger_hash] == - "A15F7FBE0B06286915D971BF9802C9431CD7DE40E2AC7D07C409EDB1C0715C60"); - BEAST_EXPECT( - result[jss::ledger][jss::parent_hash] == - "E9BB323980D202EC7E51BAB2AA8E35353F9C7BDAB59BF17378EADD4D0486EF9F"); + BEAST_EXPECT(result[jss::ledger][jss::ledger_hash] == hash2); + BEAST_EXPECT(result[jss::ledger][jss::parent_hash] == hash1); BEAST_EXPECT( result[jss::ledger][jss::account_hash] == - "CB07F3CA0398BE969A5B88F874629D4DBB6E103DE7C6DB8037281A89E51AA8C6"); - BEAST_EXPECT( - result[jss::ledger][jss::transaction_hash] == - "0000000000000000000000000000000000000000000000000000000000000000"); + "3C834285F7F464FBE99AFEB84D354A968EB2CAA24523FF26797A973D906A3D29"); + BEAST_EXPECT(result[jss::ledger][jss::transaction_hash] == zerohash); result = env.rpc("ledger_request", "3")[jss::result]; + constexpr char const* hash3 = + "8D631B20BC989AF568FBA97375290544B0703A5ADC1CF9E9053580461690C9EE"; BEAST_EXPECT(result[jss::ledger][jss::ledger_index] == "3"); BEAST_EXPECT( result[jss::ledger][jss::total_coins] == "99999999999999980"); BEAST_EXPECT(result[jss::ledger][jss::closed] == true); - BEAST_EXPECT( - result[jss::ledger][jss::ledger_hash] == - "9BCA8AE5FD41D223D82E1B8288961D693EB1B2EFA10F51827A641AD4B12111D7"); - BEAST_EXPECT( - result[jss::ledger][jss::parent_hash] == - "A15F7FBE0B06286915D971BF9802C9431CD7DE40E2AC7D07C409EDB1C0715C60"); + BEAST_EXPECT(result[jss::ledger][jss::ledger_hash] == hash3); + BEAST_EXPECT(result[jss::ledger][jss::parent_hash] == hash2); BEAST_EXPECT( result[jss::ledger][jss::account_hash] == - "5B793533909906D15CE27D1A423732D113160AB166188D89A2DFD8737CBDCBD5"); + "BC9EF2A16BFF80BCFABA6FA84688D858D33BD0FA0435CAA9DF6DA4105A39A29E"); BEAST_EXPECT( result[jss::ledger][jss::transaction_hash] == "0213EC486C058B3942FBE3DAC6839949A5C5B02B8B4244C8998EFDF04DBD8222"); result = env.rpc("ledger_request", "4")[jss::result]; + constexpr char const* hash4 = + "1A8E7098B23597E73094DADA58C9D62F3AB93A12C6F7666D56CA85A6CFDE530F"; BEAST_EXPECT(result[jss::ledger][jss::ledger_index] == "4"); BEAST_EXPECT( result[jss::ledger][jss::total_coins] == "99999999999999960"); BEAST_EXPECT(result[jss::ledger][jss::closed] == true); - BEAST_EXPECT( - result[jss::ledger][jss::ledger_hash] == - "433D1E42F2735F926BF594E4F3DFC70AE3E74F51464156ED83A33D0FF121D136"); - BEAST_EXPECT( - result[jss::ledger][jss::parent_hash] == - "9BCA8AE5FD41D223D82E1B8288961D693EB1B2EFA10F51827A641AD4B12111D7"); + BEAST_EXPECT(result[jss::ledger][jss::ledger_hash] == hash4); + BEAST_EXPECT(result[jss::ledger][jss::parent_hash] == hash3); BEAST_EXPECT( result[jss::ledger][jss::account_hash] == - "39C91E2227ACECD057AFDC64AE8FEFF5A0E07CF26ED29D1AECC55B0385F3EFDE"); + "C690188F123C91355ADA8BDF4AC5B5C927076D3590C215096868A5255264C6DD"); BEAST_EXPECT( result[jss::ledger][jss::transaction_hash] == "3CBDB8F42E04333E1642166BFB93AC9A7E1C6C067092CD5D881D6F3AB3D67E76"); result = env.rpc("ledger_request", "5")[jss::result]; + constexpr char const* hash5 = + "C6A222D71AE65D7B4F240009EAD5DEB20D7EEDE5A4064F28BBDBFEEB6FBE48E5"; BEAST_EXPECT(result[jss::ledger][jss::ledger_index] == "5"); BEAST_EXPECT( result[jss::ledger][jss::total_coins] == "99999999999999940"); BEAST_EXPECT(result[jss::ledger][jss::closed] == true); - BEAST_EXPECT( - result[jss::ledger][jss::ledger_hash] == - "9ED4D0C397810980904AF3FC08583D23B09C3C7CCF835D2A4768145A8BAC1175"); - BEAST_EXPECT( - result[jss::ledger][jss::parent_hash] == - "433D1E42F2735F926BF594E4F3DFC70AE3E74F51464156ED83A33D0FF121D136"); + BEAST_EXPECT(result[jss::ledger][jss::ledger_hash] == hash5); + BEAST_EXPECT(result[jss::ledger][jss::parent_hash] == hash4); BEAST_EXPECT( result[jss::ledger][jss::account_hash] == - "8F047B6A0D2083DF4F69C17F7CC9AE997B0D59020A43D9799A31D22F55837147"); + "EA81CD9D36740736F00CB747E0D0E32D3C10B695823D961F0FB9A1CE7133DD4D"); BEAST_EXPECT( result[jss::ledger][jss::transaction_hash] == "C3D086CD6BDB9E97AD1D513B2C049EF2840BD21D0B3E22D84EBBB89B6D2EF59D"); @@ -340,18 +330,10 @@ class LedgerRequestRPC_test : public beast::unit_test::suite BEAST_EXPECT( result[jss::ledger][jss::total_coins] == "100000000000000000"); BEAST_EXPECT(result[jss::ledger][jss::closed] == true); - BEAST_EXPECT( - result[jss::ledger][jss::ledger_hash] == - "E9BB323980D202EC7E51BAB2AA8E35353F9C7BDAB59BF17378EADD4D0486EF9F"); - BEAST_EXPECT( - result[jss::ledger][jss::parent_hash] == - "0000000000000000000000000000000000000000000000000000000000000000"); - BEAST_EXPECT( - result[jss::ledger][jss::account_hash] == - "A21ED30C04C88046FC61DB9DC19375EEDBD365FD8C17286F27127DF804E9CAA6"); - BEAST_EXPECT( - result[jss::ledger][jss::transaction_hash] == - "0000000000000000000000000000000000000000000000000000000000000000"); + BEAST_EXPECT(result[jss::ledger][jss::ledger_hash] == hash1); + BEAST_EXPECT(result[jss::ledger][jss::parent_hash] == zerohash); + BEAST_EXPECT(result[jss::ledger][jss::account_hash] == accounthash1); + BEAST_EXPECT(result[jss::ledger][jss::transaction_hash] == zerohash); } void diff --git a/src/test/rpc/ReportingETL_test.cpp b/src/test/rpc/ReportingETL_test.cpp index d8e6fc684fd..77284dd776d 100644 --- a/src/test/rpc/ReportingETL_test.cpp +++ b/src/test/rpc/ReportingETL_test.cpp @@ -532,7 +532,7 @@ class ReportingETL_test : public beast::unit_test::suite BEAST_EXPECT(status.ok()); BEAST_EXPECT( - reply.ledger_objects().objects_size() == num_accounts + 3); + reply.ledger_objects().objects_size() == num_accounts + 4); BEAST_EXPECT(reply.marker().size() == 0); auto ledger = env.closed(); size_t idx = 0;