Skip to content

Commit 87cb3d3

Browse files
refac(permission0): general pre-release tweaks (#103)
This change serves more as a QoL update then everything. The previous ID generation could allow for duplicate IDs in very specific cases, and that is now handled. When the enforcement authorities change, all ongoing enforcement votes for that permission are wiped. We cover more cases of input validation.
1 parent a926256 commit 87cb3d3

File tree

17 files changed

+212
-197
lines changed

17 files changed

+212
-197
lines changed

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"rust-analyzer.check.extraEnv": {
99
"SKIP_WASM_BUILD": "1"
1010
},
11-
"rust-analyzer.cargo.features": ["runtime-benchmarks"],
11+
"rust-analyzer.cargo.features": ["runtime-benchmarks", "testnet"],
1212
"coverage-gutters.coverageFileNames": ["target/cov.xml"],
1313
// Spell checker
1414
"cSpell.words": [

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ num-traits = { version = "0.2.19", default-features = false, features = [
5252
"libm",
5353
] }
5454
bitflags = { version = "2.9.1", default-features = false }
55+
rand = { version = "0.9.1", default-features = false }
5556

5657
# Frontier / EVM
5758
fc-api = { git = "https://github.com/paritytech/frontier.git", rev = "b9b1c620c8b418bdeeadc79725f9cfa4703c0333" }

pallets/faucet/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,4 @@ pallet-torus0.workspace = true
3333
pallet-emission0.workspace = true
3434
pallet-permission0.workspace = true
3535
pallet-governance-api.workspace = true
36+
rand = { workspace = true, features = ["thread_rng"] }

pallets/governance/src/benchmarking.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ mod benchmarks {
140140

141141
let params = proposal::GlobalParamsData {
142142
min_name_length: 2,
143-
max_name_length: T::MaxAgentNameLengthConstraint::get() as u16 - 1,
143+
max_name_length: (T::MaxAgentNameLengthConstraint::get() as u16).saturating_sub(1),
144144
max_allowed_agents: 1,
145145
min_weight_control_fee: 1,
146146
min_staking_fee: 1,

pallets/permission0/src/benchmarking.rs

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,28 @@ use polkadot_sdk::{
55
frame_benchmarking::{account, v2::*},
66
frame_system::RawOrigin,
77
sp_runtime::Percent,
8-
sp_std::vec,
98
};
109

1110
use crate::*;
1211

1312
#[benchmarks]
1413
mod benchmarks {
15-
use polkadot_sdk::sp_std::collections::btree_map::BTreeMap;
14+
use polkadot_sdk::{
15+
sp_core::TryCollect, sp_std::collections::btree_map::BTreeMap, sp_std::vec,
16+
};
1617

1718
use super::*;
1819

20+
macro_rules! bounded_btree_map {
21+
($ ( $key:expr => $value:expr ),* $(,)?) => {
22+
{
23+
TryCollect::<$crate::BoundedBTreeMap<_, _, _>>::try_collect(
24+
vec![$(($key, $value)),*].into_iter()
25+
).unwrap()
26+
}
27+
};
28+
}
29+
1930
#[benchmark]
2031
fn grant_emission_permission() {
2132
let grantor: T::AccountId = account("Grantor", 0, 0);
@@ -35,7 +46,7 @@ mod benchmarks {
3546
let stream_id: StreamId = [0; 32].into();
3647
let streams = BTreeMap::from([(stream_id, Percent::from_percent(30))]);
3748
let allocation = EmissionAllocation::Streams(streams.try_into().unwrap());
38-
let targets = vec![(target, 100)];
49+
let targets = bounded_btree_map![target => 100];
3950
let distribution = DistributionControl::Manual;
4051
let duration = PermissionDuration::Indefinite;
4152
let revocation = RevocationTerms::RevocableByGrantor;
@@ -76,7 +87,7 @@ mod benchmarks {
7687
let stream_id: StreamId = [0; 32].into();
7788
let streams = BTreeMap::from([(stream_id, Percent::from_percent(30))]);
7889
let allocation = EmissionAllocation::Streams(streams.try_into().unwrap());
79-
let targets = vec![(target, 100)];
90+
let targets = bounded_btree_map![target => 100];
8091
let permission_id = ext::emission_impl::grant_emission_permission_impl::<T>(
8192
grantor.clone(),
8293
grantee,
@@ -116,7 +127,7 @@ mod benchmarks {
116127
let stream_id: StreamId = [0; 32].into();
117128
let streams = BTreeMap::from([(stream_id, Percent::from_percent(30))]);
118129
let allocation = EmissionAllocation::Streams(streams.try_into().unwrap());
119-
let targets = vec![(target, 100)];
130+
let targets = bounded_btree_map![target => 100];
120131

121132
let permission_id = ext::emission_impl::grant_emission_permission_impl::<T>(
122133
grantor.clone(),
@@ -159,7 +170,7 @@ mod benchmarks {
159170
let stream_id: StreamId = [0; 32].into();
160171
let streams = BTreeMap::from([(stream_id, Percent::from_percent(30))]);
161172
let allocation = EmissionAllocation::Streams(streams.try_into().unwrap());
162-
let targets = vec![(target, 100)];
173+
let targets = bounded_btree_map![target => 100];
163174

164175
let permission_id = ext::emission_impl::grant_emission_permission_impl::<T>(
165176
grantor.clone(),
@@ -201,7 +212,7 @@ mod benchmarks {
201212
let stream_id: StreamId = [0; 32].into();
202213
let streams = BTreeMap::from([(stream_id, Percent::from_percent(30))]);
203214
let allocation = EmissionAllocation::Streams(streams.try_into().unwrap());
204-
let targets = vec![(target, 100)];
215+
let targets = bounded_btree_map![target => 100];
205216
let controllers = vec![controller.clone()].try_into().unwrap();
206217

207218
let enforcement = EnforcementAuthority::ControlledBy {
@@ -250,7 +261,7 @@ mod benchmarks {
250261
let stream_id: StreamId = [0; 32].into();
251262
let streams = BTreeMap::from([(stream_id, Percent::from_percent(30))]);
252263
let allocation = EmissionAllocation::Streams(streams.try_into().unwrap());
253-
let targets = vec![(target, 100)];
264+
let targets = bounded_btree_map![target => 100];
254265

255266
let permission_id = ext::emission_impl::grant_emission_permission_impl::<T>(
256267
grantor.clone(),
@@ -266,16 +277,15 @@ mod benchmarks {
266277
.expect("failed to grant permission");
267278

268279
// Prepare new controllers
269-
let controllers = vec![controller1, controller2];
280+
let controllers = vec![controller1, controller2].try_into().unwrap();
270281
let required_votes = 1u32;
271-
272-
#[extrinsic_call]
273-
set_enforcement_authority(
274-
RawOrigin::Signed(grantor),
275-
permission_id,
282+
let enforcement = EnforcementAuthority::ControlledBy {
276283
controllers,
277284
required_votes,
278-
)
285+
};
286+
287+
#[extrinsic_call]
288+
set_enforcement_authority(RawOrigin::Signed(grantor), permission_id, enforcement)
279289
}
280290

281291
#[benchmark]

pallets/permission0/src/ext/curator_impl.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ pub fn grant_curator_permission_impl<T: Config>(
134134
}
135135

136136
let scope = PermissionScope::Curator(CuratorScope { flags, cooldown });
137-
let permission_id = generate_permission_id::<T>(&grantor, &grantee, &scope);
137+
let permission_id = generate_permission_id::<T>(&grantor, &grantee, &scope)?;
138138

139139
let contract = PermissionContract {
140140
grantor,

pallets/permission0/src/ext/emission_impl.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,11 @@ use polkadot_sdk::{
1919
},
2020
frame_system::{self, ensure_signed_or_root},
2121
polkadot_sdk_frame::prelude::{BlockNumberFor, OriginFor},
22-
sp_core::Get,
22+
sp_core::{Get, TryCollect},
2323
sp_runtime::{
2424
traits::{CheckedAdd, Saturating, Zero},
25-
DispatchError, Percent, Vec,
25+
BoundedBTreeMap, DispatchError, Percent, Vec,
2626
},
27-
sp_std::collections::btree_map::BTreeMap,
2827
};
2928

3029
use pallet_torus0_api::Torus0Api;
@@ -70,6 +69,11 @@ impl<T: Config>
7069
let revocation = super::translate_revocation_terms(revocation)?;
7170
let enforcement = super::translate_enforcement_authority(enforcement)?;
7271

72+
let targets = targets
73+
.into_iter()
74+
.try_collect()
75+
.map_err(|_| crate::Error::<T>::TooManyTargets)?;
76+
7377
grant_emission_permission_impl::<T>(
7478
grantor,
7579
grantee,
@@ -114,7 +118,7 @@ pub(crate) fn grant_emission_permission_impl<T: Config>(
114118
grantor: T::AccountId,
115119
grantee: T::AccountId,
116120
allocation: EmissionAllocation<T>,
117-
targets: Vec<(T::AccountId, u16)>,
121+
targets: BoundedBTreeMap<T::AccountId, u16, T::MaxTargetsPerPermission>,
118122
distribution: DistributionControl<T>,
119123
duration: PermissionDuration<T>,
120124
revocation: RevocationTerms<T>,
@@ -134,7 +138,8 @@ pub(crate) fn grant_emission_permission_impl<T: Config>(
134138
ensure!(grantor != grantee, Error::<T>::SelfPermissionNotAllowed);
135139
ensure!(!targets.is_empty(), Error::<T>::NoTargetsSpecified);
136140

137-
for (target, _) in &targets {
141+
for (target, weight) in &targets {
142+
ensure!(*weight > 0, Error::<T>::InvalidTargetWeight);
138143
ensure!(
139144
T::Torus::is_agent_registered(target),
140145
Error::<T>::NotRegisteredAgent
@@ -201,11 +206,6 @@ pub(crate) fn grant_emission_permission_impl<T: Config>(
201206
);
202207
}
203208

204-
let target_map: BTreeMap<_, _> = targets.into_iter().collect();
205-
let targets = target_map
206-
.try_into()
207-
.map_err(|_| Error::<T>::TooManyTargets)?;
208-
209209
let emission_scope = EmissionScope {
210210
allocation: allocation.clone(),
211211
distribution,
@@ -215,7 +215,7 @@ pub(crate) fn grant_emission_permission_impl<T: Config>(
215215

216216
let scope = PermissionScope::Emission(emission_scope);
217217

218-
let permission_id = generate_permission_id::<T>(&grantor, &grantee, &scope);
218+
let permission_id = generate_permission_id::<T>(&grantor, &grantee, &scope)?;
219219

220220
let contract = PermissionContract {
221221
grantor: grantor.clone(),

pallets/permission0/src/lib.rs

Lines changed: 14 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -221,12 +221,19 @@ pub mod pallet {
221221
pub enum Error<T> {
222222
/// The agent is not registered
223223
NotRegisteredAgent,
224+
/// Permissions can only be created through extrinsics
225+
PermissionCreationOutsideExtrinsic,
226+
/// A permission with the same exact parameters was
227+
/// already created in the current block
228+
DuplicatePermissionInBlock,
224229
/// Permission not found
225230
PermissionNotFound,
226231
/// Self-permission is not allowed
227232
SelfPermissionNotAllowed,
228233
/// Invalid percentage (out of range)
229234
InvalidPercentage,
235+
/// Invalid emission weight set to target
236+
InvalidTargetWeight,
230237
/// No targets specified
231238
NoTargetsSpecified,
232239
/// Invalid threshold
@@ -296,7 +303,7 @@ pub mod pallet {
296303
origin: OriginFor<T>,
297304
grantee: T::AccountId,
298305
allocation: EmissionAllocation<T>,
299-
targets: Vec<(T::AccountId, u16)>,
306+
targets: BoundedBTreeMap<T::AccountId, u16, T::MaxTargetsPerPermission>,
300307
distribution: DistributionControl<T>,
301308
duration: PermissionDuration<T>,
302309
revocation: RevocationTerms<T>,
@@ -373,53 +380,18 @@ pub mod pallet {
373380
pub fn set_enforcement_authority(
374381
origin: OriginFor<T>,
375382
permission_id: PermissionId,
376-
controllers: Vec<T::AccountId>,
377-
required_votes: u32,
383+
enforcement: EnforcementAuthority<T>,
378384
) -> DispatchResult {
379385
let who = ensure_signed_or_root(origin)?;
380386

381-
let mut contract =
387+
let contract =
382388
Permissions::<T>::get(permission_id).ok_or(Error::<T>::PermissionNotFound)?;
383389

384-
// Only grantor or root can set enforcement authority
385390
if let Some(who) = &who {
386391
ensure!(who == &contract.grantor, Error::<T>::NotPermissionGrantor);
387392
}
388393

389-
ensure!(
390-
!controllers.is_empty(),
391-
Error::<T>::InvalidNumberOfControllers
392-
);
393-
ensure!(required_votes > 0, Error::<T>::InvalidNumberOfControllers);
394-
ensure!(
395-
required_votes as usize <= controllers.len(),
396-
Error::<T>::InvalidNumberOfControllers
397-
);
398-
399-
let controllers = controllers
400-
.try_into()
401-
.map_err(|_| Error::<T>::TooManyControllers)?;
402-
403-
contract.enforcement = EnforcementAuthority::ControlledBy {
404-
controllers,
405-
required_votes,
406-
};
407-
408-
Permissions::<T>::insert(permission_id, contract.clone());
409-
410-
if let EnforcementAuthority::ControlledBy {
411-
controllers,
412-
required_votes,
413-
} = &contract.enforcement
414-
{
415-
<Pallet<T>>::deposit_event(Event::EnforcementAuthoritySet {
416-
permission_id,
417-
controllers_count: controllers.len() as u32,
418-
required_votes: *required_votes,
419-
});
420-
}
421-
422-
Ok(())
394+
contract.update_enforcement(permission_id, enforcement)
423395
}
424396

425397
/// Grant a permission for curator delegation
@@ -469,7 +441,7 @@ fn update_permission_indices<T: Config>(
469441
grantee: &T::AccountId,
470442
permission_id: PermissionId,
471443
) -> Result<(), DispatchError> {
472-
// Update (grantor, grantee) -> permission_id mapping
444+
// Update (grantor, grantee) -> [permission_id] mapping
473445
PermissionsByParticipants::<T>::try_mutate(
474446
(grantor.clone(), grantee.clone()),
475447
|permissions| -> Result<(), DispatchError> {
@@ -491,7 +463,7 @@ fn update_permission_indices<T: Config>(
491463
},
492464
)?;
493465

494-
// Update grantor -> permission_id mapping
466+
// Update grantor -> [permission_id] mapping
495467
PermissionsByGrantor::<T>::try_mutate(
496468
grantor.clone(),
497469
|permissions| -> Result<(), DispatchError> {
@@ -513,7 +485,7 @@ fn update_permission_indices<T: Config>(
513485
},
514486
)?;
515487

516-
// Update grantee -> permission_id mapping
488+
// Update grantee -> [permission_id] mapping
517489
PermissionsByGrantee::<T>::try_mutate(
518490
grantee.clone(),
519491
|permissions| -> Result<(), DispatchError> {

0 commit comments

Comments
 (0)