1use ark_ff::fields::arithmetic::InvalidBigInt;
2use mina_p2p_messages::v2::{self, StateHash};
3
4use crate::constants::{constraint_constants, slots_per_window};
5
6#[allow(clippy::too_many_arguments)]
7pub fn genesis_and_negative_one_protocol_states(
8 constants: v2::MinaBaseProtocolConstantsCheckedValueStableV1,
9 genesis_ledger_hash: v2::LedgerHash,
10 genesis_total_currency: v2::CurrencyAmountStableV1,
11 staking_epoch_ledger_hash: v2::LedgerHash,
12 staking_epoch_total_currency: v2::CurrencyAmountStableV1,
13 next_epoch_ledger_hash: v2::LedgerHash,
14 next_epoch_total_currency: v2::CurrencyAmountStableV1,
15 genesis_winner: v2::NonZeroCurvePoint,
16 empty_pending_coinbase_hash: v2::PendingCoinbaseHash,
17 empty_local_state: v2::MinaTransactionLogicZkappCommandLogicLocalStateValueStableV1,
18 empty_body_hash: v2::ConsensusBodyReferenceStableV1,
19 genesis_vrf_output: v2::ConsensusVrfOutputTruncatedStableV1,
20 staking_epoch_seed: v2::EpochSeed,
21 next_epoch_seed: v2::EpochSeed,
22 updated_next_epoch_seed: v2::EpochSeed,
23) -> Result<
24 (
25 v2::MinaStateProtocolStateValueStableV2,
26 v2::MinaStateProtocolStateValueStableV2,
27 StateHash,
28 ),
29 InvalidBigInt,
30> {
31 let negative_one = protocol_state(
32 constants.clone(),
33 genesis_ledger_hash.clone(),
34 genesis_total_currency.clone(),
35 staking_epoch_ledger_hash.clone(),
36 staking_epoch_total_currency.clone(),
37 next_epoch_ledger_hash.clone(),
38 next_epoch_total_currency.clone(),
39 genesis_winner.clone(),
40 empty_pending_coinbase_hash.clone(),
41 empty_local_state.clone(),
42 empty_body_hash.clone(),
43 staking_epoch_seed.clone(),
44 next_epoch_seed.clone(),
45 true,
46 );
47 let negative_one_hash = negative_one.try_hash()?;
48 let mut genesis = protocol_state(
49 constants,
50 genesis_ledger_hash,
51 genesis_total_currency,
52 staking_epoch_ledger_hash,
53 staking_epoch_total_currency,
54 next_epoch_ledger_hash,
55 next_epoch_total_currency,
56 genesis_winner,
57 empty_pending_coinbase_hash,
58 empty_local_state,
59 empty_body_hash,
60 staking_epoch_seed,
61 updated_next_epoch_seed.clone(),
62 false,
63 );
64 if constraint_constants().fork.is_none() {
65 genesis.previous_state_hash = negative_one_hash.clone();
66 }
67 genesis.body.genesis_state_hash = negative_one_hash.clone();
68 genesis.body.consensus_state.last_vrf_output = genesis_vrf_output;
69 genesis.body.consensus_state.next_epoch_data =
70 v2::ConsensusProofOfStakeDataEpochDataNextValueVersionedValueStableV1 {
71 seed: updated_next_epoch_seed,
72 lock_checkpoint: negative_one_hash,
73 epoch_length: 2.into(),
74 ..genesis.body.consensus_state.next_epoch_data
75 };
76 let genesis_hash = genesis.try_hash()?;
77
78 Ok((negative_one, genesis, genesis_hash))
79}
80
81#[allow(clippy::too_many_arguments)]
82fn protocol_state(
83 constants: v2::MinaBaseProtocolConstantsCheckedValueStableV1,
84 genesis_ledger_hash: v2::LedgerHash,
85 genesis_total_currency: v2::CurrencyAmountStableV1,
86 staking_epoch_ledger_hash: v2::LedgerHash,
87 staking_epoch_total_currency: v2::CurrencyAmountStableV1,
88 next_epoch_ledger_hash: v2::LedgerHash,
89 next_epoch_total_currency: v2::CurrencyAmountStableV1,
90 genesis_winner: v2::NonZeroCurvePoint,
91 empty_pending_coinbase_hash: v2::PendingCoinbaseHash,
92 empty_local_state: v2::MinaTransactionLogicZkappCommandLogicLocalStateValueStableV1,
93 empty_body_hash: v2::ConsensusBodyReferenceStableV1,
94 staking_epoch_seed: v2::EpochSeed,
95 next_epoch_seed: v2::EpochSeed,
96 negative_one: bool,
97) -> v2::MinaStateProtocolStateValueStableV2 {
98 v2::MinaStateProtocolStateValueStableV2 {
99 previous_state_hash: match constraint_constants().fork.as_ref() {
100 None => StateHash::zero(),
101 Some(_) if negative_one => StateHash::zero(),
102 Some(fork) => StateHash::from_fp(fork.state_hash),
103 },
104 body: v2::MinaStateProtocolStateBodyValueStableV2 {
105 genesis_state_hash: StateHash::zero(),
106 blockchain_state: blockchain_state(
107 genesis_ledger_hash.clone(),
108 constants.genesis_state_timestamp,
109 empty_pending_coinbase_hash,
110 empty_local_state,
111 empty_body_hash,
112 ),
113 consensus_state: consensus_state(
114 &constants,
115 genesis_total_currency,
116 staking_epoch_ledger_hash,
117 staking_epoch_total_currency,
118 next_epoch_ledger_hash,
119 next_epoch_total_currency,
120 genesis_winner,
121 staking_epoch_seed,
122 next_epoch_seed,
123 negative_one,
124 ),
125 constants,
126 },
127 }
128}
129
130fn blockchain_state(
131 genesis_ledger_hash: v2::LedgerHash,
132 genesis_state_timestamp: v2::BlockTimeTimeStableV1,
133 empty_pending_coinbase_hash: v2::PendingCoinbaseHash,
134 empty_local_state: v2::MinaTransactionLogicZkappCommandLogicLocalStateValueStableV1,
135 empty_body_hash: v2::ConsensusBodyReferenceStableV1,
136) -> v2::MinaStateBlockchainStateValueStableV2 {
137 let stmt_registers = v2::MinaStateBlockchainStateValueStableV2LedgerProofStatementSource {
138 first_pass_ledger: genesis_ledger_hash.clone(),
139 second_pass_ledger: genesis_ledger_hash.clone(),
140 pending_coinbase_stack: v2::MinaBasePendingCoinbaseStackVersionedStableV1::empty(),
141 local_state: empty_local_state,
142 };
143 let empty_fee_excess = v2::TokenFeeExcess {
144 token: v2::TokenIdKeyHash::default(),
145 amount: v2::SignedAmount {
146 magnitude: v2::CurrencyFeeStableV1(0u64.into()),
147 sgn: v2::SgnStableV1::Pos,
148 },
149 };
150 let ledger_proof_statement = v2::MinaStateBlockchainStateValueStableV2LedgerProofStatement {
151 source: stmt_registers.clone(),
152 target: stmt_registers.clone(),
153 connecting_ledger_left: genesis_ledger_hash.clone(),
154 connecting_ledger_right: genesis_ledger_hash.clone(),
155 supply_increase: v2::MinaStateBlockchainStateValueStableV2SignedAmount {
156 magnitude: v2::CurrencyAmountStableV1(0u64.into()),
157 sgn: v2::SgnStableV1::Pos,
158 },
159 fee_excess: v2::MinaBaseFeeExcessStableV1(empty_fee_excess.clone(), empty_fee_excess),
160 sok_digest: (),
161 };
162
163 v2::MinaStateBlockchainStateValueStableV2 {
164 staged_ledger_hash: v2::MinaBaseStagedLedgerHashStableV1::zero(
165 genesis_ledger_hash.clone(),
166 empty_pending_coinbase_hash,
167 ),
168 genesis_ledger_hash,
169 ledger_proof_statement,
170 timestamp: genesis_state_timestamp,
171 body_reference: empty_body_hash,
172 }
173}
174
175#[allow(clippy::too_many_arguments)]
176fn consensus_state(
177 constants: &v2::MinaBaseProtocolConstantsCheckedValueStableV1,
178 genesis_total_currency: v2::CurrencyAmountStableV1,
179 staking_epoch_ledger_hash: v2::LedgerHash,
180 staking_epoch_total_currency: v2::CurrencyAmountStableV1,
181 next_epoch_ledger_hash: v2::LedgerHash,
182 next_epoch_total_currency: v2::CurrencyAmountStableV1,
183 genesis_winner: v2::NonZeroCurvePoint,
184 staking_epoch_seed: v2::EpochSeed,
185 next_epoch_seed: v2::EpochSeed,
186 negative_one: bool,
187) -> v2::ConsensusProofOfStakeDataConsensusStateValueStableV2 {
188 let is_genesis = if negative_one { 0 } else { 1 };
189 let (blockchain_length, global_slot_since_genesis) = match constraint_constants().fork.as_ref()
190 {
191 None => (is_genesis, 0),
192 Some(fork) => (
193 fork.blockchain_length + is_genesis,
194 fork.global_slot_since_genesis,
195 ),
196 };
197
198 v2::ConsensusProofOfStakeDataConsensusStateValueStableV2 {
199 blockchain_length: v2::UnsignedExtendedUInt32StableV1(blockchain_length.into()),
200 epoch_count: v2::UnsignedExtendedUInt32StableV1::default(),
201 min_window_density: slots_per_window(constants).into(),
202 sub_window_densities: std::iter::once(is_genesis.into())
203 .chain(
204 (1..constraint_constants().sub_windows_per_window)
205 .map(|_| constants.slots_per_sub_window),
206 )
207 .collect(),
208 last_vrf_output: v2::ConsensusVrfOutputTruncatedStableV1::zero(),
209 total_currency: genesis_total_currency,
210 curr_global_slot_since_hard_fork: v2::ConsensusGlobalSlotStableV1 {
211 slot_number: v2::MinaNumbersGlobalSlotSinceHardForkMStableV1::SinceHardFork(
212 v2::UnsignedExtendedUInt32StableV1::default(),
213 ),
214 slots_per_epoch: constants.slots_per_epoch,
215 },
216 global_slot_since_genesis: v2::MinaNumbersGlobalSlotSinceGenesisMStableV1::SinceGenesis(
217 global_slot_since_genesis.into(),
218 ),
219 staking_epoch_data:
220 v2::ConsensusProofOfStakeDataEpochDataStakingValueVersionedValueStableV1::zero(
221 staking_epoch_ledger_hash,
222 staking_epoch_total_currency,
223 staking_epoch_seed,
224 ),
225 next_epoch_data:
226 v2::ConsensusProofOfStakeDataEpochDataNextValueVersionedValueStableV1::zero(
227 next_epoch_ledger_hash,
228 next_epoch_total_currency,
229 next_epoch_seed,
230 ),
231 has_ancestor_in_same_checkpoint_window: !negative_one,
232 block_stake_winner: genesis_winner.clone(),
233 block_creator: genesis_winner.clone(),
234 coinbase_receiver: genesis_winner,
235 supercharge_coinbase: true,
236 }
237}