20 #include <ripple/ledger/CashDiff.h>
21 #include <ripple/ledger/detail/ApplyStateTable.h>
22 #include <ripple/protocol/st.h>
23 #include <boost/container/static_vector.hpp>
121 auto const& prev = *before;
138 auto const& cur = *
after;
145 if (oldTakerPays != zero && oldTakerGets != zero)
169 auto const& prev = *before;
170 switch (prev.getType())
206 auto const& cur = *
after;
207 switch (cur.getType())
210 auto const curXrp = cur[
sfBalance].xrp();
211 if (!before || (*before)[
sfBalance].xrp() != curXrp)
218 if (!before || (*before)[
sfBalance] != curBalance)
223 curBalance.getCurrency()),
230 if (!before || (*before)[
sfTakerGets] != curTakerGets ||
255 boost::container::static_vector<FuncType, 2> filters;
262 auto each = [&result, &filters](
270 [&result, isDelete, &before, &
after](FuncType func) {
271 return func(result, isDelete, before, after);
276 table.
visit(view, each);
316 findDiffs(lhsFilter, lhs, rhsFilter, rhs);
374 template <
typename T,
typename U>
382 auto lhsItr = lhs.
cbegin();
383 auto rhsItr = rhs.cbegin();
385 while (lhsItr != lhs.cend() || rhsItr != rhs.cend())
387 if (lhsItr == lhs.cend())
393 else if (rhsItr == rhs.cend())
399 else if (lhsItr->first < rhsItr->first)
405 else if (rhsItr->first < lhsItr->first)
465 bool const lhsBigger =
471 if (bigger.
offerChanges[0].second.takerGets().mantissa() -
472 smaller.
offerChanges[0].second.takerGets().mantissa() !=
490 return lhsBigger ? -1 : 1;
498 for (
auto i = 0; i < lhs.
count(); ++i)
507 template <
typename T,
typename U,
typename L>
515 std::is_same<
bool, decltype(justDust(lhs[0].second, rhs[0].second))>::
517 "Invalid lambda passed to rmVecDust");
519 bool dustWasRemoved =
false;
520 auto lhsItr = lhs.begin();
521 while (lhsItr != lhs.end())
528 [](value_t
const& a, value_t
const& b) {
529 return a.first < b.first;
532 if (found.first != found.second)
536 if (justDust(lhsItr->second, found.first->second))
538 dustWasRemoved =
true;
539 rhs.erase(found.first);
541 lhsItr = lhs.erase(lhsItr);
547 return dustWasRemoved;
553 bool removedDust =
false;
562 lhsDiffs_.xrpChanges,
563 rhsDiffs_.xrpChanges,
565 return diffIsDust(lhs, rhs);
570 lhsDiffs_.trustChanges,
571 rhsDiffs_.trustChanges,
573 return diffIsDust(lhs, rhs);
578 lhsDiffs_.offerChanges,
579 rhsDiffs_.offerChanges,
585 lhsDiffs_.offerDeletions,
586 rhsDiffs_.offerDeletions,
596 bool const ret = !lhsDiffs_.offerDeletions.empty();
598 lhsDiffs_.offerDeletions.clear();
605 bool const ret = !rhsDiffs_.offerDeletions.empty();
607 rhsDiffs_.offerDeletions.clear();
612 template <
typename T>
639 auto lhsDiffs = getCashFlow(view_, lhsFilter, lhs);
640 auto rhsDiffs = getCashFlow(view_, rhsFilter, rhs);
643 auto const counts =
countKeys(lhsDiffs, rhsDiffs);
644 commonKeys_ = counts[0];
645 lhsKeys_ = counts[1];
646 rhsKeys_ = counts[2];
650 setDiff(lhsDiffs.xrpChanges, rhsDiffs.xrpChanges, lhsDiffs_.xrpChanges);
651 setDiff(rhsDiffs.xrpChanges, lhsDiffs.xrpChanges, rhsDiffs_.xrpChanges);
655 lhsDiffs.trustChanges, rhsDiffs.trustChanges, lhsDiffs_.trustChanges);
657 rhsDiffs.trustChanges, lhsDiffs.trustChanges, rhsDiffs_.trustChanges);
661 lhsDiffs.trustDeletions,
662 rhsDiffs.trustDeletions,
663 lhsDiffs_.trustDeletions);
665 rhsDiffs.trustDeletions,
666 lhsDiffs.trustDeletions,
667 rhsDiffs_.trustDeletions);
671 lhsDiffs.offerChanges, rhsDiffs.offerChanges, lhsDiffs_.offerChanges);
673 rhsDiffs.offerChanges, lhsDiffs.offerChanges, rhsDiffs_.offerChanges);
677 lhsDiffs.offerDeletions,
678 rhsDiffs.offerDeletions,
679 lhsDiffs_.offerDeletions);
681 rhsDiffs.offerDeletions,
682 lhsDiffs.offerDeletions,
683 rhsDiffs_.offerDeletions);
701 :
impl_(new
Impl(view, lhsFilter, lhs, rhsFilter, rhs))
708 return impl_->commonCount();
714 return impl_->rhsOnlyCount();
720 return impl_->lhsOnlyCount();
726 return impl_->hasDiff();
732 return impl_->xrpRoundToZero();
738 return impl_->rmDust();
744 return impl_->rmLhsDeletedOffers();
750 return impl_->rmRhsDeletedOffers();
762 if (v1 != beast::zero && v2 != beast::zero &&
777 STAmount const& small = v1 < v2 ? v1 : v2;
778 STAmount const& large = v1 < v2 ? v2 : v1;
805 1
'000'000
'000'000ULL,
806 10
'000'000
'000'000ULL,
807 100
'000'000
'000'000ULL,
808 1
'000'000
'000'000
'000ULL,
809 10'000
'000'000
'000'000ULL,
810 100
'000'000
'000'000
'000ULL,
811 1'000
'000'000
'000'000
'000ULL,
812 10'000
'000'000
'000'000
'000ULL,
814 static std::size_t constexpr maxIndex =
815 sizeof(e10Lookup) / sizeof e10Lookup[0];
817 // Make sure the table is big enough.
819 std::numeric_limits<std::uint64_t>::max() /
820 e10Lookup[maxIndex - 1] <
827 return ratio >= e10Lookup[e10];
830 // Non-native. Note that even though large and small may not be equal,
831 // their difference may be zero. One way that can happen is if two
832 // values are different, but their difference results in an STAmount
833 // with an exponent less than -96.
834 STAmount const diff = large - small;
835 if (diff == beast::zero)
838 STAmount const ratio = divide(small, diff, v1.issue());
839 STAmount const one(v1.issue(), 1);
840 int const ratioExp = ratio.exponent() - one.exponent();
842 return ratioExp >= e10;
845 } // namespace ripple
std::vector< std::pair< std::tuple< AccountID, std::uint32_t >, CashDiff::OfferAmounts > > offerDeletions
std::size_t lhsOnlyCount() const
bool rmLhsDeletedOffers()
bool diffIsDust(STAmount const &v1, STAmount const &v2, std::uint8_t e10=6)
std::uint64_t mantissa() const noexcept
bool rmRhsDeletedOffers()
static CashSummary getCashFlow(ReadView const &view, CashFilter f, ApplyStateTable const &table)
const SF_U32 sfSequence(access, STI_UINT32, 4, "Sequence")
void visit(ReadView const &base, std::function< void(uint256 const &key, bool isDelete, std::shared_ptr< SLE const > const &before, std::shared_ptr< SLE const > const &after)> const &func) const
std::size_t rhsOnlyCount() const
void findDiffs(CashFilter lhsFilter, detail::ApplyStateTable const &lhs, CashFilter rhsFilter, detail::ApplyStateTable const &rhs)
bool rmLhsDeletedOffers()
const SF_Account sfAccount(access, STI_ACCOUNT, 1, "Account")
std::unique_ptr< Impl > impl_
Impl(ReadView const &view, CashFilter lhsFilter, detail::ApplyStateTable const &lhs, CashFilter rhsFilter, detail::ApplyStateTable const &rhs)
const SF_Amount sfTakerPays(access, STI_AMOUNT, 4, "TakerPays")
bool rmRhsDeletedOffers()
const SF_Amount sfHighLimit(access, STI_AMOUNT, 7, "HighLimit")
XRPAmount const & dropsDestroyed() const
void reserve(size_t newCap)
const SF_Amount sfLowLimit(access, STI_AMOUNT, 6, "LowLimit")
boost::optional< DropsGone > dropsGone_
std::size_t rhsOnlyCount() const
static std::array< std::size_t, 3 > countKeys(std::vector< std::pair< T, U >> const &lhs, std::vector< std::pair< T, U >> const &rhs)
static constexpr std::size_t count()
detail::CashSummary lhsDiffs_
std::vector< std::pair< std::tuple< AccountID, AccountID, Currency >, bool > > trustDeletions
static bool treatZeroOfferAsDeletion(CashSummary &result, bool isDelete, std::shared_ptr< SLE const > const &before, std::shared_ptr< SLE const > const &after)
std::vector< std::pair< AccountID, XRPAmount > > xrpChanges
std::vector< std::pair< std::tuple< AccountID, AccountID, Currency >, STAmount > > trustChanges
std::size_t commonCount() const
@ treatZeroOfferAsDeletion
static void setDiff(std::vector< T > const &a, std::vector< T > const &b, std::vector< T > &dest)
bool native() const noexcept
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
const SF_Amount sfBalance(access, STI_AMOUNT, 2, "Balance")
std::size_t lhsOnlyCount() const
T set_difference(T... args)
Issue const & issue() const
bool negative() const noexcept
const SF_Amount sfTakerGets(access, STI_AMOUNT, 5, "TakerGets")
detail::CashSummary rhsDiffs_
int xrpRoundToZero() const
static bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
static bool getBasicCashFlow(CashSummary &result, bool isDelete, std::shared_ptr< SLE const > const &before, std::shared_ptr< SLE const > const &after)
int xrpRoundToZero() const
std::size_t commonCount() const
static bool rmVecDust(std::vector< std::pair< T, U >> &lhs, std::vector< std::pair< T, U >> &rhs, L &&justDust)
std::vector< std::pair< std::tuple< AccountID, std::uint32_t >, CashDiff::OfferAmounts > > offerChanges