miden_node_store/genesis/
mod.rs

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