miden_node_store/
genesis.rs

1use miden_lib::transaction::TransactionKernel;
2use miden_objects::{
3    account::{delta::AccountUpdateDetails, Account},
4    block::{Block, BlockAccountUpdate, BlockHeader, BlockNumber},
5    crypto::merkle::{EmptySubtreeRoots, MmrPeaks, SimpleSmt, Smt},
6    utils::serde::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
7    Digest, ACCOUNT_TREE_DEPTH, BLOCK_NOTE_TREE_DEPTH,
8};
9
10use crate::errors::GenesisError;
11
12// GENESIS STATE
13// ================================================================================================
14
15/// Represents the state at genesis, which will be used to derive the genesis block.
16#[derive(Debug, PartialEq, Eq)]
17pub struct GenesisState {
18    pub accounts: Vec<Account>,
19    pub version: u32,
20    pub timestamp: u32,
21}
22
23impl GenesisState {
24    pub fn new(accounts: Vec<Account>, version: u32, timestamp: u32) -> Self {
25        Self { accounts, version, timestamp }
26    }
27
28    /// Returns the block header and the account SMT
29    pub fn into_block(self) -> Result<Block, GenesisError> {
30        let accounts: Vec<BlockAccountUpdate> = self
31            .accounts
32            .iter()
33            .map(|account| {
34                let account_update_details = if account.id().is_public() {
35                    AccountUpdateDetails::New(account.clone())
36                } else {
37                    AccountUpdateDetails::Private
38                };
39
40                BlockAccountUpdate::new(
41                    account.id(),
42                    account.hash(),
43                    account_update_details,
44                    vec![],
45                )
46            })
47            .collect();
48
49        let account_smt: SimpleSmt<ACCOUNT_TREE_DEPTH> =
50            SimpleSmt::with_leaves(accounts.iter().map(|update| {
51                (update.account_id().prefix().into(), update.new_state_hash().into())
52            }))?;
53
54        let header = BlockHeader::new(
55            self.version,
56            Digest::default(),
57            BlockNumber::GENESIS,
58            MmrPeaks::new(0, Vec::new()).unwrap().hash_peaks(),
59            account_smt.root(),
60            Smt::default().root(),
61            *EmptySubtreeRoots::entry(BLOCK_NOTE_TREE_DEPTH, 0),
62            Digest::default(),
63            TransactionKernel::kernel_root(),
64            Digest::default(),
65            self.timestamp,
66        );
67
68        Block::new(header, accounts, vec![], vec![]).map_err(Into::into)
69    }
70}
71
72// SERIALIZATION
73// ================================================================================================
74
75impl Serializable for GenesisState {
76    fn write_into<W: ByteWriter>(&self, target: &mut W) {
77        assert!(u64::try_from(self.accounts.len()).is_ok(), "too many accounts in GenesisState");
78        target.write_usize(self.accounts.len());
79        target.write_many(&self.accounts);
80
81        target.write_u32(self.version);
82        target.write_u32(self.timestamp);
83    }
84}
85
86impl Deserializable for GenesisState {
87    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
88        let num_accounts = source.read_usize()?;
89        let accounts = source.read_many::<Account>(num_accounts)?;
90
91        let version = source.read_u32()?;
92        let timestamp = source.read_u32()?;
93
94        Ok(Self::new(accounts, version, timestamp))
95    }
96}