Skip to content

Commit

Permalink
update granular permissions
Browse files Browse the repository at this point in the history
  • Loading branch information
yinyiqian1 committed Nov 19, 2024
1 parent 6bbe2ca commit 372cc5c
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/xrpld/app/tx/detail/MPTokenIssuanceSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ MPTokenIssuanceSet::doApply()
bool bUnlock = txFlags & tfMPTUnlock;
if (ctx_.isDelegated && !ctx_.gpSet.empty())
{
// if gpSet is not empty, granular delegation is happening.
if (bLock && ctx_.gpSet.find(gpMPTokenIssuanceLock) == ctx_.gpSet.end())
return terNO_AUTH;
if (bUnlock &&
Expand Down
8 changes: 6 additions & 2 deletions src/xrpld/app/tx/detail/Payment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,15 +344,19 @@ Payment::doApply()

if (ctx_.isDelegated && !ctx_.gpSet.empty())
{
// If gpSet is not empty, granular delegation is happening.
// Currently we only support PaymentMint and PaymentBurn granular
// permission. PaymentMint means the sender is the issuer. PaymentBurn
// means the destination is the issuer.
bool authorized = false;
auto const amountIssue = dstAmount.issue();
if (isXRP(amountIssue))
return tecNO_AUTH;
if (amountIssue.account == account_ &&
ctx_.gpSet.find(gpPaymentMint) == ctx_.gpSet.end())
ctx_.gpSet.find(gpPaymentMint) != ctx_.gpSet.end())
authorized = true;
if (amountIssue.account == dstAccountID &&
ctx_.gpSet.find(gpPaymentBurn) == ctx_.gpSet.end())
ctx_.gpSet.find(gpPaymentBurn) != ctx_.gpSet.end())
authorized = true;

if (!authorized)
Expand Down
37 changes: 37 additions & 0 deletions src/xrpld/app/tx/detail/SetAccount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,20 @@ SetAccount::doApply()

// legacy AccountSet flags
std::uint32_t const uTxFlags{tx.getFlags()};

bool granularDelegated = false;
if (ctx_.isDelegated && !ctx_.gpSet.empty())
{
// if gpSet is not empty, granular delegation is happening.
granularDelegated = true;

// We don't support any flag based granular permission under AccountSet
// transaction. If any delegated account is trying to update the flag
// onbehalf of another account, it is not authorized.
if (uSetFlag != 0 || uClearFlag != 0 || uTxFlags != 0)
return tecNO_AUTH;
}

bool const bSetRequireDest{
(uTxFlags & tfRequireDestTag) || (uSetFlag == asfRequireDest)};
bool const bClearRequireDest{
Expand Down Expand Up @@ -450,6 +464,10 @@ SetAccount::doApply()
//
if (tx.isFieldPresent(sfEmailHash))
{
if (granularDelegated &&
ctx_.gpSet.find(gpAccountEmailHashSet) == ctx_.gpSet.end())
return tecNO_AUTH;

uint128 const uHash = tx.getFieldH128(sfEmailHash);

if (!uHash)
Expand All @@ -469,6 +487,9 @@ SetAccount::doApply()
//
if (tx.isFieldPresent(sfWalletLocator))
{
if (granularDelegated)
return tecNO_AUTH;

uint256 const uHash = tx.getFieldH256(sfWalletLocator);

if (!uHash)
Expand All @@ -488,6 +509,10 @@ SetAccount::doApply()
//
if (tx.isFieldPresent(sfMessageKey))
{
if (granularDelegated &&
ctx_.gpSet.find(gpAccountMessageKeySet) == ctx_.gpSet.end())
return tecNO_AUTH;

Blob const messageKey = tx.getFieldVL(sfMessageKey);

if (messageKey.empty())
Expand All @@ -507,6 +532,10 @@ SetAccount::doApply()
//
if (tx.isFieldPresent(sfDomain))
{
if (granularDelegated &&
ctx_.gpSet.find(gpAccountDomainSet) == ctx_.gpSet.end())
return tecNO_AUTH;

Blob const domain = tx.getFieldVL(sfDomain);

if (domain.empty())
Expand All @@ -526,6 +555,10 @@ SetAccount::doApply()
//
if (tx.isFieldPresent(sfTransferRate))
{
if (granularDelegated &&
ctx_.gpSet.find(gpAccountTransferRateSet) == ctx_.gpSet.end())
return tecNO_AUTH;

std::uint32_t uRate = tx.getFieldU32(sfTransferRate);

if (uRate == 0 || uRate == QUALITY_ONE)
Expand All @@ -545,6 +578,10 @@ SetAccount::doApply()
//
if (tx.isFieldPresent(sfTickSize))
{
if (granularDelegated &&
ctx_.gpSet.find(gpAccountTickSizeSet) == ctx_.gpSet.end())
return tecNO_AUTH;

auto uTickSize = tx[sfTickSize];
if ((uTickSize == 0) || (uTickSize == Quality::maxTickSize))
{
Expand Down
26 changes: 25 additions & 1 deletion src/xrpld/app/tx/detail/SetTrust.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,9 +243,14 @@ SetTrust::doApply()
bool const bSetFreeze = (uTxFlags & tfSetFreeze);
bool const bClearFreeze = (uTxFlags & tfClearFreeze);

bool granularDelegated = false;
if (ctx_.isDelegated && !ctx_.gpSet.empty())
{
if (bSetNoRipple || bClearNoRipple)
granularDelegated = true;
// If granular permission is delegated under the TrustSet transaction.
// Currently we only support TrustlineAuthorize, TrustlineFreeze and
// TrustlineUnfreeze granular permission.
if (bSetNoRipple || bClearNoRipple || bQualityIn || bQualityOut)
return terNO_AUTH;
if (bSetAuth &&
ctx_.gpSet.find(gpTrustlineAuthorize) == ctx_.gpSet.end())
Expand Down Expand Up @@ -315,6 +320,18 @@ SetTrust::doApply()
//
// Limits
//
if (granularDelegated)
{
// Currently we only support TrustlineAuthorize, TrustlineFreeze and
// TrustlineUnfreeze granular permission. So updating the
// LimitAmount is not allowed unless the delegated account has full
// transaction level permission.
auto const curLimit = bHigh
? sleRippleState->getFieldAmount(sfHighLimit)
: sleRippleState->getFieldAmount(sfLowLimit);
if (curLimit != saLimitAllow)
return tecNO_AUTH;
}

sleRippleState->setFieldAmount(
!bHigh ? sfLowLimit : sfHighLimit, saLimitAllow);
Expand Down Expand Up @@ -551,6 +568,13 @@ SetTrust::doApply()
}
else
{
if (granularDelegated)
// currently we only allow TrustlineAuthorize, TrustlineFreeze and
// TrustlineUnfreeze granular permission delegation, a delegated
// account can not create a new trust line if it is not fully
// delegated with the whole TrustSet transaction based permission.
return tecNO_PERMISSION;

// Zero balance in currency.
STAmount saBalance(Issue{currency, noAccount()});

Expand Down

0 comments on commit 372cc5c

Please sign in to comment.