mina_node/transition_frontier/genesis/
transition_frontier_genesis_reducer.rs1use crate::{
2 account::AccountSecretKey, block_producer::calc_epoch_seed, p2p::P2pInitializeAction,
3 transition_frontier::genesis_effectful::TransitionFrontierGenesisEffectfulAction,
4};
5use ledger::{
6 dummy::dummy_blockchain_proof, scan_state::transaction_logic::local_state::LocalState,
7};
8use mina_core::{
9 block::{genesis::genesis_and_negative_one_protocol_states, BlockWithHash},
10 constants::PROTOCOL_VERSION,
11 error,
12};
13use mina_p2p_messages::v2;
14
15use super::{
16 empty_block_body, empty_block_body_hash, empty_pending_coinbase, empty_pending_coinbase_hash,
17 TransitionFrontierGenesisAction, TransitionFrontierGenesisActionWithMetaRef,
18 TransitionFrontierGenesisState,
19};
20
21impl TransitionFrontierGenesisState {
22 pub fn reducer(
23 mut state_context: crate::Substate<Self>,
24 action: TransitionFrontierGenesisActionWithMetaRef<'_>,
25 skip_proof_verification: bool,
26 ) {
27 let Ok(state) = state_context.get_substate_mut() else {
28 return;
30 };
31 let (action, meta) = action.split();
32
33 match action {
34 TransitionFrontierGenesisAction::LedgerLoadInit => {
35 let (dispatcher, global_state) = state_context.into_dispatcher_and_state();
36 let config = global_state.transition_frontier.config.genesis.clone();
37
38 dispatcher.push(TransitionFrontierGenesisAction::LedgerLoadPending);
39 dispatcher
40 .push(TransitionFrontierGenesisEffectfulAction::LedgerLoadInit { config });
41 }
42 TransitionFrontierGenesisAction::LedgerLoadPending => {
43 *state = Self::LedgerLoadPending { time: meta.time() };
44 }
45 TransitionFrontierGenesisAction::LedgerLoadSuccess { data } => {
46 *state = Self::LedgerLoadSuccess {
47 time: meta.time(),
48 data: *data.clone(),
49 };
50
51 let dispatcher = state_context.into_dispatcher();
53 dispatcher.push(TransitionFrontierGenesisAction::Produce);
55 }
56 TransitionFrontierGenesisAction::Produce => {
57 let Self::LedgerLoadSuccess { data, .. } = state else {
58 return;
59 };
60
61 let genesis_vrf = ::mina_vrf::genesis_vrf(data.staking_epoch_seed.clone()).unwrap();
62 let genesis_vrf_hash = genesis_vrf.hash();
63
64 let Ok((negative_one, genesis, genesis_hash)) =
65 genesis_and_negative_one_protocol_states(
66 data.constants.clone(),
67 data.genesis_ledger_hash.clone(),
68 data.genesis_total_currency.clone(),
69 data.staking_epoch_ledger_hash.clone(),
70 data.staking_epoch_total_currency.clone(),
71 data.next_epoch_ledger_hash.clone(),
72 data.next_epoch_total_currency.clone(),
73 AccountSecretKey::genesis_producer().public_key().into(),
74 empty_pending_coinbase_hash(),
75 (&LocalState::dummy()).into(),
76 empty_block_body_hash(),
77 genesis_vrf.into(),
78 data.staking_epoch_seed.clone(),
79 data.next_epoch_seed.clone(),
80 calc_epoch_seed(&data.next_epoch_seed, genesis_vrf_hash), )
82 else {
83 error!(meta.time(); "invalid negative protocol state");
84 return;
85 };
86
87 *state = Self::Produced {
88 time: meta.time(),
89 negative_one,
90 genesis,
91 genesis_hash,
92 genesis_producer_stake_proof: data.genesis_producer_stake_proof.clone(),
93 };
94
95 let (dispatcher, global_state) = state_context.into_dispatcher_and_state();
97 if global_state.p2p.ready().is_none() {
98 let TransitionFrontierGenesisState::Produced {
99 genesis,
100 genesis_hash,
101 ..
102 } = &global_state.transition_frontier.genesis
103 else {
104 error!(meta.time(); "incorrect state: {:?}", global_state.transition_frontier.genesis);
105 return;
106 };
107 use mina_core::{constants, ChainId};
108 let chain_id = if let Some(override_id) = &global_state.config.chain_id_override
109 {
110 override_id.clone()
111 } else {
112 let constraint_system_digests =
113 mina_core::NetworkConfig::global().constraint_system_digests;
114 ChainId::compute(
115 constraint_system_digests,
116 genesis_hash,
117 &genesis.body.constants,
118 constants::PROTOCOL_TRANSACTION_VERSION,
119 constants::PROTOCOL_NETWORK_VERSION,
120 &v2::UnsignedExtendedUInt32StableV1::from(constants::TX_POOL_MAX_SIZE),
121 )
122 };
123 dispatcher.push(P2pInitializeAction::Initialize { chain_id });
124 }
125 dispatcher.push(TransitionFrontierGenesisAction::ProveInit);
126 }
127 TransitionFrontierGenesisAction::ProveInit => {
128 let TransitionFrontierGenesisState::Produced {
129 negative_one,
130 genesis,
131 genesis_hash,
132 genesis_producer_stake_proof,
133 ..
134 } = state
135 else {
136 return;
137 };
138
139 if skip_proof_verification {
144 let dispatcher = state_context.into_dispatcher();
145 dispatcher.push(TransitionFrontierGenesisAction::ProvePending);
146 dispatcher.push(TransitionFrontierGenesisAction::ProveSuccess {
147 proof: dummy_blockchain_proof().clone(),
148 });
149 return;
150 }
151
152 let genesis_hash = genesis_hash.clone();
153 let producer_pk = genesis.body.consensus_state.block_creator.clone();
154 let delegator_pk = genesis.body.consensus_state.block_stake_winner.clone();
155
156 let input = v2::ProverExtendBlockchainInputStableV2 {
157 chain: v2::BlockchainSnarkBlockchainStableV2 {
158 state: negative_one.clone(),
159 proof: dummy_blockchain_proof().clone(),
160 },
161 next_state: genesis.clone(),
162 block: v2::MinaStateSnarkTransitionValueStableV2 {
163 blockchain_state: genesis.body.blockchain_state.clone(),
164 consensus_transition: genesis
165 .body
166 .consensus_state
167 .curr_global_slot_since_hard_fork
168 .slot_number
169 .clone(),
170 pending_coinbase_update: v2::MinaBasePendingCoinbaseUpdateStableV1::zero(),
171 },
172 ledger_proof: None,
173 prover_state: v2::ConsensusStakeProofStableV2 {
174 delegator: v2::MinaBaseAccountIndexStableV1(0u64.into()),
175 delegator_pk,
176 coinbase_receiver_pk: genesis
177 .body
178 .consensus_state
179 .coinbase_receiver
180 .clone(),
181 producer_public_key: producer_pk,
182 producer_private_key: AccountSecretKey::genesis_producer().into(),
183 ledger: genesis_producer_stake_proof.clone(),
184 },
185 pending_coinbase: v2::MinaBasePendingCoinbaseWitnessStableV2 {
186 pending_coinbases: (&empty_pending_coinbase()).into(),
187 is_new_stack: true,
188 },
189 };
190
191 let dispatcher = state_context.into_dispatcher();
193
194 dispatcher.push(TransitionFrontierGenesisAction::ProvePending);
195 dispatcher.push(TransitionFrontierGenesisEffectfulAction::ProveInit {
196 block_hash: genesis_hash,
197 input: input.into(),
198 });
199 }
200 TransitionFrontierGenesisAction::ProvePending => {
201 let Self::Produced {
202 negative_one,
203 genesis,
204 genesis_hash,
205 genesis_producer_stake_proof,
206 ..
207 } = state
208 else {
209 return;
210 };
211
212 *state = Self::ProvePending {
213 time: meta.time(),
214 negative_one: negative_one.clone(),
215 genesis: genesis.clone(),
216 genesis_hash: genesis_hash.clone(),
217 genesis_producer_stake_proof: genesis_producer_stake_proof.clone(),
218 };
219 }
220 TransitionFrontierGenesisAction::ProveSuccess { proof } => {
221 let Self::ProvePending {
222 genesis,
223 genesis_hash,
224 ..
225 } = state
226 else {
227 return;
228 };
229
230 let block = v2::MinaBlockBlockStableV2 {
231 header: v2::MinaBlockHeaderStableV2 {
232 protocol_state: genesis.clone(),
233 protocol_state_proof: proof.clone(),
234 delta_block_chain_proof: (
235 genesis_hash.clone(),
236 std::iter::empty().collect(),
237 ),
238 current_protocol_version: PROTOCOL_VERSION.clone(),
239 proposed_protocol_version_opt: None,
240 },
241 body: v2::StagedLedgerDiffBodyStableV1 {
242 staged_ledger_diff: empty_block_body(),
243 },
244 };
245
246 let Ok(genesis) = BlockWithHash::try_new(block.into()) else {
247 error!(meta.time(); "invalid `genesis` block");
248 return;
249 };
250
251 *state = Self::ProveSuccess {
252 time: meta.time(),
253 genesis,
254 };
255 }
256 }
257 }
258}