mina_node_testing/scenarios/multi_node/
vrf_epoch_bounds_evaluation.rs1use std::{str::FromStr, time::Duration};
2
3use mina_p2p_messages::v2::{
4 CurrencyFeeStableV1, UnsignedExtendedUInt64Int64ForVersionTagsStableV1,
5};
6use node::{
7 account::AccountSecretKey, p2p::P2pTimeouts, BlockProducerConfig, SnarkerConfig,
8 SnarkerStrategy,
9};
10
11use crate::{
12 node::{RustNodeBlockProducerTestingConfig, RustNodeTestingConfig},
13 scenario::{ListenerNode, ScenarioStep},
14 scenarios::ClusterRunner,
15};
16
17const GLOBAL_TIMEOUT: Duration = Duration::from_secs(10 * 60);
18const STEP_DURATION: Duration = Duration::from_secs(2);
19
20const SECOND_EPOCH_LAST_SLOT: u32 = 14_279;
21const THIRD_EPOCH_LAST_SLOT: u32 = 21_419;
22
23#[derive(documented::Documented, Default, Clone, Copy)]
25pub struct MultiNodeVrfEpochBoundsEvaluation;
26
27impl MultiNodeVrfEpochBoundsEvaluation {
28 pub async fn run(self, mut runner: ClusterRunner<'_>) {
29 let initial_time = runner.get_initial_time().unwrap();
30
31 let (initial_node, _) = runner.nodes_iter().last().unwrap();
32
33 let sec_key: AccountSecretKey =
35 AccountSecretKey::from_str("EKEEpMELfQkMbJDt2fB4cFXKwSf1x4t7YD4twREy5yuJ84HBZtF9")
36 .unwrap();
37
38 let rust_config = RustNodeTestingConfig {
39 initial_time,
40 genesis: node::config::DEVNET_CONFIG.clone(),
41 max_peers: 100,
42 initial_peers: Vec::new(),
43 peer_id: Default::default(),
44 block_producer: None,
45 snark_worker: None,
46 timeouts: P2pTimeouts::default(),
47 libp2p_port: None,
48 recorder: Default::default(),
49 peer_discovery: true,
50 };
51
52 let producer_node = runner.add_rust_node(RustNodeTestingConfig {
53 block_producer: Some(RustNodeBlockProducerTestingConfig {
54 config: BlockProducerConfig {
55 pub_key: sec_key.public_key().into(),
56 custom_coinbase_receiver: None,
57 proposed_protocol_version: None,
58 },
59 sec_key: sec_key.clone(),
60 }),
61 ..rust_config.clone()
62 });
63
64 let snarker_node = runner.add_rust_node(RustNodeTestingConfig {
65 snark_worker: Some(SnarkerConfig {
66 public_key: sec_key.public_key(),
67 fee: CurrencyFeeStableV1(UnsignedExtendedUInt64Int64ForVersionTagsStableV1(
68 10_000_000.into(),
69 )),
70 strategy: SnarkerStrategy::Sequential,
71 auto_commit: true,
72 }),
73 ..rust_config
74 });
75
76 tokio::time::sleep(Duration::from_secs(2)).await;
77
78 runner
79 .exec_step(ScenarioStep::ConnectNodes {
80 dialer: producer_node,
81 listener: ListenerNode::Rust(initial_node),
82 })
83 .await
84 .unwrap();
85
86 eprintln!("[PREP] Producer node connected");
87
88 runner
89 .exec_step(ScenarioStep::ConnectNodes {
90 dialer: producer_node,
91 listener: ListenerNode::Rust(snarker_node),
92 })
93 .await
94 .unwrap();
95
96 eprintln!("[PREP] Snarker node connected");
97
98 runner
100 .produce_blocks_until(
101 producer_node,
102 "EPOCH 0-1 EVAL",
103 GLOBAL_TIMEOUT,
104 STEP_DURATION,
105 false,
106 |state, _, _| {
107 let last_evaluated_slot = state
108 .block_producer
109 .vrf_evaluator()
110 .unwrap()
111 .latest_evaluated_slot;
112
113 eprintln!("HIGHEST EVALUATED SLOT: {last_evaluated_slot}");
114
115 last_evaluated_slot == SECOND_EPOCH_LAST_SLOT
116 },
117 )
118 .await;
119
120 let (state, _) = runner.node_pending_events(producer_node, false).unwrap();
121 let last_evaluated_slot = state
122 .block_producer
123 .vrf_evaluator()
124 .unwrap()
125 .latest_evaluated_slot;
126
127 assert_eq!(
129 SECOND_EPOCH_LAST_SLOT, last_evaluated_slot,
130 "VRF evaluation missing for second epoch"
131 );
132
133 runner
135 .advance_to_epoch_bounds(producer_node, GLOBAL_TIMEOUT, STEP_DURATION)
136 .await;
137 runner
138 .produce_blocks_until(
139 producer_node,
140 "EPOCH 2 EVAL",
141 GLOBAL_TIMEOUT,
142 STEP_DURATION,
143 false,
144 |_, _, produced_blocks| produced_blocks >= 20,
145 )
146 .await;
147
148 let (state, _) = runner.node_pending_events(producer_node, false).unwrap();
149
150 let last_evaluated_slot = state
151 .block_producer
152 .vrf_evaluator()
153 .unwrap()
154 .latest_evaluated_slot;
155
156 assert_ne!(
158 SECOND_EPOCH_LAST_SLOT, last_evaluated_slot,
159 "VRF evaluation not started for third epoch"
160 );
161
162 runner
163 .produce_blocks_until(
164 producer_node,
165 "EPOCH 2 EVAL",
166 GLOBAL_TIMEOUT,
167 STEP_DURATION,
168 false,
169 |state, _, _| {
170 let last_evaluated_slot = state
171 .block_producer
172 .vrf_evaluator()
173 .unwrap()
174 .latest_evaluated_slot;
175
176 eprintln!("HIGHEST EVALUATED SLOT: {last_evaluated_slot}");
177
178 last_evaluated_slot == THIRD_EPOCH_LAST_SLOT
179 },
180 )
181 .await;
182
183 eprintln!("OK");
184 }
185}