Compare commits

...

8 Commits

Author SHA1 Message Date
Ed Hennis
cbdcddba4b Merge remote-tracking branch 'XRPLF/ximinez/lending-XLS-66' into ximinez/lending-transitive-amendments
* XRPLF/ximinez/lending-XLS-66:
  chore: Update nudb recipe to remove linker warnings (6038)
  Add the testPoC_UnsignedUnderflowOnFullPayAfterEarlyPeriodic
  fix: Apply object reserve for Vault pseudo-account (5954)
  refactor: Retire TicketBatch amendment (6032)
2025-11-15 03:11:42 -05:00
Ed Hennis
21be32de62 Merge branch 'ximinez/lending-XLS-66' into ximinez/lending-transitive-amendments 2025-11-13 14:46:04 -05:00
Ed Hennis
2a795aa9db Merge branch 'ximinez/lending-XLS-66' into ximinez/lending-transitive-amendments 2025-11-13 12:21:05 -05:00
Ed Hennis
59b9c712b8 Merge branch 'ximinez/lending-XLS-66' into ximinez/lending-transitive-amendments 2025-11-13 01:53:40 -05:00
Ed Hennis
3aa2bafd6a Merge branch 'ximinez/lending-XLS-66' into ximinez/lending-transitive-amendments 2025-11-12 20:12:35 -05:00
Ed Hennis
0a292c2fcf Merge branch 'ximinez/lending-XLS-66' into ximinez/lending-transitive-amendments 2025-11-12 14:17:22 -05:00
Ed Hennis
d7d3741e1e fixup! Implement transitive feature enabling for SAV 2025-11-10 19:54:32 -05:00
Ed Hennis
85a80f4b22 Implement transitive feature enabling for SAV 2025-11-10 19:54:32 -05:00
7 changed files with 96 additions and 35 deletions

View File

@@ -107,11 +107,41 @@ Rules::presets() const
return impl_->presets();
}
/** Define features that can be considered enabled based on other features.
*
* This is a simple key-value map where
* - the key is the feature being checked
* - the value is a set of other features, which, in any of them are enabled,
* will cause the key feature to be considered enabled.
*
*/
std::map<uint256, std::vector<uint256>> const&
getTransitiveFeatureMap()
{
static std::map<uint256, std::vector<uint256>> const featureToOverride{
// If LendingProtocol is enabled, then SingleAssetVault can also be
// considered enabled
{featureSingleAssetVault, {featureLendingProtocol}}};
return featureToOverride;
}
bool
Rules::enabled(uint256 const& feature) const
{
XRPL_ASSERT(impl_, "ripple::Rules::enabled : initialized");
// Some features can be considered enabled based on other enabled features.
static auto const& transitiveFeatureMap = getTransitiveFeatureMap();
if (transitiveFeatureMap.contains(feature))
{
auto const& transitiveFeatures = transitiveFeatureMap.at(feature);
if (std::any_of(
transitiveFeatures.begin(),
transitiveFeatures.end(),
[this](auto const& f) { return impl_->enabled(f); }))
return true;
}
return impl_->enabled(feature);
}

View File

