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;
6use tracing::warn;
7
8use crate::generators::errors::GeneratorError;
9
10#[derive(PartialEq, Clone, Encode, Decode, Debug)]
15pub struct ValidatorIndex(pub u32);
16
17pub type SessionIndex = u32;
19
20#[derive(Encode, Decode, Default, Clone, Debug, PartialEq)]
22pub struct GroupIndex(pub u32);
23
24#[derive(Clone, Encode, Decode, Debug, PartialEq)]
25pub struct SessionInfo {
26 pub active_validator_indices: Vec<ValidatorIndex>,
30 pub random_seed: [u8; 32],
32 pub dispute_period: SessionIndex,
34
35 pub validators: Vec<AccountId32>,
44 pub discovery_keys: Vec<AccountId32>,
51 pub assignment_keys: Vec<AccountId32>,
57 pub validator_groups: Vec<Vec<ValidatorIndex>>,
61 pub n_cores: u32,
63 pub zeroth_delay_tranche_width: u32,
65 pub relay_vrf_modulo_samples: u32,
67 pub n_delay_tranches: u32,
69 pub no_show_slots: u32,
72 pub needed_approvals: u32,
74}
75
76pub fn generate_session_0_overrides(
77 raw_spec: &serde_json::Value,
78 num_genesis_cores: u32,
79) -> Result<serde_json::Value, GeneratorError> {
80 let mut overrides = json!({});
81 if num_genesis_cores == 0 {
82 warn!("'num_genesis_cores' is 0, means that we can not override session 0. Please check your config to ensure you have paras to register in chain-spec.");
83 return Ok(overrides);
84 }
85 let sessions_prefix = storage_value_key(&b"ParaSessionInfo"[..], b"Sessions");
87 let session_0_key = format!(
88 "{}{}",
89 bytes2hex("0x", &sessions_prefix),
90 bytes2hex("", 0_u32.encode())
91 );
92
93 let current_value = &raw_spec["genesis"]["raw"]["top"][&session_0_key];
94 let Some(current_value_inner) = current_value.as_str() else {
95 return Err(GeneratorError::OverridingRawSpec(format!(
96 "Session_0 keys {} is missing (in genesis.raw.top)",
97 session_0_key
98 )));
99 };
100
101 let encoded = hex::decode(¤t_value_inner[2..]).map_err(|e| {
102 GeneratorError::EncodeDecodeError(format!(
103 "Error decoding hex: {}, err: {e}",
104 current_value_inner
105 ))
106 })?;
107 let mut session: SessionInfo = SessionInfo::decode(&mut encoded.as_slice()).map_err(|e| {
108 GeneratorError::EncodeDecodeError(format!("Error decoding scale: {:?}, err: {e}", encoded))
109 })?;
110
111 session.assignment_keys = session.validators.clone();
113 session.discovery_keys = session.validators.clone();
114
115 if num_genesis_cores > session.validators.len() as u32 {
119 return Err(GeneratorError::InvariantError(format!("Num cores in genesis {num_genesis_cores} should be less than or equal to the num of validators ({})", session.validators.len())));
120 }
121
122 let groups = genetate_groups(session.validators.len() as u32, num_genesis_cores);
123 session.validator_groups = groups.clone();
124 session.n_cores = num_genesis_cores;
125
126 let session_0_value = bytes2hex("0x", session.encode());
128 overrides[session_0_key] = json!(session_0_value);
129
130 let para_scheduler_validator_groups_key = bytes2hex(
132 "0x",
133 storage_value_key(&b"ParaScheduler"[..], b"ValidatorGroups"),
134 );
135
136 overrides[para_scheduler_validator_groups_key] = json!(bytes2hex("0x", groups.encode()));
137
138 Ok(overrides)
139}
140
141fn genetate_groups(num_validators: u32, num_cores: u32) -> Vec<Vec<ValidatorIndex>> {
142 let iter = std::iter::repeat_n(vec![], num_cores as usize);
143 let mut groups: Vec<Vec<ValidatorIndex>> = Vec::from_iter(iter);
144 for i in 0..num_validators {
145 let index = i % num_cores;
146 let group = groups.get_mut(index as usize).expect(&format!(
147 "Group index {index} should be part of groups. qed"
148 ));
149 group.push(ValidatorIndex(i));
150 }
151
152 groups
153}
154
155#[cfg(test)]
156mod test {
157 use std::assert_eq;
158
159 use tracing::debug;
160
161 use super::*;
162
163 #[test]
164 fn decode_encode_should_work() {
165 use support::substorage::storage_value_key;
166
167 let k = storage_value_key(&b"ParaSessionInfo"[..], b"Sessions");
168 debug!("k: {}{}", bytes2hex("", &k), bytes2hex("", 0_u32.encode()));
169
170 let encoded = hex::decode( "1003000000010000000000000002000000abc3f086f5ac20eaab792c75933b2e196307835a61a955be82aa63bc0ff9617a06000000108eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22306721211d5404bd9da88e0204360a1a9ab8b87c66c1bc2fcdd37f3c2222cc20000000000000000000000000000000010000000100000000000000").unwrap();
171 let mut session: SessionInfo = SessionInfo::decode(&mut encoded.as_slice()).unwrap();
172
173 debug!("{session:?}");
174
175 session.assignment_keys = session.validators.clone();
176 session.discovery_keys = session.validators.clone();
177
178 let encoded = session.encode();
179 debug!("{}", bytes2hex("", &encoded));
180
181 let session_modified = SessionInfo::decode(&mut &encoded[..]).unwrap();
182
183 debug!("{session_modified:?}");
184 }
185
186 #[test]
187 fn val_groups() {
188 let num_cores = 3_u32;
189 let validators = ["abc", "cds", "qwe", "eds"];
190 let groups = genetate_groups(validators.len() as u32, num_cores);
191
192 debug!("{:?}", groups);
193 assert_eq!(groups.len(), num_cores as usize);
194 }
195
196 #[test]
197 fn generate_should_work() {
198 let sessions_prefix = storage_value_key(&b"ParaSessionInfo"[..], b"Sessions");
199 let session_0_key = format!(
200 "{}{}",
201 bytes2hex("0x", &sessions_prefix),
202 bytes2hex("", 0_u32.encode())
203 );
204
205 let session_value = "0x1003000000010000000000000002000000abc3f086f5ac20eaab792c75933b2e196307835a61a955be82aa63bc0ff9617a06000000108eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22306721211d5404bd9da88e0204360a1a9ab8b87c66c1bc2fcdd37f3c2222cc20000000000000000000000000000000010000000100000000000000";
206 let mock_spec = json!({
207 "genesis": {
208 "raw": {
209 "top": {
210 session_0_key: session_value
211 }
212 }
213 }
214 });
215
216 debug!("mock {:?}", mock_spec);
217
218 let overrides = generate_session_0_overrides(&mock_spec, 3).unwrap();
219 debug!("{:?}", overrides);
220 assert_eq!(overrides.as_object().unwrap().keys().len(), 2);
222 }
223
224 #[test]
225 fn generate_should_work_without_cores() {
226 let sessions_prefix = storage_value_key(&b"ParaSessionInfo"[..], b"Sessions");
227 let session_0_key = format!(
228 "{}{}",
229 bytes2hex("0x", &sessions_prefix),
230 bytes2hex("", 0_u32.encode())
231 );
232
233 let session_value = "0x1003000000010000000000000002000000abc3f086f5ac20eaab792c75933b2e196307835a61a955be82aa63bc0ff9617a06000000108eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22306721211d5404bd9da88e0204360a1a9ab8b87c66c1bc2fcdd37f3c2222cc20000000000000000000000000000000010000000100000000000000";
234 let mock_spec = json!({
235 "genesis": {
236 "raw": {
237 "top": {
238 session_0_key: session_value
239 }
240 }
241 }
242 });
243
244 debug!("mock {:?}", mock_spec);
245
246 let overrides = generate_session_0_overrides(&mock_spec, 0).unwrap();
247 debug!("{:?}", overrides);
248 assert_eq!(overrides.as_object().unwrap().keys().len(), 0);
249 }
250}