mirror of
https://github.com/XRPLF/rippled.git
synced 2026-06-04 09:16:47 +00:00
Sponsor permissions
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user