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;