mina_node_testing/scenarios/multi_node/
vrf_epoch_bounds_evaluation.rs

1use 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/// TODO: DOCS
24#[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        // for account B62qrztYfPinaKqpXaYGY6QJ3SSW2NNKs7SajBLF1iFNXW9BoALN2Aq
34        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        // produce blocks until evaluation finishes for the first two epochs
99        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        // should have all the slots in the first and second epoch
128        assert_eq!(
129            SECOND_EPOCH_LAST_SLOT, last_evaluated_slot,
130            "VRF evaluation missing for second epoch"
131        );
132
133        // skip to the epoch bounds
134        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        // after the epoch changes the new evaluation should start
157        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}