19
19
use frame_support:: ensure;
20
20
use kilt_support:: test_utils:: log_and_return_error_message;
21
21
use scale_info:: prelude:: format;
22
+ use sp_runtime:: TryRuntimeError ;
22
23
23
24
use crate :: { Config , DelegationHierarchies , DelegationNodeOf , DelegationNodes } ;
24
25
25
- pub ( crate ) fn do_try_state < T : Config > ( ) -> Result < ( ) , & ' static str > {
26
- DelegationNodes :: < T > :: iter ( ) . try_for_each ( |( delegation_node_id, delegation_details) | -> Result < ( ) , & ' static str > {
27
- let hierarchy_id = delegation_details. hierarchy_root_id ;
26
+ pub ( crate ) fn do_try_state < T : Config > ( ) -> Result < ( ) , TryRuntimeError > {
27
+ DelegationNodes :: < T > :: iter ( ) . try_for_each (
28
+ |( delegation_node_id, delegation_details) | -> Result < ( ) , TryRuntimeError > {
29
+ let hierarchy_id = delegation_details. hierarchy_root_id ;
28
30
29
- // check if node is in part of a delegation hierarchy.
30
- ensure ! (
31
- DelegationHierarchies :: <T >:: contains_key( hierarchy_id) ,
32
- log_and_return_error_message( format!( "Delegation hierarchy {:?} not found" , hierarchy_id) )
33
- ) ;
34
-
35
- let parent_count = DelegationNodes :: < T > :: iter_values ( )
36
- . filter ( |delegation_node : & DelegationNodeOf < T > | delegation_node. children . contains ( & delegation_node_id) )
37
- . count ( ) ;
38
-
39
- if delegation_details. parent . is_some ( ) {
40
- // If node is a leaf or intermediate, check if it occurs only once. Otherwise we
41
- // have cycles.
42
- ensure ! (
43
- parent_count == 1 ,
44
- log_and_return_error_message( format!(
45
- "Delegation with cycles detected. Node {:?} in hierarchy {:?} has two or more parents." ,
46
- delegation_node_id, hierarchy_id
47
- ) )
48
- ) ;
49
- } else {
50
- // if parent is None, check that the root is not the children
51
- // from another node.
31
+ // check if node is in part of a delegation hierarchy.
52
32
ensure ! (
53
- parent_count == 0 ,
54
- log_and_return_error_message( format!(
55
- "Root node {:?} is child from other delegation nodes" ,
56
- delegation_node_id
57
- ) )
33
+ DelegationHierarchies :: <T >:: contains_key( hierarchy_id) ,
34
+ log_and_return_error_message( format!( "Delegation hierarchy {:?} not found" , hierarchy_id) )
58
35
) ;
59
- }
60
36
61
- // if a node is revoked, the subtree should be revoked as well.
62
- if delegation_details. details . revoked {
63
- let is_subtree_revoked = get_merged_subtree :: < T > ( delegation_details)
64
- . iter ( )
65
- . map ( |child : & DelegationNodeOf < T > | child. details . revoked )
66
- . all ( |x| x) ;
67
- ensure ! (
68
- is_subtree_revoked,
69
- log_and_return_error_message( format!(
70
- "Revoked delegation node {:?} has an unrevoked subtree." ,
71
- delegation_node_id
72
- ) )
73
- ) ;
74
- }
75
- Ok ( ( ) )
76
- } )
37
+ // Delegation hierarchy should be a tree.
38
+ check_no_cycles :: < T > ( & delegation_details, & delegation_node_id) ?;
39
+
40
+ // if a node is revoked, the subtree should be revoked as well.
41
+ check_subtree_is_revoked :: < T > ( delegation_details, & delegation_node_id)
42
+ } ,
43
+ )
77
44
}
78
45
79
46
fn get_merged_subtree < T : Config > ( node : DelegationNodeOf < T > ) -> sp_std:: vec:: Vec < DelegationNodeOf < T > > {
@@ -86,3 +53,55 @@ fn get_merged_subtree<T: Config>(node: DelegationNodeOf<T>) -> sp_std::vec::Vec<
86
53
}
87
54
children
88
55
}
56
+
57
+ fn check_subtree_is_revoked < T : Config > (
58
+ delegation_details : DelegationNodeOf < T > ,
59
+ delegation_node_id : & <T as Config >:: DelegationNodeId ,
60
+ ) -> Result < ( ) , TryRuntimeError > {
61
+ if delegation_details. details . revoked {
62
+ let is_subtree_revoked = get_merged_subtree :: < T > ( delegation_details)
63
+ . iter ( )
64
+ . map ( |child : & DelegationNodeOf < T > | child. details . revoked )
65
+ . all ( |x| x) ;
66
+ ensure ! (
67
+ is_subtree_revoked,
68
+ log_and_return_error_message( format!(
69
+ "Revoked delegation node {:?} has an unrevoked subtree." ,
70
+ delegation_node_id
71
+ ) )
72
+ ) ;
73
+ }
74
+ Ok ( ( ) )
75
+ }
76
+
77
+ fn check_no_cycles < T : Config > (
78
+ delegation_details : & DelegationNodeOf < T > ,
79
+ delegation_node_id : & <T as Config >:: DelegationNodeId ,
80
+ ) -> Result < ( ) , TryRuntimeError > {
81
+ let parent_count = DelegationNodes :: < T > :: iter_values ( )
82
+ . filter ( |delegation_node : & DelegationNodeOf < T > | delegation_node. children . contains ( delegation_node_id) )
83
+ . count ( ) ;
84
+
85
+ if delegation_details. parent . is_some ( ) {
86
+ // If node is a leaf or intermediate, check if it occurs only once. Otherwise we
87
+ // have cycles.
88
+ ensure ! (
89
+ parent_count == 1 ,
90
+ log_and_return_error_message( format!(
91
+ "Delegation with cycles detected. Node {:?} in hierarchy {:?} has two or more parents." ,
92
+ delegation_node_id, delegation_details. hierarchy_root_id
93
+ ) )
94
+ ) ;
95
+ } else {
96
+ // if parent is None, check that the root is not the children
97
+ // from another node.
98
+ ensure ! (
99
+ parent_count == 0 ,
100
+ log_and_return_error_message( format!(
101
+ "Root node {:?} is child from other delegation nodes" ,
102
+ delegation_node_id
103
+ ) )
104
+ ) ;
105
+ }
106
+ Ok ( ( ) )
107
+ }
0 commit comments