Merge branch 'xrplf/sponsor' of https://github.com/XRPLF/rippled into mvadari/sponsor/apply-view-context

This commit is contained in:
Mayukha Vadari
2026-07-01 13:40:50 -04:00
13 changed files with 734 additions and 189 deletions

View File

@@ -109,7 +109,7 @@ baseAccountReserve(ReadView const& view, std::int32_t ownerCount, std::int32_t a
*/
[[nodiscard]] TER
checkInsufficientReserve(
ReadView const& view,
ApplyView const& view,
STTx const& tx,
SLE::const_ref accSle,
STAmount const& accBalance,

View File

@@ -0,0 +1,19 @@
#pragma once
#include <cstddef>
#include <cstdint>
namespace xrpl {
constexpr uint32_t kMinOracleReserveCount = 1;
constexpr uint32_t kMaxOracleReserveCount = 2;
constexpr std::size_t kOracleReserveCountThreshold = 5;
inline uint32_t
calculateOracleReserve(std::size_t priceDataSeriesCount)
{
return priceDataSeriesCount > kOracleReserveCountThreshold ? kMaxOracleReserveCount
: kMinOracleReserveCount;
}
} // namespace xrpl

View File

@@ -3,6 +3,7 @@
#include <xrpl/basics/Log.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/OracleHelpers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STTx.h>
@@ -123,4 +124,121 @@ removeSponsorFromLedgerEntry(SLE::ref sle, SF_ACCOUNT const& field = sfSponsor)
sle->makeFieldAbsent(field);
}
template <typename T>
inline std::optional<AccountID>
getLedgerEntryOwner(ReadView const& view, T const& sle, AccountID const& account)
{
switch (sle->getType())
{
case ltCHECK:
case ltESCROW:
case ltPAYCHAN:
case ltMPTOKEN:
case ltDELEGATE:
case ltDEPOSIT_PREAUTH:
return sle->getAccountID(sfAccount);
case ltMPTOKEN_ISSUANCE:
return sle->getAccountID(sfIssuer);
case ltSIGNER_LIST: {
auto const signerList = view.read(keylet::signers(account));
if (!signerList)
return std::nullopt;
if (signerList->key() == sle->key())
return account;
return std::nullopt;
}
case ltCREDENTIAL: {
if (sle->isFlag(lsfAccepted))
return sle->getAccountID(sfSubject);
return sle->getAccountID(sfIssuer);
}
case ltRIPPLE_STATE: {
if (sle->isFlag(lsfHighReserve))
{
auto const highAccount = sle->getFieldAmount(sfHighLimit).getIssuer();
if (highAccount == account)
return highAccount;
}
if (sle->isFlag(lsfLowReserve))
{
auto const lowAccount = sle->getFieldAmount(sfLowLimit).getIssuer();
if (lowAccount == account)
return lowAccount;
}
return std::nullopt;
}
default:
UNREACHABLE("Object is not supported by sponsorship.");
return std::nullopt;
};
}
template <typename T>
inline bool
isLedgerEntrySupportedBySponsorship(T const& sle)
{
switch (sle->getType())
{
case ltCHECK:
case ltESCROW:
case ltPAYCHAN:
case ltMPTOKEN:
case ltDELEGATE:
case ltDEPOSIT_PREAUTH:
case ltMPTOKEN_ISSUANCE:
case ltSIGNER_LIST:
case ltCREDENTIAL:
case ltRIPPLE_STATE:
return true;
default:
return false;
};
}
template <typename T>
inline std::uint32_t
getLedgerEntryOwnerCount(T const& sle)
{
switch (sle->getType())
{
case ltORACLE: {
return calculateOracleReserve(sle->getFieldArray(sfPriceDataSeries).size());
}
// Vaults require 2 owner counts (the vault and a pseudo-account)
case ltVAULT:
return 2;
default:
return 1;
}
};
template <typename T>
inline SF_ACCOUNT const&
getLedgerEntrySponsorField(T const& sle, AccountID const& owner)
{
switch (sle->getType())
{
case ltRIPPLE_STATE: {
if (sle->isFlag(lsfHighReserve))
{
auto const highAccount = sle->getFieldAmount(sfHighLimit).getIssuer();
if (highAccount == owner)
return sfHighSponsor;
}
if (sle->isFlag(lsfLowReserve))
{
auto const lowAccount = sle->getFieldAmount(sfLowLimit).getIssuer();
if (lowAccount == owner)
return sfLowSponsor;
}
// LCOV_EXCL_START
UNREACHABLE("Should not happen. Owner should be checked before calling this function.");
return sfSponsor;
// LCOV_EXCL_STOP
}
default:
return sfSponsor;
}
};
} // namespace xrpl

View File

@@ -22,12 +22,6 @@ public:
{
}
static uint32_t
calculateOracleReserve(std::size_t count)
{
return count > 5 ? 2 : 1;
}
static NotTEC
preflight(PreflightContext const& ctx);