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