@@ -58,7 +58,8 @@ private:
{},
0,
{},
{testable_amendments() - featureSingleAssetVault});
{testable_amendments() - featureSingleAssetVault -
featureLendingProtocol});
// IOU to IOU
testAMM(
@@ -7499,7 +7500,9 @@ private:
};
testCase(
"tecDUPLICATE", testable_amendments() - featureSingleAssetVault);
"tecDUPLICATE",
testable_amendments() - featureSingleAssetVault -
featureLendingProtocol);
testCase(
"terADDRESS_COLLISION",
testable_amendments() | featureSingleAssetVault);
@@ -7881,6 +7884,8 @@ private:
run() override
{
FeatureBitset const all{jtx::testable_amendments()};
FeatureBitset const featuresNoSAV =
all - featureSingleAssetVault - featureLendingProtocol;
testInvalidInstance();
testInstanceCreate();
testInvalidDeposit(all);
@@ -7931,8 +7936,8 @@ private:
testLPTokenBalance(all - fixAMMv1_3);
testLPTokenBalance(all - fixAMMv1_1 - fixAMMv1_3);
testAMMClawback(all);
testAMMClawback(all - featureSingleAssetVault);
testAMMClawback(all - featureAMMClawback - featureSingleAssetVault);
testAMMClawback(featuresNoSAV);
testAMMClawback(featuresNoSAV - featureAMMClawback);
testAMMClawback(all - featureAMMClawback);
testAMMClawback(all - fixAMMv1_1 - fixAMMv1_3 - featureAMMClawback);
testAMMDepositWithFrozenAssets(all);

View File

@@ -1692,17 +1692,33 @@ class Delegate_test : public beast::unit_test::suite
}
}
/// This class only adds a non-explicit ctor for uint256's to FeatureBitset
class BitsetWrapper : public FeatureBitset
{
public:
BitsetWrapper() = default;
template <class... Fs>
BitsetWrapper(uint256 const& f, Fs&&... fs)
: FeatureBitset(f, std::forward<Fs>(fs)...)
{
}
};
void
testTxReqireFeatures(FeatureBitset features)
{
testcase("test delegate disabled tx");
using namespace jtx;
BitsetWrapper const featuresSAV{
featureSingleAssetVault, featureLendingProtocol};
// map of tx and required feature.
// non-delegatable tx are not included.
// NFTokenMint, NFTokenBurn, NFTokenCreateOffer, NFTokenCancelOffer,
// NFTokenAcceptOffer are not included, they are tested separately.
std::unordered_map<std::string, uint256> txRequiredFeatures{
std::unordered_map<std::string, BitsetWrapper> txRequiredFeatures{
{"CheckCreate", featureChecks},
{"CheckCash", featureChecks},
{"CheckCancel", featureChecks},
@@ -1737,12 +1753,12 @@ class Delegate_test : public beast::unit_test::suite
{"NFTokenModify", featureDynamicNFT},
{"PermissionedDomainSet", featurePermissionedDomains},
{"PermissionedDomainDelete", featurePermissionedDomains},
{"VaultCreate", featureSingleAssetVault},
{"VaultSet", featureSingleAssetVault},
{"VaultDelete", featureSingleAssetVault},
{"VaultDeposit", featureSingleAssetVault},
{"VaultWithdraw", featureSingleAssetVault},
{"VaultClawback", featureSingleAssetVault}};
{"VaultCreate", featuresSAV},
{"VaultSet", featuresSAV},
{"VaultDelete", featuresSAV},
{"VaultDeposit", featuresSAV},
{"VaultWithdraw", featuresSAV},
{"VaultClawback", featuresSAV}};
// Can not delegate tx if any required feature disabled.
{
@@ -1760,8 +1776,8 @@ class Delegate_test : public beast::unit_test::suite
env(delegate::set(alice, bob, {tx}), ter(temMALFORMED));
};
for (auto const& tx : txRequiredFeatures)
txAmendmentDisabled(features, tx.first);
for (auto const& required : txRequiredFeatures)
txAmendmentDisabled(features, required.first);
}
// if all the required features in txRequiredFeatures are enabled, will
@@ -1778,8 +1794,8 @@ class Delegate_test : public beast::unit_test::suite
env(delegate::set(alice, bob, {tx}));
};
for (auto const& tx : txRequiredFeatures)
txAmendmentEnabled(tx.first);
for (auto const& required : txRequiredFeatures)
txAmendmentEnabled(required.first);
}
}

View File

