miden_node_store/genesis/
mod.rs

1use miden_lib::transaction::TransactionKernel;
2use miden_objects::Word;
3use miden_objects::account::Account;
4use miden_objects::account::delta::AccountUpdateDetails;
5use miden_objects::block::{
6    AccountTree,
7    BlockAccountUpdate,
8    BlockHeader,
9    BlockNoteTree,
10    BlockNumber,
11    FeeParameters,
12    ProvenBlock,
13};
14use miden_objects::crypto::merkle::{Forest, MmrPeaks, Smt};
15use miden_objects::note::Nullifier;
16use miden_objects::transaction::OrderedTransactionHeaders;
17use miden_objects::utils::serde::{ByteReader, Deserializable, DeserializationError};
18
19use crate::errors::GenesisError;
20
21pub mod config;
22
23// GENESIS STATE
24// ================================================================================================
25
26/// Represents the state at genesis, which will be used to derive the genesis block.
27#[derive(Clone, Debug, PartialEq, Eq)]
28pub struct GenesisState {
29    pub accounts: Vec<Account>,
30    pub fee_parameters: FeeParameters,
31    pub version: u32,
32    pub timestamp: u32,
33}
34
35/// A type-safety wrapper ensuring that genesis block data can only be created from
36/// [`GenesisState`].
37pub struct GenesisBlock(ProvenBlock);
38
39impl GenesisBlock {
40    pub fn inner(&self) -> &ProvenBlock {
41        &self.0
42    }
43
44    pub fn into_inner(self) -> ProvenBlock {
45        self.0
46    }
47}
48
49impl GenesisState {
50    pub fn new(
51        accounts: Vec<Account>,
52        fee_parameters: FeeParameters,
53        version: u32,
54        timestamp: u32,
55    ) -> Self {
56        Self {
57            accounts,
58            fee_parameters,
59            version,
60            timestamp,
61        }
62    }
63
64    /// Returns the block header and the account SMT
65    pub fn into_block(self) -> Result<GenesisBlock, GenesisError> {
66        let accounts: Vec<BlockAccountUpdate> = self
67            .accounts
68            .iter()
69            .map(|account| {
70                let account_update_details = if account.id().is_public() {
71                    AccountUpdateDetails::New(account.clone())
72                } else {
73                    AccountUpdateDetails::Private
74                };
75
76                BlockAccountUpdate::new(account.id(), account.commitment(), account_update_details)
77            })
78            .collect();
79
80        let account_smt = AccountTree::with_entries(
81            accounts
82                .iter()
83                .map(|update| (update.account_id(), update.final_state_commitment())),
84        )
85        .map_err(GenesisError::AccountTree)?;
86
87        let empty_nullifiers: Vec<Nullifier> = Vec::new();
88        let empty_nullifier_tree = Smt::new();
89
90        let empty_output_notes = Vec::new();
91        let empty_block_note_tree = BlockNoteTree::empty();
92
93        let empty_transactions = OrderedTransactionHeaders::new_unchecked(Vec::new());
94
95        let header = BlockHeader::new(
96            self.version,
97            Word::empty(),
98            BlockNumber::GENESIS,
99            MmrPeaks::new(Forest::empty(), Vec::new()).unwrap().hash_peaks(),
100            account_smt.root(),
101            empty_nullifier_tree.root(),
102            empty_block_note_tree.root(),
103            Word::empty(),
104            TransactionKernel::kernel_commitment(),
105            Word::empty(),
106            self.fee_parameters,
107            self.timestamp,
108        );
109
110        // SAFETY: Header and accounts should be valid by construction.
111        // No notes or nullifiers are created at genesis, which is consistent with the above empty
112        // block note tree root and empty nullifier tree root.
113        Ok(GenesisBlock(ProvenBlock::new_unchecked(
114            header,
115            accounts,
116            empty_output_notes,
117            empty_nullifiers,
118            empty_transactions,
119        )))
120    }
121}
122
123// SERIALIZATION
124// ================================================================================================
125
126impl Deserializable for GenesisState {
127    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
128        let num_accounts = source.read_usize()?;
129        let accounts = source.read_many::<Account>(num_accounts)?;
130
131        let version = source.read_u32()?;
132        let timestamp = source.read_u32()?;
133        let fee_parameters = source.read::<FeeParameters>()?;
134
135        Ok(Self::new(accounts, fee_parameters, version, timestamp))
136    }
137}