diff --git a/src/ripple/app/ledger/Ledger.cpp b/src/ripple/app/ledger/Ledger.cpp index 5448d56c7..c72537eaf 100644 --- a/src/ripple/app/ledger/Ledger.cpp +++ b/src/ripple/app/ledger/Ledger.cpp @@ -192,7 +192,7 @@ Ledger::Ledger (create_genesis_t, Config const& config) updateHash(); setClosed(); setAccepted(); - setFees(config); + setup(config); } Ledger::Ledger (uint256 const& parentHash, @@ -240,7 +240,7 @@ Ledger::Ledger (uint256 const& parentHash, txMap_->setImmutable (); stateMap_->setImmutable (); - setFees(config); + setup(config); } // Create a new ledger that's a snapshot of this one @@ -296,7 +296,7 @@ Ledger::Ledger (void const* data, { SerialIter sit (data, size); setRaw (sit, hasPrefix); - // We can't set the fees until the stateMap is populated + // Can't set up until the stateMap is filled in } Ledger::Ledger (std::uint32_t ledgerSeq, @@ -312,7 +312,7 @@ Ledger::Ledger (std::uint32_t ledgerSeq, info_.seq = ledgerSeq; info_.closeTime = closeTime; info_.closeTimeResolution = ledgerDefaultTimeResolution; - setFees(config); + setup(config); } //------------------------------------------------------------------------------ @@ -332,7 +332,7 @@ void Ledger::setImmutable () txMap_->setImmutable (); if (stateMap_) stateMap_->setImmutable (); - setFees (getConfig ()); + setup(getConfig ()); } void Ledger::updateHash() @@ -1066,7 +1066,7 @@ Ledger::rawTxInsert (uint256 const& key, } void -Ledger::setFees (Config const& config) +Ledger::setup (Config const& config) { fees_.base = config.FEE_DEFAULT; fees_.units = config.TRANSACTION_FEE_BASE; @@ -1089,6 +1089,7 @@ Ledger::setFees (Config const& config) if (sle->getFieldIndex (sfReserveIncrement) != -1) fees_.increment = sle->getFieldU32 (sfReserveIncrement); } + rules_ = Rules(*this); } std::shared_ptr diff --git a/src/ripple/app/ledger/Ledger.h b/src/ripple/app/ledger/Ledger.h index 182bd32d0..303d43b58 100644 --- a/src/ripple/app/ledger/Ledger.h +++ b/src/ripple/app/ledger/Ledger.h @@ -142,6 +142,12 @@ public: return fees_; } + Rules const& + rules() const override + { + return rules_; + } + bool exists (Keylet const& k) const override; @@ -379,7 +385,7 @@ private: bool saveValidatedLedger (bool current); void - setFees (Config const& config); + setup (Config const& config); std::shared_ptr peek (Keylet const& k) const; @@ -406,6 +412,7 @@ private: std::mutex mutable mutex_; Fees fees_; + Rules rules_; LedgerInfo info_; // Ripple cost of the reference transaction diff --git a/src/ripple/app/ledger/OpenLedger.h b/src/ripple/app/ledger/OpenLedger.h index bbb9ca052..37f92d398 100644 --- a/src/ripple/app/ledger/OpenLedger.h +++ b/src/ripple/app/ledger/OpenLedger.h @@ -143,14 +143,16 @@ public: The current view is atomically set to the new open view. + @param rules The rules for the open ledger @param ledger A new closed ledger */ void - accept(std::shared_ptr const& ledger, - OrderedTxs const& locals, bool retriesFirst, - OrderedTxs& retries, ApplyFlags flags, - IHashRouter& router, - std::string const& suffix = ""); + accept (Rules const& rules, + std::shared_ptr const& ledger, + OrderedTxs const& locals, bool retriesFirst, + OrderedTxs& retries, ApplyFlags flags, + IHashRouter& router, + std::string const& suffix = ""); /** Algorithm for applying transactions. @@ -174,8 +176,8 @@ private: }; std::shared_ptr - create (std::shared_ptr< - Ledger const> const& ledger); + create (Rules const& rules, + std::shared_ptr const& ledger); static Result diff --git a/src/ripple/app/ledger/impl/LedgerConsensusImp.cpp b/src/ripple/app/ledger/impl/LedgerConsensusImp.cpp index 656ba703a..a5636245d 100644 --- a/src/ripple/app/ledger/impl/LedgerConsensusImp.cpp +++ b/src/ripple/app/ledger/impl/LedgerConsensusImp.cpp @@ -1157,8 +1157,15 @@ void LedgerConsensusImp::accept (std::shared_ptr set) ledgerMaster_.pushLedger (newLCL, newOL); #if RIPPLE_OPEN_LEDGER - getApp().openLedger().accept(newLCL, - localTx, anyDisputes, retries, tapNONE, + auto const lastVal = + getApp().getLedgerMaster().getValidatedLedger(); + boost::optional rules; + if (lastVal) + rules.emplace(*lastVal); + else + rules.emplace(); + getApp().openLedger().accept(*rules, + newLCL, localTx, anyDisputes, retries, tapNONE, getApp().getHashRouter(), "consensus"); getApp().openLedger().verify(*newOL, "consensus after"); #endif diff --git a/src/ripple/app/ledger/impl/OpenLedger.cpp b/src/ripple/app/ledger/impl/OpenLedger.cpp index 46b0c2ddb..7f467cca5 100644 --- a/src/ripple/app/ledger/impl/OpenLedger.cpp +++ b/src/ripple/app/ledger/impl/OpenLedger.cpp @@ -32,7 +32,7 @@ OpenLedger::OpenLedger(std::shared_ptr< : j_ (journal) , cache_ (cache) , config_ (config) - , current_ (create(ledger)) + , current_ (create(ledger->rules(), ledger)) { } @@ -73,15 +73,15 @@ OpenLedger::modify (std::function< } void -OpenLedger::accept(std::shared_ptr< - Ledger const> const& ledger, +OpenLedger::accept(Rules const& rules, + std::shared_ptr const& ledger, OrderedTxs const& locals, bool retriesFirst, OrderedTxs& retries, ApplyFlags flags, IHashRouter& router, std::string const& suffix) { JLOG(j_.error) << "accept ledger " << ledger->seq() << " " << suffix; - auto next = create(ledger); + auto next = create(rules, ledger); if (retriesFirst) { // Handle disputed tx, outside lock @@ -121,11 +121,11 @@ OpenLedger::accept(std::shared_ptr< //------------------------------------------------------------------------------ std::shared_ptr -OpenLedger::create(std::shared_ptr< - Ledger const> const& ledger) +OpenLedger::create (Rules const& rules, + std::shared_ptr const& ledger) { return std::make_shared( - open_ledger, std::make_shared< + open_ledger, rules, std::make_shared< CachedLedger const>(ledger, cache_)); } diff --git a/src/ripple/app/misc/NetworkOPs.cpp b/src/ripple/app/misc/NetworkOPs.cpp index ef2750857..c385091b1 100644 --- a/src/ripple/app/misc/NetworkOPs.cpp +++ b/src/ripple/app/misc/NetworkOPs.cpp @@ -1322,7 +1322,14 @@ void NetworkOPsImp::switchLastClosedLedger ( #if RIPPLE_OPEN_LEDGER auto retries = localTx; - getApp().openLedger().accept( + auto const lastVal = + getApp().getLedgerMaster().getValidatedLedger(); + boost::optional rules; + if (lastVal) + rules.emplace(*lastVal); + else + rules.emplace(); + getApp().openLedger().accept(*rules, newLCL, OrderedTxs({}), false, retries, tapNONE, getApp().getHashRouter(), "jump"); getApp().openLedger().verify( diff --git a/src/ripple/app/paths/RippleLineCache.cpp b/src/ripple/app/paths/RippleLineCache.cpp index 816b7a309..11c773d0b 100644 --- a/src/ripple/app/paths/RippleLineCache.cpp +++ b/src/ripple/app/paths/RippleLineCache.cpp @@ -28,6 +28,7 @@ RippleLineCache::RippleLineCache( { // We want the caching that OpenView provides // And we need to own a shared_ptr to the input view + // VFALCO TODO This should be a CachedLedger mLedger = std::make_shared(&*ledger, ledger); } diff --git a/src/ripple/ledger/ApplyViewImpl.h b/src/ripple/ledger/ApplyViewImpl.h index 16aef0ac5..5786f9cba 100644 --- a/src/ripple/ledger/ApplyViewImpl.h +++ b/src/ripple/ledger/ApplyViewImpl.h @@ -53,8 +53,8 @@ public: ApplyViewImpl (ApplyViewImpl&&) = default; #endif - ApplyViewImpl (ReadView const* base, - ApplyFlags flags); + ApplyViewImpl( + ReadView const* base, ApplyFlags flags); /** Apply the transaction. diff --git a/src/ripple/ledger/CachedView.h b/src/ripple/ledger/CachedView.h index 8825e16f6..76e519450 100644 --- a/src/ripple/ledger/CachedView.h +++ b/src/ripple/ledger/CachedView.h @@ -77,6 +77,12 @@ public: return base_.fees(); } + Rules const& + rules() const override + { + return base_.rules(); + } + boost::optional succ (key_type const& key, boost::optional< key_type> last = boost::none) const override diff --git a/src/ripple/ledger/OpenView.h b/src/ripple/ledger/OpenView.h index c8e74bb97..e1a0b5cd1 100644 --- a/src/ripple/ledger/OpenView.h +++ b/src/ripple/ledger/OpenView.h @@ -54,6 +54,7 @@ private: Serializer const>, std::shared_ptr< Serializer const>>>; + Rules rules_; txs_map txs_; LedgerInfo info_; ReadView const* base_; @@ -69,6 +70,7 @@ public: OpenView (OpenView&& other) : ReadView (std::move(other)) , TxsRawView (std::move(other)) + , rules_ (std::move(other.rules_)) , txs_ (std::move(other.txs_)) , info_ (std::move(other.info_)) , base_ (std::move(other.base_)) @@ -108,16 +110,20 @@ public: ownership of a copy of `hold` until the MetaView is destroyed. + Calls to rules() will return the + rules provided on construction. + The tx list starts empty and will contain all newly inserted tx. */ /** @{ */ - OpenView (open_ledger_t, ReadView const* base, - std::shared_ptr hold = nullptr); + OpenView (open_ledger_t, + ReadView const* base, Rules const& rules, + std::shared_ptr hold = nullptr); - OpenView (open_ledger_t, std::shared_ptr< - ReadView const> const& base) - : OpenView (open_ledger, &*base, base) + OpenView (open_ledger_t, Rules const& rules, + std::shared_ptr const& base) + : OpenView (open_ledger, &*base, rules, base) { } /** @} */ @@ -128,6 +134,8 @@ public: The LedgerInfo is copied from the base. + The rules are inherited from the base. + The tx list starts empty and will contain all newly inserted tx. */ @@ -154,6 +162,9 @@ public: Fees const& fees() const override; + Rules const& + rules() const override; + bool exists (Keylet const& k) const override; diff --git a/src/ripple/ledger/PaymentSandbox.h b/src/ripple/ledger/PaymentSandbox.h index 853cdf088..b1fc17a69 100644 --- a/src/ripple/ledger/PaymentSandbox.h +++ b/src/ripple/ledger/PaymentSandbox.h @@ -107,8 +107,7 @@ public: PaymentSandbox (PaymentSandbox&&) = default; #endif - PaymentSandbox (ReadView const* base, - ApplyFlags flags) + PaymentSandbox (ReadView const* base, ApplyFlags flags) : ApplyViewBase (base, flags) { } @@ -134,14 +133,14 @@ public: /** @{ */ explicit PaymentSandbox (PaymentSandbox const* base) - : ApplyViewBase (base, base->flags()) + : ApplyViewBase(base, base->flags()) , ps_ (base) { } explicit PaymentSandbox (PaymentSandbox* base) - : ApplyViewBase (base, base->flags()) + : ApplyViewBase(base, base->flags()) , ps_ (base) { } diff --git a/src/ripple/ledger/ReadView.h b/src/ripple/ledger/ReadView.h index d4135ee34..17124018a 100644 --- a/src/ripple/ledger/ReadView.h +++ b/src/ripple/ledger/ReadView.h @@ -104,17 +104,59 @@ struct LedgerInfo std::uint32_t closeTime = 0; }; -// ledger close flags -static -std::uint32_t const sLCF_NoConsensusTime = 1; +//------------------------------------------------------------------------------ -inline -bool getCloseAgree (LedgerInfo const& info) +class DigestAwareReadView; + +/** Rules controlling protocol behavior. */ +class Rules { - return (info.closeFlags & sLCF_NoConsensusTime) == 0; -} +private: + class Impl; -void addRaw (LedgerInfo const&, Serializer&); + std::shared_ptr impl_; + +public: + Rules (Rules const&) = default; + Rules& operator= (Rules const&) = default; + + /** Construct an empty rule set. + + These are the rules reflected by + the genesis ledger. + */ + Rules() = default; + + /** Construct rules from a ledger. + + The ledger contents are analyzed for rules + and amendments and extracted to the object. + */ + explicit + Rules (DigestAwareReadView const& ledger); + + /** Returns `true` if a feature is enabled. */ + bool + enabled (uint256 const& feature) const; + + /** Returns `true` if these rules don't match the ledger. */ + bool + changed (DigestAwareReadView const& ledger) const; + + /** Returns `true` if two rule sets are identical. + + @note This is for diagnostics. To determine if new + rules should be constructed, call changed() first instead. + */ + bool + operator== (Rules const&) const; + + bool + operator!= (Rules const& other) const + { + return ! (*this == other); + } +}; //------------------------------------------------------------------------------ @@ -214,6 +256,11 @@ public: Fees const& fees() const = 0; + /** Returns the tx processing rules. */ + virtual + Rules const& + rules() const = 0; + /** Determine if a state item exists. @note This can be more efficient than calling read. @@ -344,6 +391,20 @@ public: digest (key_type const& key) const = 0; }; +//------------------------------------------------------------------------------ + +// ledger close flags +static +std::uint32_t const sLCF_NoConsensusTime = 1; + +inline +bool getCloseAgree (LedgerInfo const& info) +{ + return (info.closeFlags & sLCF_NoConsensusTime) == 0; +} + +void addRaw (LedgerInfo const&, Serializer&); + } // ripple #include diff --git a/src/ripple/ledger/Sandbox.h b/src/ripple/ledger/Sandbox.h index 9de4d1c1a..371205972 100644 --- a/src/ripple/ledger/Sandbox.h +++ b/src/ripple/ledger/Sandbox.h @@ -49,14 +49,13 @@ public: Sandbox (Sandbox&&) = default; #endif - Sandbox (ReadView const* base, - ApplyFlags flags) + Sandbox (ReadView const* base, ApplyFlags flags) : ApplyViewBase (base, flags) { } Sandbox (ApplyView const* base) - : Sandbox (base, base->flags()) + : Sandbox(base, base->flags()) { } diff --git a/src/ripple/ledger/detail/ApplyViewBase.h b/src/ripple/ledger/detail/ApplyViewBase.h index 4165e8a4b..7d76c85ea 100644 --- a/src/ripple/ledger/detail/ApplyViewBase.h +++ b/src/ripple/ledger/detail/ApplyViewBase.h @@ -52,8 +52,8 @@ public: ApplyViewBase (ApplyViewBase&&) = default; #endif - ApplyViewBase (ReadView const* base, - ApplyFlags flags); + ApplyViewBase( + ReadView const* base, ApplyFlags flags); // ReadView @@ -63,6 +63,9 @@ public: Fees const& fees() const override; + Rules const& + rules() const override; + bool exists (Keylet const& k) const override; diff --git a/src/ripple/ledger/impl/ApplyViewBase.cpp b/src/ripple/ledger/impl/ApplyViewBase.cpp index 14853ec12..143bd1add 100644 --- a/src/ripple/ledger/impl/ApplyViewBase.cpp +++ b/src/ripple/ledger/impl/ApplyViewBase.cpp @@ -25,8 +25,7 @@ namespace ripple { namespace detail { ApplyViewBase::ApplyViewBase( - ReadView const* base, - ApplyFlags flags) + ReadView const* base, ApplyFlags flags) : flags_ (flags) , base_ (base) { @@ -46,6 +45,12 @@ ApplyViewBase::fees() const return base_->fees(); } +Rules const& +ApplyViewBase::rules() const +{ + return base_->rules(); +} + bool ApplyViewBase::exists (Keylet const& k) const { diff --git a/src/ripple/ledger/impl/ApplyViewImpl.cpp b/src/ripple/ledger/impl/ApplyViewImpl.cpp index 8edb0c7c1..6d2634f98 100644 --- a/src/ripple/ledger/impl/ApplyViewImpl.cpp +++ b/src/ripple/ledger/impl/ApplyViewImpl.cpp @@ -20,12 +20,12 @@ #include #include #include +#include namespace ripple { ApplyViewImpl::ApplyViewImpl( - ReadView const* base, - ApplyFlags flags) + ReadView const* base, ApplyFlags flags) : ApplyViewBase (base, flags) { } diff --git a/src/ripple/ledger/impl/OpenView.cpp b/src/ripple/ledger/impl/OpenView.cpp index 659f6de6c..cf40cabcd 100644 --- a/src/ripple/ledger/impl/OpenView.cpp +++ b/src/ripple/ledger/impl/OpenView.cpp @@ -89,9 +89,10 @@ public: //------------------------------------------------------------------------------ OpenView::OpenView (open_ledger_t, - ReadView const* base, + ReadView const* base, Rules const& rules, std::shared_ptr hold) - : info_ (base->info()) + : rules_ (rules) + , info_ (base->info()) , base_ (base) , hold_ (std::move(hold)) { @@ -102,7 +103,8 @@ OpenView::OpenView (open_ledger_t, OpenView::OpenView (ReadView const* base, std::shared_ptr hold) - : info_ (base->info()) + : rules_ (base->rules()) + , info_ (base->info()) , base_ (base) , hold_ (std::move(hold)) { @@ -138,6 +140,12 @@ OpenView::fees() const return base_->fees(); } +Rules const& +OpenView::rules() const +{ + return rules_; +} + bool OpenView::exists (Keylet const& k) const { diff --git a/src/ripple/ledger/impl/ReadView.cpp b/src/ripple/ledger/impl/ReadView.cpp index 884ef4dac..ee941d5fb 100644 --- a/src/ripple/ledger/impl/ReadView.cpp +++ b/src/ripple/ledger/impl/ReadView.cpp @@ -19,9 +19,105 @@ #include #include +#include namespace ripple { +class Rules::Impl +{ +private: + std::unordered_set> set_; + boost::optional digest_; + +public: + Impl (DigestAwareReadView const& ledger) + { + auto const k = keylet::amendments(); + digest_ = ledger.digest(k.key); + if (! digest_) + return; + auto const sle = ledger.read(k); + if (! sle) + { + // LogicError() ? + return; + } + + for (auto const& item : + sle->getFieldV256(sfAmendments)) + set_.insert(item); + } + + bool + enabled (uint256 const& feature) const + { + return set_.count(feature) > 0; + } + + bool + changed (DigestAwareReadView const& ledger) const + { + auto const digest = + ledger.digest(keylet::amendments().key); + if (! digest && ! digest_) + return false; + if (! digest || ! digest_) + return true; + return *digest != *digest_; + } + + bool + operator== (Impl const& other) const + { + if (! digest_ && ! other.digest_) + return true; + if (! digest_ || ! other.digest_) + return false; + return *digest_ == *other.digest_; + } +}; + +//------------------------------------------------------------------------------ + +Rules::Rules (DigestAwareReadView const& ledger) + : impl_(std::make_shared(ledger)) +{ +} + +bool +Rules::enabled (uint256 const& feature) const +{ + if (! impl_) + return false; + return impl_->enabled(feature); +} + +bool +Rules::changed (DigestAwareReadView const& ledger) const +{ + if (! impl_) + return static_cast( + ledger.digest(keylet::amendments().key)); + return impl_->changed(ledger); +} + +bool +Rules::operator== (Rules const& other) const +{ +#if 0 + if (! impl_ && ! other.impl_) + return true; + if (! impl_ || ! other.impl_) + return false; + return *impl_ == *other.impl_; +#else + return impl_.get() == other.impl_.get(); +#endif +} + +//------------------------------------------------------------------------------ + ReadView::sles_type::sles_type( ReadView const& view) : ReadViewFwdRange(view) diff --git a/src/ripple/test/jtx/impl/Env.cpp b/src/ripple/test/jtx/impl/Env.cpp index 3df2a83a8..b63f079ff 100644 --- a/src/ripple/test/jtx/impl/Env.cpp +++ b/src/ripple/test/jtx/impl/Env.cpp @@ -117,7 +117,7 @@ Env::close(NetClock::time_point const& closeTime) closeTime.time_since_epoch ()).count (), ledgerPossibleTimeResolutions[0], false); OrderedTxs locals({}); - openLedger.accept(next, locals, + openLedger.accept(next->rules(), next, locals, false, retries, applyFlags(), *router); closed_ = next; cachedSLEs_.expire();