1use super::*;
2use crate::internal_prelude::*;
3use crate::system::bootstrap::*;
4
5#[derive(Debug, Clone, ScryptoSbor)]
6pub struct BabylonSettings {
7 pub genesis_data_chunks: Vec<GenesisDataChunk>,
8 pub genesis_epoch: Epoch,
9 pub consensus_manager_config: ConsensusManagerConfig,
10 pub initial_time_ms: i64,
11 pub initial_current_leader: Option<ValidatorIndex>,
12 pub faucet_supply: Decimal,
13}
14
15impl BabylonSettings {
16 pub fn test_minimal() -> Self {
21 Self {
22 genesis_data_chunks: vec![],
23 genesis_epoch: Epoch::of(1),
24 consensus_manager_config: ConsensusManagerConfig::test_default(),
25 initial_time_ms: 1,
26 initial_current_leader: Some(0),
27 faucet_supply: *DEFAULT_TESTING_FAUCET_SUPPLY,
28 }
29 }
30
31 pub fn test_mainnet() -> Self {
32 let pub_key = Secp256k1PrivateKey::from_u64(1u64).unwrap().public_key();
33 let genesis_epoch = Epoch::of(1);
34 let consensus_manager_config = ConsensusManagerConfig::mainnet_genesis();
35 Self::single_validator_and_staker(
36 pub_key,
37 Decimal::one(),
38 Decimal::zero(),
39 ComponentAddress::preallocated_account_from_public_key(&pub_key),
40 genesis_epoch,
41 consensus_manager_config,
42 )
43 }
44
45 pub fn test_default() -> Self {
46 let pub_key = Secp256k1PrivateKey::from_u64(1u64).unwrap().public_key();
47 let genesis_epoch = Epoch::of(1);
48 let consensus_manager_config = ConsensusManagerConfig::test_default();
49 Self::single_validator_and_staker(
50 pub_key,
51 Decimal::one(),
52 Decimal::zero(),
53 ComponentAddress::preallocated_account_from_public_key(&pub_key),
54 genesis_epoch,
55 consensus_manager_config,
56 )
57 }
58
59 pub fn single_validator_and_staker(
60 validator_public_key: Secp256k1PublicKey,
61 stake_xrd_amount: Decimal,
62 staker_account_xrd_amount: Decimal,
63 staker_account: ComponentAddress,
64 genesis_epoch: Epoch,
65 consensus_manager_config: ConsensusManagerConfig,
66 ) -> Self {
67 Self::validators_and_single_staker(
68 vec![(validator_public_key, stake_xrd_amount)],
69 staker_account,
70 staker_account_xrd_amount,
71 genesis_epoch,
72 consensus_manager_config,
73 )
74 }
75
76 pub fn validators_and_single_staker(
77 validators_and_stakes: Vec<(Secp256k1PublicKey, Decimal)>,
78 staker_account: ComponentAddress,
79 staker_account_xrd_amount: Decimal,
80 genesis_epoch: Epoch,
81 consensus_manager_config: ConsensusManagerConfig,
82 ) -> Self {
83 let genesis_validators: Vec<GenesisValidator> = validators_and_stakes
84 .iter()
85 .map(|(key, _)| key.clone().into())
86 .collect();
87 let stake_allocations: Vec<(Secp256k1PublicKey, Vec<GenesisStakeAllocation>)> =
88 validators_and_stakes
89 .into_iter()
90 .map(|(key, stake_xrd_amount)| {
91 (
92 key,
93 vec![GenesisStakeAllocation {
94 account_index: 0,
95 xrd_amount: stake_xrd_amount,
96 }],
97 )
98 })
99 .collect();
100 let genesis_data_chunks = vec![
101 GenesisDataChunk::Validators(genesis_validators),
102 GenesisDataChunk::Stakes {
103 accounts: vec![staker_account],
104 allocations: stake_allocations,
105 },
106 GenesisDataChunk::ResourceBalances {
107 accounts: vec![staker_account],
108 allocations: vec![(
109 XRD,
110 vec![GenesisResourceAllocation {
111 account_index: 0u32,
112 amount: staker_account_xrd_amount,
113 }],
114 )],
115 },
116 ];
117 Self {
118 genesis_data_chunks,
119 genesis_epoch,
120 consensus_manager_config,
121 initial_time_ms: 0,
122 initial_current_leader: Some(0),
123 faucet_supply: *DEFAULT_TESTING_FAUCET_SUPPLY,
124 }
125 }
126
127 pub fn test_complex() -> Self {
128 let validator_key = Secp256k1PublicKey([0; 33]);
129 let staker_address = ComponentAddress::preallocated_account_from_public_key(
130 &Secp256k1PrivateKey::from_u64(1).unwrap().public_key(),
131 );
132 let token_holder = ComponentAddress::preallocated_account_from_public_key(
133 &PublicKey::Secp256k1(Secp256k1PrivateKey::from_u64(1).unwrap().public_key()),
134 );
135 let resource_address = ResourceAddress::new_or_panic(
136 NodeId::new(
137 EntityType::GlobalFungibleResourceManager as u8,
138 &hash(vec![1, 2, 3]).lower_bytes(),
139 )
140 .0,
141 );
142 let stake = GenesisStakeAllocation {
143 account_index: 0,
144 xrd_amount: Decimal::one(),
145 };
146 let mut xrd_balances = Vec::new();
147 let mut pub_key_accounts = Vec::new();
148
149 for i in 0..20 {
150 let pub_key = Secp256k1PrivateKey::from_u64((i + 1).try_into().unwrap())
151 .unwrap()
152 .public_key();
153 let account_address = ComponentAddress::preallocated_account_from_public_key(&pub_key);
154 pub_key_accounts.push((pub_key, account_address));
155 xrd_balances.push((account_address, dec!("10")));
156 }
157 let genesis_resource = GenesisResource {
158 reserved_resource_address: resource_address,
159 metadata: vec![(
160 "symbol".to_string(),
161 MetadataValue::String("TST".to_string()),
162 )],
163 owner: None,
164 };
165 let resource_allocation = GenesisResourceAllocation {
166 account_index: 0,
167 amount: dec!("10"),
168 };
169 let genesis_data_chunks = vec![
170 GenesisDataChunk::Validators(vec![validator_key.clone().into()]),
171 GenesisDataChunk::Stakes {
172 accounts: vec![staker_address],
173 allocations: vec![(validator_key, vec![stake])],
174 },
175 GenesisDataChunk::XrdBalances(xrd_balances),
176 GenesisDataChunk::Resources(vec![genesis_resource]),
177 GenesisDataChunk::ResourceBalances {
178 accounts: vec![token_holder.clone()],
179 allocations: vec![(resource_address.clone(), vec![resource_allocation])],
180 },
181 ];
182 Self {
183 genesis_data_chunks,
184 genesis_epoch: Epoch::of(1),
185 consensus_manager_config: ConsensusManagerConfig::mainnet_genesis(),
186 initial_time_ms: 1,
187 initial_current_leader: Some(0),
188 faucet_supply: Decimal::zero(),
189 }
190 }
191
192 pub fn with_faucet_supply(mut self, faucet_supply: Decimal) -> Self {
193 self.faucet_supply = faucet_supply;
194 self
195 }
196
197 pub fn with_genesis_epoch(mut self, genesis_epoch: Epoch) -> Self {
198 self.genesis_epoch = genesis_epoch;
199 self
200 }
201
202 pub fn with_consensus_manager_config(
203 mut self,
204 consensus_manager_config: ConsensusManagerConfig,
205 ) -> Self {
206 self.consensus_manager_config = consensus_manager_config;
207 self
208 }
209}
210
211impl UpdateSettings for BabylonSettings {
212 type UpdateGenerator = BabylonGenerator;
213
214 fn protocol_version() -> ProtocolVersion {
215 ProtocolVersion::Babylon
216 }
217
218 fn all_enabled_as_default_for_network(_network: &NetworkDefinition) -> Self {
219 Self::test_default()
220 }
221
222 fn all_disabled() -> Self {
223 Self::test_default()
224 }
225
226 fn create_generator(&self) -> Self::UpdateGenerator {
227 Self::UpdateGenerator {
228 settings: self.clone(),
229 }
230 }
231}
232
233pub struct BabylonGenerator {
234 settings: BabylonSettings,
235}
236
237impl ProtocolUpdateGenerator for BabylonGenerator {
238 fn insert_status_tracking_flash_transactions(&self) -> bool {
239 false
241 }
242
243 fn batch_groups(&self) -> Vec<Box<dyn ProtocolUpdateBatchGroupGenerator + '_>> {
244 let bootstrap = FixedBatchGroupGenerator::named("bootstrap")
245 .add_batch("flash", |_| {
246 ProtocolUpdateBatch::single(ProtocolUpdateTransaction::flash(
247 "flash",
248 create_system_bootstrap_flash_state_updates(),
249 ))
250 })
251 .add_batch("bootstrap", |_| {
252 ProtocolUpdateBatch::single(ProtocolUpdateTransaction::genesis_transaction(
253 "bootstrap",
254 create_system_bootstrap_transaction(
255 self.settings.genesis_epoch,
256 self.settings.consensus_manager_config.clone(),
257 self.settings.initial_time_ms,
258 self.settings.initial_current_leader,
259 self.settings.faucet_supply,
260 ),
261 ))
262 });
263
264 let mut chunks = FixedBatchGroupGenerator::named("chunks");
265 for (chunk_index, chunk) in self.settings.genesis_data_chunks.iter().enumerate() {
266 let chunk_name = match chunk {
267 GenesisDataChunk::Validators { .. } => "validators",
268 GenesisDataChunk::Stakes { .. } => "stakes",
269 GenesisDataChunk::Resources { .. } => "resources",
270 GenesisDataChunk::ResourceBalances { .. } => "resource-balances",
271 GenesisDataChunk::XrdBalances { .. } => "xrd-balances",
272 };
273 chunks = chunks.add_batch(chunk_name, move |_| {
274 ProtocolUpdateBatch::single(ProtocolUpdateTransaction::genesis_transaction(
275 &format!("chunk-{chunk_index:04}"),
276 create_genesis_data_ingestion_transaction(chunk.clone(), chunk_index),
277 ))
278 });
279 }
280
281 let wrap_up = FixedBatchGroupGenerator::named("wrap-up").add_batch("wrap-up", |_| {
282 ProtocolUpdateBatch::single(ProtocolUpdateTransaction::genesis_transaction(
283 "wrap-up",
284 create_genesis_wrap_up_transaction(),
285 ))
286 });
287
288 vec![bootstrap.build(), chunks.build(), wrap_up.build()]
289 }
290}