Skip to content

Commit e478bed

Browse files
committed
add AccountPermission
1 parent 63209c2 commit e478bed

18 files changed

+473
-6
lines changed

include/xrpl/protocol/Feature.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ namespace detail {
8080
// Feature.cpp. Because it's only used to reserve storage, and determine how
8181
// large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than
8282
// the actual number of amendments. A LogicError on startup will verify this.
83-
static constexpr std::size_t numFeatures = 79;
83+
static constexpr std::size_t numFeatures = 80;
8484

8585
/** Amendments that this server supports and the default voting behavior.
8686
Whether they are enabled depends on the Rules defined in the validated

include/xrpl/protocol/Indexes.h

+11
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,17 @@ amm(Issue const& issue1, Issue const& issue2) noexcept;
272272
Keylet
273273
amm(uint256 const& amm) noexcept;
274274

275+
/** An AccountPermission */
276+
/** @{ */
277+
Keylet
278+
accountPermission(
279+
AccountID const& account,
280+
AccountID const& authorizedAccount) noexcept;
281+
282+
Keylet
283+
accountPermission(uint256 const& key) noexcept;
284+
/** @} */
285+
275286
Keylet
276287
bridge(STXChainBridge const& bridge, STXChainBridge::ChainType chainType);
277288

include/xrpl/protocol/Permissions.h

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//------------------------------------------------------------------------------
2+
/*
3+
This file is part of rippled: https://github.com/ripple/rippled
4+
Copyright (c) 2024 Ripple Labs Inc.
5+
6+
Permission to use, copy, modify, and/or distribute this software for any
7+
purpose with or without fee is hereby granted, provided that the above
8+
copyright notice and this permission notice appear in all copies.
9+
10+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13+
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17+
*/
18+
//==============================================================================
19+
20+
#ifndef RIPPLE_PROTOCOL_PERMISSIONFORMATS_H_INCLUDED
21+
#define RIPPLE_PROTOCOL_PERMISSIONFORMATS_H_INCLUDED
22+
23+
#include <xrpl/protocol/KnownFormats.h>
24+
25+
namespace ripple {
26+
27+
/**
28+
* We have transaction type account permissions and granular account
29+
* permissions. Since we will reuse the TransactionFormats to parse the
30+
* Transaction Permissions, we only define the GranularPermissionType here.
31+
*/
32+
33+
enum GranularPermissionType : std::uint32_t {
34+
gpTrustlineAuthorize = 65537,
35+
36+
gpTrustlineFreeze = 65538,
37+
38+
gpTrustlineUnfreeze = 65539,
39+
40+
gpAccountDomainSet = 65540,
41+
42+
gpAccountEmailHashSet = 65541,
43+
44+
gpAccountMessageKeySet = 65542,
45+
46+
gpAccountTransferRateSet = 65543,
47+
48+
gpAccountTickSizeSet = 65544,
49+
50+
gpPaymentMint = 65545,
51+
52+
gpPaymentBurn = 65546,
53+
54+
gpMPTokenIssuanceLock = 65547,
55+
56+
gpMPTokenIssuanceUnlock = 65548,
57+
};
58+
59+
class GranularPermission
60+
{
61+
private:
62+
GranularPermission();
63+
64+
std::unordered_map<std::string, GranularPermissionType>
65+
granularPermissionMap;
66+
67+
public:
68+
static GranularPermission const&
69+
getInstance();
70+
71+
std::optional<std::uint32_t>
72+
getValue(const std::string& name) const;
73+
};
74+
75+
} // namespace ripple
76+
77+
#endif

include/xrpl/protocol/detail/features.macro

+1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ XRPL_FIX (1513, Supported::yes, VoteBehavior::DefaultYe
9494
XRPL_FEATURE(FlowCross, Supported::yes, VoteBehavior::DefaultYes)
9595
XRPL_FEATURE(Flow, Supported::yes, VoteBehavior::DefaultYes)
9696
XRPL_FEATURE(OwnerPaysFee, Supported::no, VoteBehavior::DefaultNo)
97+
XRPL_FEATURE(AccountPermission, Supported::yes, VoteBehavior::DefaultYes)
9798

9899
// The following amendments are obsolete, but must remain supported
99100
// because they could potentially get enabled.

include/xrpl/protocol/detail/ledger_entries.macro

+14
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ LEDGER_ENTRY(ltSIGNER_LIST, 0x0053, SignerList, ({
114114
{sfSignerEntries, soeREQUIRED},
115115
{sfSignerListID, soeREQUIRED},
116116
{sfPreviousTxnID, soeREQUIRED},
117+
117118
{sfPreviousTxnLgrSeq, soeREQUIRED},
118119
}))
119120

@@ -392,3 +393,16 @@ LEDGER_ENTRY(ltORACLE, 0x0080, Oracle, ({
392393
{sfPreviousTxnID, soeREQUIRED},
393394
{sfPreviousTxnLgrSeq, soeREQUIRED},
394395
}))
396+
397+
/** A ledger object representing permissions an account has delegated to another account.
398+
399+
\sa keylet::accountPermission
400+
*/
401+
LEDGER_ENTRY(ltACCOUNT_PERMISSION, 0x0081, AccountPermission, ({
402+
{sfAccount, soeREQUIRED},
403+
{sfAuthorize, soeREQUIRED},
404+
{sfPermissions, soeREQUIRED},
405+
{sfOwnerNode, soeREQUIRED},
406+
{sfPreviousTxnID, soeREQUIRED},
407+
{sfPreviousTxnLgrSeq, soeREQUIRED},
408+
}))

include/xrpl/protocol/detail/sfields.macro

+4
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ TYPED_SFIELD(sfEmitGeneration, UINT32, 46)
111111
TYPED_SFIELD(sfVoteWeight, UINT32, 48)
112112
TYPED_SFIELD(sfFirstNFTokenSequence, UINT32, 50)
113113
TYPED_SFIELD(sfOracleDocumentID, UINT32, 51)
114+
TYPED_SFIELD(sfPermissionValue, UINT32, 52)
115+
114116

115117
// 64-bit integers (common)
116118
TYPED_SFIELD(sfIndexNext, UINT64, 1)
@@ -309,6 +311,7 @@ UNTYPED_SFIELD(sfSignerEntry, OBJECT, 11)
309311
UNTYPED_SFIELD(sfNFToken, OBJECT, 12)
310312
UNTYPED_SFIELD(sfEmitDetails, OBJECT, 13)
311313
UNTYPED_SFIELD(sfHook, OBJECT, 14)
314+
UNTYPED_SFIELD(sfPermission, OBJECT, 15)
312315

313316
// inner object (uncommon)
314317
UNTYPED_SFIELD(sfSigner, OBJECT, 16)
@@ -355,3 +358,4 @@ UNTYPED_SFIELD(sfXChainCreateAccountAttestations, ARRAY, 22)
355358
// 23 unused
356359
UNTYPED_SFIELD(sfPriceDataSeries, ARRAY, 24)
357360
UNTYPED_SFIELD(sfAuthAccounts, ARRAY, 25)
361+
UNTYPED_SFIELD(sfPermissions, ARRAY, 26)

include/xrpl/protocol/detail/transactions.macro

+6
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,12 @@ TRANSACTION(ttLEDGER_STATE_FIX, 53, LedgerStateFix, ({
386386
{sfOwner, soeOPTIONAL},
387387
}))
388388

389+
/** This transaction type delegates authorized account specified permissions */
390+
TRANSACTION(ttACCOUNT_PERMISSION_SET, 54, AccountPermissionSet, ({
391+
{sfAuthorize, soeREQUIRED},
392+
{sfPermissions, soeREQUIRED},
393+
}))
394+
389395
/** This system-generated transaction type is used to update the status of the various amendments.
390396

391397
For details, see: https://xrpl.org/amendments.html

include/xrpl/protocol/jss.h

+3
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ namespace jss {
4545
JSS(AL_size); // out: GetCounts
4646
JSS(AL_hit_rate); // out: GetCounts
4747
JSS(Account); // in: TransactionSign; field.
48+
JSS(AccountPermission); // ledger type.
4849
JSS(AccountRoot); // ledger type.
4950
JSS(AMM); // ledger type
5051
JSS(AMMID); // field
@@ -126,6 +127,7 @@ JSS(account_hash); // out: LedgerToJson
126127
JSS(account_id); // out: WalletPropose
127128
JSS(account_nfts); // out: AccountNFTs
128129
JSS(account_objects); // out: AccountObjects
130+
JSS(account_permission); // AccountPermission
129131
JSS(account_root); // in: LedgerEntry
130132
JSS(account_sequence_next); // out: SubmitTransaction
131133
JSS(account_sequence_available); // out: SubmitTransaction
@@ -718,6 +720,7 @@ JSS(write_load); // out: GetCounts
718720
JSS(xchain_owned_claim_id); // in: LedgerEntry, AccountObjects
719721
JSS(xchain_owned_create_account_claim_id); // in: LedgerEntry
720722
JSS(NegativeUNL); // out: ValidatorList; ledger type
723+
JSS(TrustlineAuthorize);
721724
// clang-format on
722725

723726
#pragma push_macro("TRANSACTION")

src/libxrpl/protocol/Indexes.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ enum class LedgerNameSpace : std::uint16_t {
7373
XCHAIN_CREATE_ACCOUNT_CLAIM_ID = 'K',
7474
DID = 'I',
7575
ORACLE = 'R',
76+
ACCOUNT_PERMISSION = 'P',
7677

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

402+
Keylet
403+
accountPermission(
404+
AccountID const& account,
405+
AccountID const& authorizedAccount) noexcept
406+
{
407+
return {
408+
ltACCOUNT_PERMISSION,
409+
indexHash(
410+
LedgerNameSpace::ACCOUNT_PERMISSION, account, authorizedAccount)};
411+
}
412+
413+
Keylet
414+
accountPermission(uint256 const& key) noexcept
415+
{
416+
return {ltACCOUNT_PERMISSION, key};
417+
}
418+
401419
Keylet
402420
bridge(STXChainBridge const& bridge, STXChainBridge::ChainType chainType)
403421
{

src/libxrpl/protocol/Permissions.cpp

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
//------------------------------------------------------------------------------
2+
/*
3+
This file is part of rippled: https://github.com/ripple/rippled
4+
Copyright (c) 2024 Ripple Labs Inc.
5+
6+
Permission to use, copy, modify, and/or distribute this software for any
7+
purpose with or without fee is hereby granted, provided that the above
8+
copyright notice and this permission notice appear in all copies.
9+
10+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13+
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17+
*/
18+
//==============================================================================
19+
20+
#include <xrpl/protocol/Permissions.h>
21+
#include <xrpl/protocol/SField.h>
22+
#include <xrpl/protocol/SOTemplate.h>
23+
#include <xrpl/protocol/jss.h>
24+
25+
namespace ripple {
26+
27+
GranularPermission::GranularPermission()
28+
{
29+
// add(jss::TrustlineAuthorize, gpTrustlineAuthorize, {});
30+
granularPermissionMap = {
31+
{"TrustlineAuthorize", gpTrustlineAuthorize},
32+
{"TrustlineFreeze", gpTrustlineFreeze},
33+
{"TrustlineUnfreeze", gpTrustlineUnfreeze},
34+
{"AccountDomainSet", gpAccountDomainSet},
35+
{"AccountEmailHashSet", gpAccountEmailHashSet},
36+
{"AccountMessageKeySet", gpAccountMessageKeySet},
37+
{"AccountTransferRateSet", gpAccountTransferRateSet},
38+
{"AccountTickSizeSet", gpAccountTickSizeSet},
39+
{"PaymentMint", gpPaymentMint},
40+
{"PaymentBurn", gpPaymentBurn},
41+
{"MPTokenIssuanceLock", gpMPTokenIssuanceLock},
42+
{"MPTokenIssuanceUnlock", gpMPTokenIssuanceUnlock}};
43+
}
44+
45+
GranularPermission const&
46+
GranularPermission::getInstance()
47+
{
48+
static GranularPermission const instance;
49+
return instance;
50+
}
51+
52+
std::optional<std::uint32_t>
53+
GranularPermission::getValue(const std::string& name) const
54+
{
55+
auto const it = granularPermissionMap.find(name);
56+
if (it != granularPermissionMap.end())
57+
return static_cast<uint32_t>(it->second);
58+
59+
return std::nullopt;
60+
}
61+
62+
} // namespace ripple

src/libxrpl/protocol/STParsedJSON.cpp

+35-4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <xrpl/beast/core/LexicalCast.h>
2424
#include <xrpl/protocol/ErrorCodes.h>
2525
#include <xrpl/protocol/LedgerFormats.h>
26+
#include <xrpl/protocol/Permissions.h>
2627
#include <xrpl/protocol/SField.h>
2728
#include <xrpl/protocol/STAccount.h>
2829
#include <xrpl/protocol/STAmount.h>
@@ -318,6 +319,15 @@ parseLeaf(
318319
if (*name == sfGeneric)
319320
name = &sfLedgerEntry;
320321
}
322+
// else if (field == sfTransactionPermission)
323+
// {
324+
// ret = detail::make_stvar<STUInt16>(
325+
// field,
326+
// static_cast<std::uint16_t>(
327+
// TxFormats::getInstance().findTypeByName(
328+
// strValue) +
329+
// 1));
330+
// }
321331
else
322332
{
323333
error = invalid_data(json_name, fieldName);
@@ -360,10 +370,31 @@ parseLeaf(
360370
{
361371
if (value.isString())
362372
{
363-
ret = detail::make_stvar<STUInt32>(
364-
field,
365-
beast::lexicalCastThrow<std::uint32_t>(
366-
value.asString()));
373+
if (field == sfPermissionValue)
374+
{
375+
auto const granularPermission =
376+
GranularPermission::getInstance().getValue(
377+
value.asString());
378+
if (!granularPermission)
379+
// if it's not granular permission, parse as
380+
// transaction type permission
381+
ret = detail::make_stvar<STUInt32>(
382+
field,
383+
static_cast<std::uint32_t>(
384+
TxFormats::getInstance().findTypeByName(
385+
value.asString()) +
386+
1));
387+
else
388+
ret = detail::make_stvar<STUInt32>(
389+
field, *granularPermission);
390+
}
391+
else
392+
{
393+
ret = detail::make_stvar<STUInt32>(
394+
field,
395+
beast::lexicalCastThrow<std::uint32_t>(
396+
value.asString()));
397+
}
367398
}
368399
else if (value.isInt())
369400
{

0 commit comments

Comments
 (0)