mirror of
https://github.com/XRPLF/rippled.git
synced 2026-06-03 16:56:48 +00:00
fix: No invariant verifying sfSponsor field on objects matches sponsoring/sponsored count deltas #6897
This commit is contained in:
@@ -21,6 +21,7 @@ class SponsorshipOwnerCountsMatch
|
||||
{
|
||||
std::int64_t deltaSponsoredOwnerCount_ = 0;
|
||||
std::int64_t deltaSponsoringOwnerCount_ = 0;
|
||||
std::int64_t deltaSponsoredObjectOwnerCount_ = 0;
|
||||
std::uint64_t invalidOwnerCountLessThanSponsoredOwnerCount_ = 0;
|
||||
|
||||
public:
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
#include <xrpl/tx/invariants/SponsorshipInvariant.h>
|
||||
//
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/protocol/STArray.h>
|
||||
#include <xrpl/tx/transactors/oracle/OracleSet.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
// Add new sponsorship-related invariants implementations
|
||||
void
|
||||
SponsorshipOwnerCountsMatch::visitEntry(
|
||||
bool,
|
||||
bool isDelete,
|
||||
std::shared_ptr<SLE const> const& before,
|
||||
std::shared_ptr<SLE const> const& after)
|
||||
{
|
||||
@@ -33,14 +35,57 @@ SponsorshipOwnerCountsMatch::visitEntry(
|
||||
return 0;
|
||||
};
|
||||
|
||||
auto getSponsoredObjectOwnerCount =
|
||||
[&](std::shared_ptr<SLE const> const& sle) -> std::uint32_t {
|
||||
if (!sle)
|
||||
return 0;
|
||||
switch (sle->getType())
|
||||
{
|
||||
case ltACCOUNT_ROOT: {
|
||||
return 0;
|
||||
}
|
||||
case ltRIPPLE_STATE: {
|
||||
uint32_t ownerCount = 0;
|
||||
if (sle->isFieldPresent(sfHighSponsor))
|
||||
ownerCount++;
|
||||
if (sle->isFieldPresent(sfLowSponsor))
|
||||
ownerCount++;
|
||||
return ownerCount;
|
||||
}
|
||||
case ltORACLE: {
|
||||
if (!sle->isFieldPresent(sfSponsor))
|
||||
return 0;
|
||||
auto const priceDataSeries = sle->getFieldArray(sfPriceDataSeries);
|
||||
return OracleSet::calculateOracleReserve(priceDataSeries.size());
|
||||
}
|
||||
case ltVAULT: {
|
||||
if (!sle->isFieldPresent(sfSponsor))
|
||||
return 0;
|
||||
return 2;
|
||||
}
|
||||
default: {
|
||||
if (sle->isFieldPresent(sfSponsor))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::int64_t const beforeSponsored = getSponsored(before);
|
||||
std::int64_t const afterSponsored = getSponsored(after);
|
||||
std::int64_t const beforeSponsoring = getSponsoring(before);
|
||||
std::int64_t const afterSponsoring = getSponsoring(after);
|
||||
|
||||
std::int64_t const beforeSponsoredObjectOwnerCount = getSponsoredObjectOwnerCount(before);
|
||||
std::int64_t const afterSponsoredObjectOwnerCount =
|
||||
isDelete ? 0 : getSponsoredObjectOwnerCount(after);
|
||||
|
||||
deltaSponsoredOwnerCount_ += (afterSponsored - beforeSponsored);
|
||||
deltaSponsoringOwnerCount_ += (afterSponsoring - beforeSponsoring);
|
||||
|
||||
deltaSponsoredObjectOwnerCount_ +=
|
||||
(afterSponsoredObjectOwnerCount - beforeSponsoredObjectOwnerCount);
|
||||
|
||||
if (getOwnerCount(after) < getSponsoredOwnerCount(after))
|
||||
invalidOwnerCountLessThanSponsoredOwnerCount_ += 1;
|
||||
}
|
||||
@@ -60,6 +105,13 @@ SponsorshipOwnerCountsMatch::finalize(
|
||||
return false;
|
||||
}
|
||||
|
||||
if (deltaSponsoredObjectOwnerCount_ != deltaSponsoredOwnerCount_)
|
||||
{
|
||||
JLOG(j.fatal()) << "Invariant failed: SponsoredObjectOwnerCount does not "
|
||||
"equal SponsoredOwnerCount delta.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (invalidOwnerCountLessThanSponsoredOwnerCount_ > 0)
|
||||
{
|
||||
JLOG(j.fatal())
|
||||
|
||||
Reference in New Issue
Block a user