Sponsor permissions

This commit is contained in:
tequ
2025-09-16 23:11:19 +09:00
parent 5ac7bbf51b
commit 759f843020
4 changed files with 135 additions and 0 deletions

View File

@@ -66,3 +66,9 @@ PERMISSION(MPTokenIssuanceLock, ttMPTOKEN_ISSUANCE_SET, 65547)
/** This permission grants the delegated account the ability to unlock MPToken. */
PERMISSION(MPTokenIssuanceUnlock, ttMPTOKEN_ISSUANCE_SET, 65548)
/** This permission grants the delegated account the ability to set SponsorFee. */
PERMISSION(SponsorFee, ttSPONSORSHIP_SET, 65549)
/** This permission grants the delegated account the ability to set SponsorReserve. */
PERMISSION(SponsorReserve, ttSPONSORSHIP_SET, 65550)

View File

@@ -1327,6 +1327,93 @@ public:
}
}
void
testDelegatePermission()
{
testcase("DelegatePermission");
using namespace test::jtx;
Account const alice("alice");
Account const bob("bob");
Account const carol("carol");
//
// Permission SponsorFee
//
{
Env env{*this, testable_amendments()};
env.fund(XRP(1000000), alice, bob, carol);
env.close();
auto const testFeePermission = [&](TER result) {
// FeeAmount
env(sponsor::set(alice, bob, 0, std::nullopt, XRP(100)),
delegate::as(carol),
ter(result));
// MaxFee
env(sponsor::set(
alice, bob, 0, std::nullopt, std::nullopt, XRP(100)),
delegate::as(carol),
ter(result));
// SetRequireSignForFee flag
env(sponsor::set(alice, bob, tfSponsorshipSetRequireSignForFee),
delegate::as(carol),
ter(result));
env.close();
};
// no delegated
testFeePermission(tecNO_DELEGATE_PERMISSION);
// set non-SponsorFee Permission
env(delegate::set(alice, carol, {"SponsorReserve"}));
env.close();
testFeePermission(tecNO_DELEGATE_PERMISSION);
// set SponsorFee Permission
env(delegate::set(alice, carol, {"SponsorFee"}));
env.close();
testFeePermission(tesSUCCESS);
}
//
// Permission SponsorReserve
//
{
Env env{*this, testable_amendments()};
env.fund(XRP(1000000), alice, bob, carol);
env.close();
auto const testReservePermission = [&](TER result) {
// ReserveCount
env(sponsor::set(alice, bob, 0, 100),
delegate::as(carol),
ter(result));
// SetRequireSignForReserve flag
env(sponsor::set(
alice, bob, tfSponsorshipSetRequireSignForReserve),
delegate::as(carol),
ter(result));
env.close();
};
// no delegated
testReservePermission(tecNO_DELEGATE_PERMISSION);
// set non-SponsorReserve Permission
env(delegate::set(alice, carol, {"SponsorFee"}));
env.close();
testReservePermission(tecNO_DELEGATE_PERMISSION);
// set SponsorReserve Permission
env(delegate::set(alice, carol, {"SponsorReserve"}));
env.close();
testReservePermission(tesSUCCESS);
}
}
void
testSponsorReserve()
{
@@ -1368,6 +1455,8 @@ public:
testDisallowIncoming();
testAccountDelete();
testDelegatePermission();
}
};

View File

@@ -17,6 +17,7 @@
*/
//==============================================================================
#include <xrpld/app/misc/DelegateUtils.h>
#include <xrpld/app/tx/detail/SponsorshipSet.h>
#include <xrpld/ledger/View.h>
@@ -122,6 +123,42 @@ SponsorshipSet::preflight(PreflightContext const& ctx)
return preflight2(ctx);
}
TER
SponsorshipSet::checkPermission(ReadView const& view, STTx const& tx)
{
auto const delegate = tx[~sfDelegate];
if (!delegate)
return tesSUCCESS;
auto const delegateKey = keylet::delegate(tx[sfAccount], *delegate);
auto const sle = view.read(delegateKey);
if (!sle)
return tecNO_DELEGATE_PERMISSION;
if (checkTxPermission(sle, tx) == tesSUCCESS)
return tesSUCCESS;
std::unordered_set<GranularPermissionType> granularPermissions;
loadGranularPermission(sle, ttSPONSORSHIP_SET, granularPermissions);
auto const sponsoringFee = tx.isFieldPresent(sfFeeAmount) ||
tx.isFieldPresent(sfMaxFee) ||
tx.isFlag(tfSponsorshipSetRequireSignForFee);
auto const sponsoringReserve = tx.isFieldPresent(sfReserveCount) ||
tx.isFlag(tfSponsorshipSetRequireSignForReserve);
if (granularPermissions.contains(SponsorFee) && sponsoringFee)
return tesSUCCESS;
if (granularPermissions.contains(SponsorReserve) && sponsoringReserve)
return tesSUCCESS;
// TODO: needs to check permission to delete sponsorship?
return tecNO_DELEGATE_PERMISSION;
}
TER
SponsorshipSet::preclaim(PreclaimContext const& ctx)
{

View File

@@ -36,6 +36,9 @@ public:
static NotTEC
preflight(PreflightContext const& ctx);
static TER
checkPermission(ReadView const& view, STTx const& tx);
static TER
preclaim(PreclaimContext const& ctx);