openmina_core/block/
genesis.rs

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}