zombienet_orchestrator/generators/
session_0_overrides.rs1use array_bytes::bytes2hex;
2use codec::{Decode, Encode};
3use serde_json::json;
4use sp_core::crypto::AccountId32;
5use support::substorage::storage_value_key;
6
7use crate::generators::errors::GeneratorError;
8
9#[derive(PartialEq, Clone, Encode, Decode, Debug)]
14pub struct ValidatorIndex(pub u32);
15
16pub type SessionIndex = u32;
18
19#[derive(Encode, Decode, Default, Clone, Debug, PartialEq)]
21pub struct GroupIndex(pub u32);
22
23#[derive(Clone, Encode, Decode, Debug, PartialEq)]
24pub struct SessionInfo {
25 pub active_validator_indices: Vec<ValidatorIndex>,
29 pub random_seed: [u8; 32],
31 pub dispute_period: SessionIndex,
33
34 pub validators: Vec<AccountId32>,
43 pub discovery_keys: Vec<AccountId32>,
50 pub assignment_keys: Vec<AccountId32>,
56 pub validator_groups: Vec<Vec<ValidatorIndex>>,
60 pub n_cores: u32,
62 pub zeroth_delay_tranche_width: u32,
64 pub relay_vrf_modulo_samples: u32,
66 pub n_delay_tranches: u32,
68 pub no_show_slots: u32,
71 pub needed_approvals: u32,
73}
74
75pub fn generate_session_0_overrides(
76 raw_spec: &serde_json::Value,
77 num_genesis_cores: u32,
78) -> Result<serde_json::Value, GeneratorError> {
79 let mut overrides = json!({});
80 let sessions_prefix = storage_value_key(&b"ParaSessionInfo"[..], b"Sessions");
82 let session_0_key = format!(
83 "{}{}",
84 bytes2hex("0x", &sessions_prefix),
85 bytes2hex("", 0_u32.encode())
86 );
87
88 let current_value = &raw_spec["genesis"]["raw"]["top"][&session_0_key];
89 let Some(current_value_inner) = current_value.as_str() else {
90 return Err(GeneratorError::OverridingRawSpec(format!(
91 "Session_0 keys {} is missing (in genesis.raw.top)",
92 session_0_key
93 )));
94 };
95
96 let encoded = hex::decode(¤t_value_inner[2..]).map_err(|e| {
97 GeneratorError::EncodeDecodeError(format!(
98 "Error decoding hex: {}, err: {e}",
99 current_value_inner
100 ))
101 })?;
102 let mut session: SessionInfo = SessionInfo::decode(&mut encoded.as_slice()).map_err(|e| {
103 GeneratorError::EncodeDecodeError(format!("Error decoding scale: {:?}, err: {e}", encoded))
104 })?;
105
106 session.assignment_keys = session.validators.clone();
108 session.discovery_keys = session.validators.clone();
109
110 if num_genesis_cores >= session.validators.len() as u32 {
114 return Err(GeneratorError::InvariantError(format!("Num cores in genesis {num_genesis_cores} should be less than the num of validators ({})", session.validators.len())));
115 }
116
117 let groups = genetate_groups(session.validators.len() as u32, num_genesis_cores);
118 session.validator_groups = groups.clone();
119 session.n_cores = num_genesis_cores;
120
121 let session_0_value = bytes2hex("0x", session.encode());
123 overrides[session_0_key] = json!(session_0_value);
124
125 let para_scheduler_validator_groups_key = bytes2hex(
127 "0x",
128 storage_value_key(&b"ParaScheduler"[..], b"ValidatorGroups"),
129 );
130
131 overrides[para_scheduler_validator_groups_key] = json!(bytes2hex("0x", groups.encode()));
132
133 Ok(overrides)
134}
135
136fn genetate_groups(num_validators: u32, num_cores: u32) -> Vec<Vec<ValidatorIndex>> {
137 let iter = std::iter::repeat(vec![]).take(num_cores as usize);
138 let mut groups: Vec<Vec<ValidatorIndex>> = Vec::from_iter(iter);
139 for i in 0..num_validators {
140 let index = i % num_cores;
141 let group = groups.get_mut(index as usize).expect(&format!(
142 "Group index {index} should be part of groups. qed"
143 ));
144 group.push(ValidatorIndex(i));
145 }
146
147 groups
148}
149
150#[cfg(test)]
151mod test {
152 use tracing::debug;
153
154 use super::*;
155
156 #[test]
157 fn decode_encode_should_work() {
158 use support::substorage::storage_value_key;
159
160 let k = storage_value_key(&b"ParaSessionInfo"[..], b"Sessions");
161 debug!("k: {}{}", bytes2hex("", &k), bytes2hex("", 0_u32.encode()));
162
163 let encoded = hex::decode( "1003000000010000000000000002000000abc3f086f5ac20eaab792c75933b2e196307835a61a955be82aa63bc0ff9617a06000000108eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22306721211d5404bd9da88e0204360a1a9ab8b87c66c1bc2fcdd37f3c2222cc20000000000000000000000000000000010000000100000000000000").unwrap();
164 let mut session: SessionInfo = SessionInfo::decode(&mut encoded.as_slice()).unwrap();
165
166 debug!("{session:?}");
167
168 session.assignment_keys = session.validators.clone();
169 session.discovery_keys = session.validators.clone();
170
171 let encoded = session.encode();
172 debug!("{}", bytes2hex("", &encoded));
173
174 let session_modified = SessionInfo::decode(&mut &encoded[..]).unwrap();
175
176 debug!("{session_modified:?}");
177 }
178
179 #[test]
180 fn val_groups() {
181 let num_cores = 3_u32;
182 let validators = ["abc", "cds", "qwe", "eds"];
183 let groups = genetate_groups(validators.len() as u32, num_cores);
184
185 debug!("{:?}", groups);
186 assert_eq!(groups.len(), num_cores as usize);
187 }
188
189 #[test]
190 fn generate_should_work() {
191 let sessions_prefix = storage_value_key(&b"ParaSessionInfo"[..], b"Sessions");
192 let session_0_key = format!(
193 "{}{}",
194 bytes2hex("0x", &sessions_prefix),
195 bytes2hex("", 0_u32.encode())
196 );
197
198 let session_value = "0x1003000000010000000000000002000000abc3f086f5ac20eaab792c75933b2e196307835a61a955be82aa63bc0ff9617a06000000108eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22306721211d5404bd9da88e0204360a1a9ab8b87c66c1bc2fcdd37f3c2222cc20000000000000000000000000000000010000000100000000000000";
199 let mock_spec = json!({
200 "genesis": {
201 "raw": {
202 "top": {
203 session_0_key: session_value
204 }
205 }
206 }
207 });
208
209 debug!("mock {:?}", mock_spec);
210
211 let overrides = generate_session_0_overrides(&mock_spec, 3).unwrap();
212 debug!("{:?}", overrides);
213 }
214}