Skip to content

Commit

Permalink
add AccountPermission
Browse files Browse the repository at this point in the history
  • Loading branch information
yinyiqian1 committed Oct 25, 2024
1 parent 63209c2 commit 2e9b7a6
Show file tree
Hide file tree
Showing 18 changed files with 490 additions and 6 deletions.
2 changes: 1 addition & 1 deletion include/xrpl/protocol/Feature.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ namespace detail {
// Feature.cpp. Because it's only used to reserve storage, and determine how
// large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than
// the actual number of amendments. A LogicError on startup will verify this.
static constexpr std::size_t numFeatures = 79;
static constexpr std::size_t numFeatures = 80;

/** Amendments that this server supports and the default voting behavior.
Whether they are enabled depends on the Rules defined in the validated
Expand Down
11 changes: 11 additions & 0 deletions include/xrpl/protocol/Indexes.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,17 @@ amm(Issue const& issue1, Issue const& issue2) noexcept;
Keylet
amm(uint256 const& amm) noexcept;

/** An AccountPermission */
/** @{ */
Keylet
accountPermission(
AccountID const& account,
AccountID const& authorizedAccount) noexcept;

Keylet
accountPermission(uint256 const& key) noexcept;
/** @} */

Keylet
bridge(STXChainBridge const& bridge, STXChainBridge::ChainType chainType);

Expand Down
82 changes: 82 additions & 0 deletions include/xrpl/protocol/Permissions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2024 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================

#ifndef RIPPLE_PROTOCOL_PERMISSION_H_INCLUDED
#define RIPPLE_PROTOCOL_PERMISSION_H_INCLUDED

#include <optional>
#include <string>
#include <unordered_map>

namespace ripple {

/**
* We have transaction type permissions and granular type
* permissions. Since we will reuse the TransactionFormats to parse the
* Transaction Permissions, we only define the GranularPermissionType here.
*/

enum GranularPermissionType : std::uint32_t {
gpTrustlineAuthorize = 65537,

gpTrustlineFreeze = 65538,

gpTrustlineUnfreeze = 65539,

gpAccountDomainSet = 65540,

gpAccountEmailHashSet = 65541,

gpAccountMessageKeySet = 65542,

gpAccountTransferRateSet = 65543,

gpAccountTickSizeSet = 65544,

gpPaymentMint = 65545,

gpPaymentBurn = 65546,

gpMPTokenIssuanceLock = 65547,

gpMPTokenIssuanceUnlock = 65548,
};

class Permission
{
private:
Permission();

std::unordered_map<std::string, GranularPermissionType>
granularPermissionMap;

public:
static Permission const&
getInstance();

std::optional<std::uint32_t>
getGranularValue(const std::string& name) const;

bool
isProhibited(const std::string& name) const;
};

} // namespace ripple

#endif
1 change: 1 addition & 0 deletions include/xrpl/protocol/detail/features.macro
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ XRPL_FIX (1513, Supported::yes, VoteBehavior::DefaultYe
XRPL_FEATURE(FlowCross, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(Flow, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(OwnerPaysFee, Supported::no, VoteBehavior::DefaultNo)
XRPL_FEATURE(AccountPermission, Supported::yes, VoteBehavior::DefaultYes)

// The following amendments are obsolete, but must remain supported
// because they could potentially get enabled.
Expand Down
13 changes: 13 additions & 0 deletions include/xrpl/protocol/detail/ledger_entries.macro
Original file line number Diff line number Diff line change
Expand Up @@ -392,3 +392,16 @@ LEDGER_ENTRY(ltORACLE, 0x0080, Oracle, ({
{sfPreviousTxnID, soeREQUIRED},
{sfPreviousTxnLgrSeq, soeREQUIRED},
}))

/** A ledger object representing permissions an account has delegated to another account.

\sa keylet::accountPermission
*/
LEDGER_ENTRY(ltACCOUNT_PERMISSION, 0x0081, AccountPermission, ({
{sfAccount, soeREQUIRED},
{sfAuthorize, soeREQUIRED},
{sfPermissions, soeREQUIRED},
{sfOwnerNode, soeREQUIRED},
{sfPreviousTxnID, soeREQUIRED},
{sfPreviousTxnLgrSeq, soeREQUIRED},
}))
3 changes: 3 additions & 0 deletions include/xrpl/protocol/detail/sfields.macro
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ TYPED_SFIELD(sfEmitGeneration, UINT32, 46)
TYPED_SFIELD(sfVoteWeight, UINT32, 48)
TYPED_SFIELD(sfFirstNFTokenSequence, UINT32, 50)
TYPED_SFIELD(sfOracleDocumentID, UINT32, 51)
TYPED_SFIELD(sfPermissionValue, UINT32, 52)

// 64-bit integers (common)
TYPED_SFIELD(sfIndexNext, UINT64, 1)
Expand Down Expand Up @@ -309,6 +310,7 @@ UNTYPED_SFIELD(sfSignerEntry, OBJECT, 11)
UNTYPED_SFIELD(sfNFToken, OBJECT, 12)
UNTYPED_SFIELD(sfEmitDetails, OBJECT, 13)
UNTYPED_SFIELD(sfHook, OBJECT, 14)
UNTYPED_SFIELD(sfPermission, OBJECT, 15)

// inner object (uncommon)
UNTYPED_SFIELD(sfSigner, OBJECT, 16)
Expand Down Expand Up @@ -355,3 +357,4 @@ UNTYPED_SFIELD(sfXChainCreateAccountAttestations, ARRAY, 22)
// 23 unused
UNTYPED_SFIELD(sfPriceDataSeries, ARRAY, 24)
UNTYPED_SFIELD(sfAuthAccounts, ARRAY, 25)
UNTYPED_SFIELD(sfPermissions, ARRAY, 26)
6 changes: 6 additions & 0 deletions include/xrpl/protocol/detail/transactions.macro
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,12 @@ TRANSACTION(ttLEDGER_STATE_FIX, 53, LedgerStateFix, ({
{sfOwner, soeOPTIONAL},
}))

/** This transaction type delegates authorized account specified permissions */
TRANSACTION(ttACCOUNT_PERMISSION_SET, 54, AccountPermissionSet, ({
{sfAuthorize, soeREQUIRED},
{sfPermissions, soeREQUIRED},
}))

/** This system-generated transaction type is used to update the status of the various amendments.

For details, see: https://xrpl.org/amendments.html
Expand Down
2 changes: 2 additions & 0 deletions include/xrpl/protocol/jss.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ namespace jss {
JSS(AL_size); // out: GetCounts
JSS(AL_hit_rate); // out: GetCounts
JSS(Account); // in: TransactionSign; field.
JSS(AccountPermission); // ledger type.
JSS(AccountRoot); // ledger type.
JSS(AMM); // ledger type
JSS(AMMID); // field
Expand Down Expand Up @@ -126,6 +127,7 @@ JSS(account_hash); // out: LedgerToJson
JSS(account_id); // out: WalletPropose
JSS(account_nfts); // out: AccountNFTs
JSS(account_objects); // out: AccountObjects
JSS(account_permission); // in: AccountPermission
JSS(account_root); // in: LedgerEntry
JSS(account_sequence_next); // out: SubmitTransaction
JSS(account_sequence_available); // out: SubmitTransaction
Expand Down
18 changes: 18 additions & 0 deletions src/libxrpl/protocol/Indexes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ enum class LedgerNameSpace : std::uint16_t {
XCHAIN_CREATE_ACCOUNT_CLAIM_ID = 'K',
DID = 'I',
ORACLE = 'R',
ACCOUNT_PERMISSION = 'P',

// No longer used or supported. Left here to reserve the space
// to avoid accidental reuse.
Expand Down Expand Up @@ -398,6 +399,23 @@ amm(uint256 const& id) noexcept
return {ltAMM, id};
}

Keylet
accountPermission(
AccountID const& account,
AccountID const& authorizedAccount) noexcept
{
return {
ltACCOUNT_PERMISSION,
indexHash(
LedgerNameSpace::ACCOUNT_PERMISSION, account, authorizedAccount)};
}

Keylet
accountPermission(uint256 const& key) noexcept
{
return {ltACCOUNT_PERMISSION, key};
}

Keylet
bridge(STXChainBridge const& bridge, STXChainBridge::ChainType chainType)
{
Expand Down
73 changes: 73 additions & 0 deletions src/libxrpl/protocol/Permissions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2024 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================

#include <xrpl/protocol/Permissions.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/SOTemplate.h>
#include <xrpl/protocol/jss.h>

namespace ripple {

Permission::Permission()
{
granularPermissionMap = {
{"TrustlineAuthorize", gpTrustlineAuthorize},
{"TrustlineFreeze", gpTrustlineFreeze},
{"TrustlineUnfreeze", gpTrustlineUnfreeze},
{"AccountDomainSet", gpAccountDomainSet},
{"AccountEmailHashSet", gpAccountEmailHashSet},
{"AccountMessageKeySet", gpAccountMessageKeySet},
{"AccountTransferRateSet", gpAccountTransferRateSet},
{"AccountTickSizeSet", gpAccountTickSizeSet},
{"PaymentMint", gpPaymentMint},
{"PaymentBurn", gpPaymentBurn},
{"MPTokenIssuanceLock", gpMPTokenIssuanceLock},
{"MPTokenIssuanceUnlock", gpMPTokenIssuanceUnlock}};
}

Permission const&
Permission::getInstance()
{
static Permission const instance;
return instance;
}

std::optional<std::uint32_t>
Permission::getGranularValue(const std::string& name) const
{
auto const it = granularPermissionMap.find(name);
if (it != granularPermissionMap.end())
return static_cast<uint32_t>(it->second);

return std::nullopt;
}

bool
Permission::isProhibited(const std::string& name) const
{
// We do not allow delegating the following transaction permissions to other
// accounts for security reason.
if (name == "AccountSet" || name == "SetRegularKey" ||
name == "SignerListSet")
return true;

return false;
}

} // namespace ripple
43 changes: 39 additions & 4 deletions src/libxrpl/protocol/STParsedJSON.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <xrpl/beast/core/LexicalCast.h>
#include <xrpl/protocol/ErrorCodes.h>
#include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/Permissions.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STAccount.h>
#include <xrpl/protocol/STAmount.h>
Expand Down Expand Up @@ -360,10 +361,44 @@ parseLeaf(
{
if (value.isString())
{
ret = detail::make_stvar<STUInt32>(
field,
beast::lexicalCastThrow<std::uint32_t>(
value.asString()));
if (field == sfPermissionValue)
{
std::string const strValue = value.asString();
auto const granularPermission =
Permission::getInstance().getGranularValue(
strValue);
if (!granularPermission)
{
// if it's not granular permission, parse as
// transaction type permission.
if (Permission::getInstance().isProhibited(
strValue))
{
// we do not allow delegating some transaction
// type permissions to other accounts for
// security reason.
error = invalid_data(json_name, fieldName);
return ret;
}
else
ret = detail::make_stvar<STUInt32>(
field,
static_cast<std::uint32_t>(
TxFormats::getInstance().findTypeByName(
strValue) +
1));
}
else
ret = detail::make_stvar<STUInt32>(
field, *granularPermission);
}
else
{
ret = detail::make_stvar<STUInt32>(
field,
beast::lexicalCastThrow<std::uint32_t>(
value.asString()));
}
}
else if (value.isInt())
{
Expand Down
Loading

0 comments on commit 2e9b7a6

Please sign in to comment.