@@ -12,8 +12,9 @@ class LoanBroker_test : public beast::unit_test::suite
// Ensure that all the features needed for Lending Protocol are included,
// even if they are set to unsupported.
FeatureBitset const all{
jtx::testable_amendments() | featureMPTokensV1 |
featureSingleAssetVault | featureLendingProtocol};
(jtx::testable_amendments() | featureMPTokensV1 |
featureLendingProtocol) -
featureSingleAssetVault};
void
testDisabled()
@@ -66,8 +67,10 @@ class LoanBroker_test : public beast::unit_test::suite
};
failAll(all - featureMPTokensV1);
failAll(all - featureSingleAssetVault - featureLendingProtocol);
failAll(all - featureSingleAssetVault);
failAll(all - featureLendingProtocol, true);
failAll((all | featureSingleAssetVault) - featureLendingProtocol, true);
// Don't test SAV disabled by itself, because it is transitively enabled
// by lending protocol. It is explicitly disabled by `all` above, which
// is used for the remaining tests.
}
struct VaultInfo

View File

@@ -20,8 +20,9 @@ protected:
// Ensure that all the features needed for Lending Protocol are included,
// even if they are set to unsupported.
FeatureBitset const all{
jtx::testable_amendments() | featureMPTokensV1 |
featureSingleAssetVault | featureLendingProtocol};
(jtx::testable_amendments() | featureMPTokensV1 |
featureLendingProtocol) -
featureSingleAssetVault};
std::string const iouCurrency{"IOU"};
@@ -70,8 +71,10 @@ protected:
};
failAll(all - featureMPTokensV1);
failAll(all - featureSingleAssetVault - featureLendingProtocol);
failAll(all - featureSingleAssetVault);
failAll(all - featureLendingProtocol);
failAll((all | featureSingleAssetVault) - featureLendingProtocol);
// Don't test SAV disabled by itself, because it is transitively enabled
// by lending protocol. It is explicitly disabled by `all` above, which
// is used for the remaining tests.
}
struct BrokerParameters

View File

@@ -3613,33 +3613,36 @@ public:
using namespace test::jtx;
FeatureBitset const all{testable_amendments()};
auto const featuresNoSAV =
all - featureSingleAssetVault - featureLendingProtocol;
auto const featuresNoDomains = all - featurePermissionedDomains;
// MPTokenIssuanceCreate
testCreateValidation(all - featureSingleAssetVault);
testCreateValidation(all - featurePermissionedDomains);
testCreateValidation(featuresNoSAV);
testCreateValidation(featuresNoDomains);
testCreateValidation(all);
testCreateEnabled(all - featureSingleAssetVault);
testCreateEnabled(featuresNoSAV);
testCreateEnabled(all);
// MPTokenIssuanceDestroy
testDestroyValidation(all - featureSingleAssetVault);
testDestroyValidation(featuresNoSAV);
testDestroyValidation(all);
testDestroyEnabled(all - featureSingleAssetVault);
testDestroyEnabled(featuresNoSAV);
testDestroyEnabled(all);
// MPTokenAuthorize
testAuthorizeValidation(all - featureSingleAssetVault);
testAuthorizeValidation(featuresNoSAV);
testAuthorizeValidation(all);
testAuthorizeEnabled(all - featureSingleAssetVault);
testAuthorizeEnabled(featuresNoSAV);
testAuthorizeEnabled(all);
// MPTokenIssuanceSet
testSetValidation(all - featureSingleAssetVault - featureDynamicMPT);
testSetValidation(all - featureSingleAssetVault);
testSetValidation(featuresNoSAV - featureDynamicMPT);
testSetValidation(featuresNoSAV);
testSetValidation(all - featureDynamicMPT);
testSetValidation(all - featurePermissionedDomains);
testSetValidation(featuresNoDomains);
testSetValidation(all);
testSetEnabled(all - featureSingleAssetVault);
testSetEnabled(featuresNoSAV);
testSetEnabled(all);
// MPT clawback

View File

@@ -722,7 +722,8 @@ class Vault_test : public beast::unit_test::suite
testCase(
testDisabled(),
{.features = testable_amendments() - featureSingleAssetVault});
{.features = testable_amendments() - featureSingleAssetVault -
featureLendingProtocol});
testCase(
testDisabled(tecNO_ENTRY),