@@ -3,6 +3,7 @@ use pallet_torus0_api::NamespacePath;
33use polkadot_sdk:: {
44 frame_support:: { CloneNoBound , DebugNoBound , dispatch:: DispatchResult } ,
55 sp_runtime:: { BoundedBTreeMap , BoundedBTreeSet } ,
6+ sp_std:: vec:: Vec ,
67} ;
78use scale_info:: TypeInfo ;
89
@@ -28,22 +29,8 @@ pub struct NamespaceScope<T: Config> {
2829}
2930
3031impl < T : Config > NamespaceScope < T > {
31- /// Checks that the provided paths are allowed to be delegated.
32- /// This is true if enough instances are available and unused by
33- /// sibilings.
34- ///
35- /// Given a subpath, an instance is used if any parent or child
36- /// paths from that subpath were delegated to a sibiling permission.
37- /// Sibiling subpaths do not consume an instance relative to this
38- /// subpath.
39- pub ( crate ) fn check_available_instances < ' a > (
40- & self ,
41- this_id : PermissionId ,
42- other : impl Iterator < Item = & ' a NamespacePath > ,
43- instances : u32 ,
44- ) -> DispatchResult {
45- let mut sibiling_paths = self
46- . children
32+ fn sibiling_paths ( & self , this_id : PermissionId ) -> impl Iterator < Item = ( NamespacePath , u32 ) > {
33+ self . children
4734 . iter ( )
4835 . filter_map ( |c| {
4936 if let PermissionScope :: Namespace ( sibiling) = Permissions :: < T > :: get ( c) ?. scope {
@@ -52,25 +39,44 @@ impl<T: Config> NamespaceScope<T> {
5239 None
5340 }
5441 } )
55- . flat_map ( |sibiling| {
42+ . flat_map ( move |sibiling| {
5643 sibiling
5744 . paths
5845 . into_iter ( )
59- . filter ( |( pid, _) | pid. as_ref ( ) . is_some_and ( |pid| pid == & this_id) )
46+ . filter ( move |( pid, _) | pid. as_ref ( ) . is_some_and ( |pid| pid == & this_id) )
6047 . flat_map ( |( _, paths) | paths)
6148 . map ( move |path| ( path, sibiling. max_instances ) )
6249 } )
63- . collect :: < polkadot_sdk:: sp_std:: vec:: Vec < _ > > ( ) ;
50+ }
51+
52+ /// Checks that the provided paths are allowed to be delegated.
53+ /// This is true if enough instances are available and unused by
54+ /// sibilings.
55+ ///
56+ /// Given a subpath, an instance is used if any parent or child
57+ /// paths from that subpath were delegated to a sibiling permission.
58+ /// Sibiling subpaths do not consume an instance relative to this
59+ /// subpath.
60+ pub ( crate ) fn check_available_instances < ' a > (
61+ & self ,
62+ this_id : PermissionId ,
63+ other : impl Iterator < Item = & ' a NamespacePath > ,
64+ instances : u32 ,
65+ ) -> DispatchResult {
66+ let mut sibiling_paths: Vec < _ > = self . sibiling_paths ( this_id) . collect ( ) ;
6467
6568 for other in other {
66- let mut used_instances = 0u32 ;
69+ let mut available_instances = self . max_instances ;
6770
6871 for ( sibiling_path, max_instances) in & sibiling_paths {
6972 if sibiling_path == other
7073 || sibiling_path. is_parent_of ( other)
7174 || other. is_parent_of ( sibiling_path)
7275 {
73- used_instances = used_instances. saturating_add ( * max_instances) ;
76+ available_instances = available_instances. saturating_sub ( * max_instances) ;
77+ if available_instances < instances {
78+ return Err ( Error :: < T > :: NotEnoughInstances . into ( ) ) ;
79+ }
7480 }
7581 }
7682
@@ -86,14 +92,33 @@ impl<T: Config> NamespaceScope<T> {
8692 // Earlier paths are sibilings to later paths.
8793 sibiling_paths. push ( ( other. clone ( ) , instances) ) ;
8894
89- if self . max_instances . saturating_sub ( used_instances ) < instances {
95+ if available_instances < instances {
9096 return Err ( Error :: < T > :: NotEnoughInstances . into ( ) ) ;
9197 }
9298 }
9399
94100 Ok ( ( ) )
95101 }
96102
103+ /// Count the number of available instances for a given path.
104+ pub fn available_instances ( & self , this_id : PermissionId , path : & NamespacePath ) -> u32 {
105+ let mut available_instances = self . max_instances ;
106+
107+ for ( sibiling_path, max_instances) in self . sibiling_paths ( this_id) {
108+ if & sibiling_path == path
109+ || sibiling_path. is_parent_of ( path)
110+ || path. is_parent_of ( & sibiling_path)
111+ {
112+ available_instances = available_instances. saturating_sub ( max_instances) ;
113+ if available_instances == 0 {
114+ return 0 ;
115+ }
116+ }
117+ }
118+
119+ available_instances
120+ }
121+
97122 /// Cleanup operations when permission is revoked or expired
98123 pub ( super ) fn cleanup (
99124 & self ,
0 commit comments