mina_core/
constants.rs

1use binprot_derive::BinProtWrite;
2use mina_curves::pasta::Fp;
3use mina_p2p_messages::{bigint, number, v2};
4
5pub const GENESIS_PRODUCER_SK: &str = "EKFKgDtU3rcuFTVSEpmpXSkukjmX4cKefYREi6Sdsk7E7wsT7KRw";
6
7pub const PROTOCOL_VERSION: v2::ProtocolVersionStableV2 = v2::ProtocolVersionStableV2 {
8    transaction: number::Number(3),
9    network: number::Number(0),
10    patch: number::Number(0),
11};
12
13pub fn constraint_constants() -> &'static ConstraintConstants {
14    NetworkConfig::global().constraint_constants
15}
16
17/// Constants that define fork-specific blockchain state.
18///
19/// Fork constants specify the blockchain state at which a protocol upgrade or fork occurred.
20/// These are used to handle protocol changes and ensure compatibility across network upgrades.
21#[derive(Clone, Debug)]
22pub struct ForkConstants {
23    /// Hash of the blockchain state at the fork point
24    pub state_hash: Fp,
25
26    /// Blockchain length (number of blocks) at the fork point
27    pub blockchain_length: u32,
28
29    /// Global slot number since genesis at the fork point
30    pub global_slot_since_genesis: u32,
31}
32
33/// Protocol constraint constants that define core blockchain behavior.
34///
35/// These constants configure fundamental aspects of the Mina protocol including consensus,
36/// transaction processing, economic parameters, and ledger structure. They are compile-time
37/// parameters that must be consistent across all nodes in a network.
38///
39/// ## Consensus and Timing Parameters
40///
41/// The consensus mechanism relies on slot-based timing where blocks are
42/// produced in discrete time slots. The timing hierarchy is:
43/// - **Slots**: Basic time units for block production
44/// - **Sub-windows**: Groups of slots within an epoch
45/// - **Windows**: Collections of sub-windows that define epoch structure
46/// - **Epochs**: Complete consensus periods
47///
48/// ## Economic Parameters
49///
50/// The protocol defines economic incentives through fees and rewards:
51/// - **Coinbase rewards**: Paid to block producers for successful blocks
52/// - **Account creation fees**: Required to create new accounts on the ledger
53/// - **Supercharged rewards**: Multiplier for enhanced block producer rewards
54///
55/// ## Ledger and Transaction Structure
56///
57/// The ledger uses a Merkle tree structure for efficient verification:
58/// - **Ledger depth**: Determines the maximum number of accounts (2^depth)
59/// - **Transaction capacity**: Limits transactions per block for performance
60/// - **Pending coinbase**: Manages delayed coinbase payouts
61///
62/// ## Usage Example
63///
64/// ```rust
65/// use mina_core::constants::constraint_constants;
66///
67/// // Access global constraint constants
68/// let constants = constraint_constants();
69///
70/// // Calculate slots per window
71/// let slots_per_window = constants.sub_windows_per_window;
72/// println!("Sub-windows per window: {}", slots_per_window);
73///
74/// // Get block timing
75/// let block_time_ms = constants.block_window_duration_ms;
76/// println!("Block time: {}ms", block_time_ms);
77///
78/// // Check economic parameters
79/// let coinbase_reward = constants.coinbase_amount;
80/// let creation_fee = constants.account_creation_fee;
81/// println!("Coinbase: {} nanomina, Account fee: {} nanomina",
82///          coinbase_reward, creation_fee);
83/// ```
84///
85/// ## Network Differences
86///
87/// While most constraint constants are identical across networks, some parameters
88/// may differ between mainnet and testnets for development purposes.
89///
90/// Related OCaml implementation: <https://github.com/MinaProtocol/mina/tree/compatible/src/config>
91/// Protocol specification: <https://github.com/MinaProtocol/mina/blob/compatible/docs/specs/types_and_structures/serialized_key.md>
92#[derive(Clone, Debug)]
93pub struct ConstraintConstants {
94    /// Number of sub-windows that make up a complete window.
95    ///
96    /// Used in the consensus mechanism to structure epoch timing. Combined with
97    /// `slots_per_sub_window` from protocol constants, this determines the total
98    /// slots per window: `slots_per_window = slots_per_sub_window × sub_windows_per_window`.
99    ///
100    /// **Value**: 11 (both mainnet and devnet)
101    pub sub_windows_per_window: u64,
102
103    /// Depth of the account ledger Merkle tree.
104    ///
105    /// This determines the maximum number of accounts that can be stored in the ledger:
106    /// `max_accounts = 2^ledger_depth`. The depth affects proof sizes and verification time.
107    /// A larger depth allows more accounts but increases computational overhead.
108    ///
109    /// **Value**: 35 (supports ~34 billion accounts)
110    /// **Usage**: Account addressing, sparse ledger proofs, zkSNARK constraints
111    pub ledger_depth: u64,
112
113    /// Number of blocks to delay before SNARK work becomes available.
114    ///
115    /// This creates a buffer period between when a block is produced and when
116    /// the associated SNARK work can be included in subsequent blocks. This delay
117    /// helps ensure fair distribution of SNARK work opportunities.
118    ///
119    /// **Value**: 2 blocks
120    /// **Usage**: SNARK work scheduling, proof marketplace timing
121    pub work_delay: u64,
122
123    /// Duration of each block production slot in milliseconds.
124    ///
125    /// This is the fundamental time unit for the consensus protocol. Block producers
126    /// attempt to create blocks during their assigned slots. The duration affects
127    /// network synchronization requirements and transaction confirmation times.
128    ///
129    /// **Value**: 180,000ms (3 minutes)
130    /// **Usage**: Consensus timing, slot calculations, network synchronization
131    pub block_window_duration_ms: u64,
132
133    /// Log₂ of the maximum number of transactions per block.
134    ///
135    /// The actual transaction capacity is `2^transaction_capacity_log_2`. This logarithmic
136    /// representation is used because the value directly affects zkSNARK circuit constraints.
137    /// Higher capacity allows more transactions but increases block processing time.
138    ///
139    /// Corresponds to `transaction_capacity` in the protocol specification, which defines
140    /// the maximum transactions per block (represented as `two_to_the`).
141    ///
142    /// **Value**: 7 (supports 2^7 = 128 transactions per block)
143    /// **Usage**: Transaction pool management, block construction, circuit constraints
144    pub transaction_capacity_log_2: u64,
145
146    /// Number of confirmations before coinbase reward is spendable.
147    ///
148    /// Coinbase rewards are not immediately spendable and require a certain number
149    /// of block confirmations before they can be used. This parameter defines the
150    /// depth of the pending coinbase Merkle tree structure used to track these
151    /// delayed rewards until they mature.
152    ///
153    /// **Value**: 5 (coinbase rewards require 5 block confirmations)
154    /// **Usage**: Coinbase reward management, staged ledger operations, reward maturity
155    pub pending_coinbase_depth: usize,
156
157    /// Block reward amount in nanomina (10⁻⁹ MINA).
158    ///
159    /// This is the base reward paid to block producers for successfully creating a block.
160    /// The amount is specified in nanomina, where 1 MINA = 10⁹ nanomina. Block producers
161    /// may receive additional rewards through the supercharged coinbase mechanism.
162    ///
163    /// **Value**: 720,000,000,000 nanomina (720 MINA)
164    /// **Usage**: Block producer rewards, economic incentives, reward calculations
165    pub coinbase_amount: u64,
166
167    /// Multiplier for supercharged coinbase rewards.
168    ///
169    /// Supercharged rewards were designed to provide double block rewards (factor of 2)
170    /// to block producers staking with unlocked tokens during the early mainnet period
171    /// following the 2021 launch. This mechanism incentivized participation and orderly
172    /// markets after mainnet launch.
173    ///
174    /// **Historical values**:
175    /// - Original mainnet: 2 (double rewards for unlocked tokens)
176    /// - Berkeley hardfork (June 2024): 1 (supercharged rewards removed via MIP1)
177    ///
178    /// The removal was decided by community vote on January 1, 2023, as proposed by
179    /// community member Gareth Davies. This change ensures uniform rewards for all
180    /// tokens and reduces inflation, promoting a sustainable economic model.
181    ///
182    /// **References**:
183    /// - Berkeley Upgrade: <https://minaprotocol.com/blog/minas-berkeley-upgrade-what-to-expect>
184    /// - Supercharged Rewards Removal: <https://minaprotocol.com/blog/update-on-minas-supercharged-rewards-schedule>
185    /// - Original Proposal: <https://github.com/MinaProtocol/mina/issues/5753>
186    ///
187    /// **Usage**: Enhanced reward calculations, incentive mechanisms
188    pub supercharged_coinbase_factor: u64,
189
190    /// Fee required to create a new account in nanomina.
191    ///
192    /// When a transaction creates a new account that doesn't exist on the ledger,
193    /// this fee is charged in addition to the transaction fee. This prevents
194    /// spam account creation and manages ledger growth.
195    ///
196    /// **Value**: 1,000,000,000 nanomina (1 MINA)
197    /// **Usage**: Account creation, transaction validation, fee calculations
198    pub account_creation_fee: u64,
199
200    /// Optional fork constants defining a protocol upgrade point.
201    ///
202    /// When present, these constants specify the blockchain state at which a protocol
203    /// fork or upgrade occurred. This allows the protocol to handle transitions between
204    /// different versions while maintaining consensus.
205    ///
206    /// **Usage**: Protocol upgrades, compatibility handling, genesis configuration
207    pub fork: Option<ForkConstants>,
208}
209#[derive(Clone, Debug, BinProtWrite)]
210pub struct ForkConstantsUnversioned {
211    previous_state_hash: bigint::BigInt,
212    previous_length: number::Int32,
213    genesis_slot: number::Int32,
214}
215
216impl From<&ForkConstants> for ForkConstantsUnversioned {
217    fn from(fork_constants: &ForkConstants) -> Self {
218        Self {
219            previous_state_hash: fork_constants.state_hash.into(),
220            previous_length: fork_constants.blockchain_length.into(),
221            genesis_slot: fork_constants.global_slot_since_genesis.into(),
222        }
223    }
224}
225
226#[derive(Clone, Debug, BinProtWrite)]
227pub struct ConstraintConstantsUnversioned {
228    pub sub_windows_per_window: number::Int64,
229    pub ledger_depth: number::Int64,
230    pub work_delay: number::Int64,
231    pub block_window_duration_ms: number::Int64,
232    pub transaction_capacity_log_2: number::Int64,
233    pub pending_coinbase_depth: number::Int64,
234    pub coinbase_amount: number::UInt64,
235    pub supercharged_coinbase_factor: number::Int64,
236    pub account_creation_fee: number::UInt64,
237    pub fork: Option<ForkConstantsUnversioned>,
238}
239
240impl From<&ConstraintConstants> for ConstraintConstantsUnversioned {
241    fn from(constraints: &ConstraintConstants) -> Self {
242        Self {
243            sub_windows_per_window: constraints.sub_windows_per_window.into(),
244            ledger_depth: constraints.ledger_depth.into(),
245            work_delay: constraints.work_delay.into(),
246            block_window_duration_ms: constraints.block_window_duration_ms.into(),
247            transaction_capacity_log_2: constraints.transaction_capacity_log_2.into(),
248            pending_coinbase_depth: (constraints.pending_coinbase_depth as u64).into(),
249            coinbase_amount: constraints.coinbase_amount.into(),
250            supercharged_coinbase_factor: constraints.supercharged_coinbase_factor.into(),
251            account_creation_fee: constraints.account_creation_fee.into(),
252            fork: constraints.fork.as_ref().map(|fork| fork.into()),
253        }
254    }
255}
256
257impl binprot::BinProtWrite for ConstraintConstants {
258    fn binprot_write<W: std::io::Write>(&self, w: &mut W) -> std::io::Result<()> {
259        let constraints: ConstraintConstantsUnversioned = self.into();
260        constraints.binprot_write(w)
261    }
262}
263
264pub fn slots_per_window(constants: &v2::MinaBaseProtocolConstantsCheckedValueStableV1) -> u32 {
265    constants.slots_per_sub_window.as_u32() * (constraint_constants().sub_windows_per_window as u32)
266}
267
268const fn days_to_ms(days: u64) -> u64 {
269    days * 24 * 60 * 60 * 1000
270}
271
272pub const CHECKPOINTS_PER_YEAR: u64 = 12;
273
274pub fn checkpoint_window_size_in_slots() -> u32 {
275    let one_year_ms = days_to_ms(365);
276    let slots_per_year = one_year_ms / constraint_constants().block_window_duration_ms;
277    let size_in_slots = slots_per_year / CHECKPOINTS_PER_YEAR;
278    assert_eq!(slots_per_year % CHECKPOINTS_PER_YEAR, 0);
279    size_in_slots as u32
280}
281
282pub const DEFAULT_GENESIS_TIMESTAMP_MILLISECONDS: u64 = 1707157200000;
283
284pub const PROTOCOL_TRANSACTION_VERSION: u8 = 3;
285pub const PROTOCOL_NETWORK_VERSION: u8 = 3;
286pub const TX_POOL_MAX_SIZE: u32 = 3000;
287
288pub use v2::PROTOCOL_CONSTANTS;
289
290use crate::NetworkConfig;