Skip to main content

miden_node_store/genesis/
mod.rs

1use miden_protocol::Word;
2use miden_protocol::account::{Account, AccountPatch, AccountUpdateDetails};
3use miden_protocol::block::account_tree::{AccountIdKey, AccountTree};
4use miden_protocol::block::{
5    BlockAccountUpdate,
6    BlockBody,
7    BlockHeader,
8    BlockNoteTree,
9    BlockNumber,
10    BlockSignatures,
11    FeeParameters,
12    SignedBlock,
13    ValidatorConfig,
14};
15use miden_protocol::crypto::merkle::mmr::{Forest, MmrPeaks};
16use miden_protocol::crypto::merkle::smt::Smt;
17use miden_protocol::note::Nullifier;
18use miden_protocol::protocol_config::ProtocolConfig;
19use miden_protocol::transaction::OrderedTransactionHeaders;
20
21pub mod config;
22
23pub use miden_node_utils::genesis::GenesisBlock;
24
25// GENESIS STATE
26// ================================================================================================
27
28/// Represents the state at genesis, which will be used to derive the genesis block.
29#[derive(Clone, Debug, PartialEq, Eq)]
30pub struct GenesisState {
31    pub accounts: Vec<Account>,
32    pub fee_parameters: FeeParameters,
33    pub timestamp: u32,
34    pub validator_config: ValidatorConfig,
35    pub protocol_config: ProtocolConfig,
36}
37
38impl GenesisState {
39    pub fn new(
40        accounts: Vec<Account>,
41        fee_parameters: FeeParameters,
42        timestamp: u32,
43        validator_config: ValidatorConfig,
44        protocol_config: ProtocolConfig,
45    ) -> Self {
46        Self {
47            accounts,
48            fee_parameters,
49            timestamp,
50            validator_config,
51            protocol_config,
52        }
53    }
54
55    /// Builds the genesis block.
56    ///
57    /// The genesis block has no parent and is not signed: it acts as the chain's trust root and
58    /// must be obtained from a trusted source. Its header commits to the validator set, which is
59    /// required to sign every block after genesis.
60    pub fn into_block(self) -> anyhow::Result<GenesisBlock> {
61        let accounts: Vec<BlockAccountUpdate> = self
62            .accounts
63            .iter()
64            .map(|account| -> anyhow::Result<_> {
65                let account_update_details = if account.id().is_private() {
66                    AccountUpdateDetails::Private
67                } else {
68                    AccountUpdateDetails::Public(AccountPatch::try_from(account.clone())?)
69                };
70
71                Ok(BlockAccountUpdate::new(
72                    account.id(),
73                    account.to_commitment(),
74                    account_update_details,
75                )?)
76            })
77            .collect::<Result<Vec<_>, _>>()?;
78
79        // Convert account updates to SMT entries using account_id_to_smt_key
80        let smt_entries = accounts.iter().map(|update| {
81            (
82                AccountIdKey::from(update.account_id()).as_word(),
83                update.final_state_commitment(),
84            )
85        });
86
87        let smt =
88            Smt::with_entries(smt_entries).expect("Failed to create LargeSmt for genesis accounts");
89
90        let account_smt = AccountTree::new(smt).expect("Failed to create AccountTree for genesis");
91
92        let empty_nullifiers: Vec<Nullifier> = Vec::new();
93        let empty_nullifier_tree = Smt::new();
94
95        let empty_output_notes = Vec::new();
96        let empty_block_note_tree = BlockNoteTree::empty();
97
98        let empty_transactions = OrderedTransactionHeaders::new_unchecked(Vec::new());
99
100        let validator_config = self.validator_config;
101
102        let header = BlockHeader::new(
103            Word::empty(),
104            BlockNumber::GENESIS,
105            MmrPeaks::new(Forest::empty(), Vec::new()).unwrap().hash_peaks(),
106            account_smt.root(),
107            empty_nullifier_tree.root(),
108            empty_block_note_tree.root(),
109            empty_transactions.commitment(),
110            validator_config,
111            self.fee_parameters,
112            self.protocol_config.to_commitment(),
113            None,
114            self.timestamp,
115        );
116
117        let body = BlockBody::new_unchecked(
118            accounts,
119            empty_output_notes,
120            empty_nullifiers,
121            empty_transactions,
122        );
123
124        let signatures = BlockSignatures::new(Vec::new())
125            .map_err(|err| anyhow::anyhow!("failed to build empty genesis signatures: {err}"))?;
126
127        GenesisBlock::new(SignedBlock::new(header, body, signatures)?, self.protocol_config)
128    }
129}