Skip to content

Commit cf4dd6b

Browse files
refac(permission0): move recipient field to within the scope (#134)
This change is a big one. We are moving the recipient field to within each scope. This allows the scope to decide how to handle recipients. On emissions, for example, we are bridging the gap that existed between the targets and the recipient, which confusion before: targets are now the recipients of the permissions. Just as before, a recipient can auto-revoke the permission, and in case it is of an emission type, this only means removing itself from the list of recipients without deleting it (in case there are more recipients). Closes CHAIN-122, CHAIN-124.
2 parents 1c5e0f1 + 93a7870 commit cf4dd6b

File tree

22 files changed

+1953
-491
lines changed

22 files changed

+1953
-491
lines changed

docs/changes/spec-24.md

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
# Runtime Spec Version 24 Changes
2+
3+
This document outlines all interface changes between runtime spec version 23 and 24, including new extrinsics, modified events, storage changes, and behavioral updates.
4+
5+
## Extrinsics
6+
7+
### `permission0::update_namespace_permission` (NEW)
8+
9+
```diff
10+
+#[pallet::call_index(9)]
11+
+pub fn update_namespace_permission(
12+
+ origin: OriginFor<T>,
13+
+ permission_id: PermissionId,
14+
+ max_instances: u32,
15+
+) -> DispatchResult
16+
```
17+
18+
A new extrinsic that allows permission delegators to update the maximum number of instances allowed for a namespace permission. This provides delegators with the ability to dynamically adjust permission limits after initial creation, enabling more flexible permission management.
19+
20+
### `permission0::delegate_emission_permission`
21+
22+
```diff
23+
pub fn delegate_emission_permission(
24+
delegator: T::AccountId,
25+
- recipient: T::AccountId,
26+
+ recipients: Vec<(T::AccountId, u16)>,
27+
allocation: EmissionAllocation<Balance>,
28+
- targets: Vec<(T::AccountId, u16)>,
29+
distribution: DistributionControl<Balance, BlockNumber>,
30+
duration: PermissionDuration<BlockNumber>,
31+
revocation: RevocationTerms<AccountId, BlockNumber>,
32+
enforcement: EnforcementAuthority<AccountId>,
33+
+ recipient_manager: Option<AccountId>,
34+
+ weight_setter: Option<AccountId>,
35+
) -> Result<PermissionId, DispatchError>
36+
```
37+
38+
The emission permission delegation has been restructured to consolidate recipients and their weights into a single parameter, while adding new optional manager fields. The `recipient_manager` can modify the list of recipients, while the `weight_setter` can adjust distribution weights, enabling more granular permission management.
39+
40+
## Events
41+
42+
### `permission0::PermissionDelegated`
43+
44+
```diff
45+
PermissionDelegated {
46+
delegator: T::AccountId,
47+
- recipient: T::AccountId,
48+
permission_id: PermissionId,
49+
}
50+
```
51+
52+
The `recipient` field has been removed from the `PermissionDelegated` event since permissions can now have multiple recipients. Client applications should query the permission contract directly to determine recipients.
53+
54+
### `permission0::PermissionRevoked`
55+
56+
```diff
57+
PermissionRevoked {
58+
delegator: T::AccountId,
59+
- recipient: T::AccountId,
60+
- revoked_by: T::AccountId,
61+
+ revoked_by: Option<T::AccountId>,
62+
permission_id: PermissionId,
63+
}
64+
```
65+
66+
The `recipient` field has been removed and `revoked_by` is now optional to handle cases where permissions are revoked by the system automatically (e.g., expiration) rather than by a specific account.
67+
68+
### `permission0::PermissionExpired`
69+
70+
```diff
71+
PermissionExpired {
72+
delegator: T::AccountId,
73+
- recipient: T::AccountId,
74+
permission_id: PermissionId,
75+
}
76+
```
77+
78+
Consistent with other events, the `recipient` field has been removed from `PermissionExpired` events.
79+
80+
## Storage Items
81+
82+
No storage item names were changed in this version, but several storage values were migrated through the permission pallet's v6 migration to update the internal structure of permission contracts.
83+
84+
## Structs & Enums
85+
86+
### `permission0::PermissionContract<T>`
87+
88+
```diff
89+
pub struct PermissionContract<T: Config> {
90+
pub delegator: T::AccountId,
91+
- pub recipient: T::AccountId,
92+
pub scope: PermissionScope<T>,
93+
// ... other fields
94+
}
95+
```
96+
97+
The `recipient` field has been removed from the main contract structure since recipients are now scope-specific and can be multiple accounts for emission permissions.
98+
99+
### `permission0::EmissionScope<T>`
100+
101+
```diff
102+
pub struct EmissionScope<T: Config> {
103+
+ pub recipients: BoundedBTreeMap<T::AccountId, u16, T::MaxTargetsPerPermission>,
104+
pub allocation: EmissionAllocation<T>,
105+
pub distribution: DistributionControl<T>,
106+
- pub targets: BoundedBTreeMap<T::AccountId, u16, T::MaxTargetsPerPermission>,
107+
pub accumulating: bool,
108+
+ pub recipient_manager: Option<T::AccountId>,
109+
+ pub weight_setter: Option<T::AccountId>,
110+
}
111+
```
112+
113+
The `targets` field has been renamed to `recipients` for clarity, and new manager fields enable delegated management of recipients and weights within emission permissions.
114+
115+
### `permission0::CuratorScope<T>`
116+
117+
```diff
118+
pub struct CuratorScope<T: Config> {
119+
+ pub recipient: T::AccountId,
120+
pub flags: BoundedBTreeMap<
121+
Option<PermissionId>,
122+
CuratorPermissions,
123+
T::MaxCuratorSubpermissionsPerPermission,
124+
>,
125+
pub cooldown: Option<BlockNumberFor<T>>,
126+
}
127+
```
128+
129+
The `recipient` field has been added to track the specific recipient of curator permissions, and the flags structure now supports parent-child relationships through the optional PermissionId key.
130+
131+
### `permission0::NamespaceScope<T>`
132+
133+
```diff
134+
pub struct NamespaceScope<T: Config> {
135+
+ pub recipient: T::AccountId,
136+
pub paths: BoundedBTreeMap<
137+
Option<PermissionId>,
138+
BoundedBTreeSet<NamespacePath, T::MaxNamespacesPerPermission>,
139+
T::MaxNamespacesPerPermission,
140+
>,
141+
}
142+
```
143+
144+
Similar to curator permissions, namespace permissions now explicitly track their recipient and support hierarchical path delegation through the optional PermissionId structure.
145+
146+
## Behavior Changes
147+
148+
### Permission Recipients Management
149+
150+
**What changed**: Permission contracts no longer store a single recipient in the main contract structure. Instead, recipients are managed within each permission scope type, allowing for multiple recipients in emission permissions and explicit recipient tracking in curator and namespace permissions.
151+
152+
**Why it matters**: This change enables more flexible permission models, particularly for emission permissions where multiple accounts can receive distributions from a single permission contract. It also provides clearer separation of concerns between permission metadata and scope-specific recipient management.
153+
154+
**Migration needed**: Existing permission contracts are automatically migrated during runtime upgrade. Client applications that previously relied on the `recipient` field in events or contract queries must be updated to extract recipient information from the appropriate scope structure.
155+
156+
*Tests*: The migration is validated through comprehensive tests in `pallets/permission0/src/migrations.rs` that ensure all existing permissions are correctly transformed and all storage indices are properly updated.
157+
158+
*Cross-pallet impact*: Changes affect any pallet that queries permission contracts, though the API layer abstracts most of these changes from external consumers.
159+
160+
### Emission Permission Weight Management
161+
162+
**What changed**: Emission permissions now support designated `weight_setter` and `recipient_manager` accounts that can modify distribution parameters without requiring the original delegator's signature. The permission validation logic checks these manager accounts when processing updates.
163+
164+
**Why it matters**: This enables delegated management of emission streams where the original permission creator can designate trusted accounts to handle operational aspects like weight adjustments or recipient list management. This is particularly useful for automated systems or multi-signature scenarios.
165+
166+
**Migration needed**: Existing emission permissions will have `None` values for the new manager fields and continue to work with delegator-only management. New permissions can optionally specify managers during creation.
167+
168+
*Tests*: Manager functionality is validated through permission update tests that verify proper access control for different management roles.
169+
170+
*Cross-pallet impact*: The emission0 pallet can leverage these new management capabilities for more flexible weight control delegation scenarios.
171+
172+
### Permission Index Management
173+
174+
**What changed**: The permission indexing system has been redesigned to handle multiple recipients per permission contract. The new system maintains separate indices for delegators and participants (recipients), with proper cleanup when permissions are modified or revoked.
175+
176+
**Why it matters**: This ensures that permission queries remain efficient even with the new multi-recipient model, and that storage cleanup properly handles all affected accounts when permissions change.
177+
178+
**Migration needed**: The migration automatically rebuilds all permission indices using the new structure. No client-side changes are required.
179+
180+
*Tests*: Index management is validated through migration tests that verify index consistency before and after the upgrade, including edge cases with complex permission hierarchies.
181+
182+
*Cross-pallet impact*: Any pallet querying permissions by recipient will benefit from the improved index structure, with better performance for multi-recipient scenarios.

flake.nix

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
pkgs.python310
5252
# Subxt CLI for metadata handling
5353
pkgs.subxt
54+
pkgs.cargo-nextest
5455
# # Code coverage tool
5556
# pkgs.cargo-llvm-cov # marked as broken
5657
];
@@ -59,7 +60,17 @@
5960
checks = pkgs.mkShell {
6061
pre-commit-check = pre-commit-hooks.lib.${system}.run {
6162
src = ./.;
62-
hooks = { rustfmt.enable = true; };
63+
hooks = {
64+
rustfmt.enable = true;
65+
66+
push = {
67+
enable = true;
68+
name = "Tests & Stuff";
69+
entry = "just test";
70+
pass_filenames = false;
71+
stages = ["pre-push"];
72+
};
73+
};
6374
};
6475
};
6576

justfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ build-testnet:
1010

1111
# Development
1212

13-
check:
13+
check: fmt
1414
cargo clippy --tests
1515

16-
test:
17-
cargo test
16+
test: check
17+
cargo nextest run
1818

1919
fmt:
2020
cargo fmt

pallets/faucet/tests/faucet.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ impl pallet_governance::Config for Test {
232232

233233
parameter_types! {
234234
pub const PermissionPalletId: PalletId = PalletId(*b"torusper");
235-
pub const MaxTargetsPerPermission: u32 = 100;
235+
pub const MaxRecipientsPerPermission: u32 = 100;
236236
pub const MaxStreamsPerPermission: u32 = 100;
237237
pub const MaxRevokersPerPermission: u32 = 10;
238238
pub const MaxControllersPerPermission: u32 = 10;
@@ -250,7 +250,7 @@ impl pallet_permission0::Config for Test {
250250

251251
type Torus = Torus0;
252252

253-
type MaxTargetsPerPermission = MaxTargetsPerPermission;
253+
type MaxRecipientsPerPermission = MaxRecipientsPerPermission;
254254

255255
type MaxStreamsPerPermission = MaxStreamsPerPermission;
256256

pallets/permission0/api/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ use polkadot_sdk::{
66
frame_support::dispatch::DispatchResult,
77
sp_core::{H256, blake2_256},
88
sp_runtime::{DispatchError, Percent},
9-
sp_std::collections::btree_map::BTreeMap,
10-
sp_std::vec::Vec,
9+
sp_std::{collections::btree_map::BTreeMap, vec::Vec},
1110
};
1211
use scale_info::TypeInfo;
1312

@@ -106,13 +105,14 @@ pub trait Permission0EmissionApi<AccountId, Origin, BlockNumber, Balance, Negati
106105
#[allow(clippy::too_many_arguments)]
107106
fn delegate_emission_permission(
108107
delegator: AccountId,
109-
recipient: AccountId,
108+
recipients: Vec<(AccountId, u16)>,
110109
allocation: EmissionAllocation<Balance>,
111-
targets: Vec<(AccountId, u16)>,
112110
distribution: DistributionControl<Balance, BlockNumber>,
113111
duration: PermissionDuration<BlockNumber>,
114112
revocation: RevocationTerms<AccountId, BlockNumber>,
115113
enforcement: EnforcementAuthority<AccountId>,
114+
recipient_manager: Option<AccountId>,
115+
weight_setter: Option<AccountId>,
116116
) -> Result<PermissionId, DispatchError>;
117117

118118
/// Accumulate emissions for an agent with permissions

0 commit comments

Comments
 (0)