miden_node_store/genesis/
mod.rs1use miden_protocol::Word;
2use miden_protocol::account::delta::AccountUpdateDetails;
3use miden_protocol::account::{Account, AccountDelta};
4use miden_protocol::block::account_tree::{AccountIdKey, AccountTree};
5use miden_protocol::block::{
6 BlockAccountUpdate,
7 BlockBody,
8 BlockHeader,
9 BlockNoteTree,
10 BlockNumber,
11 FeeParameters,
12 SignedBlock,
13};
14use miden_protocol::crypto::dsa::ecdsa_k256_keccak::{PublicKey, Signature, SigningKey};
15use miden_protocol::crypto::merkle::mmr::{Forest, MmrPeaks};
16use miden_protocol::crypto::merkle::smt::Smt;
17use miden_protocol::errors::AccountError;
18use miden_protocol::note::Nullifier;
19use miden_protocol::transaction::{OrderedTransactionHeaders, TransactionKernel};
20
21pub mod config;
22
23#[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 pub validator_key: PublicKey,
34}
35
36pub struct GenesisBlock(SignedBlock);
39
40pub struct UnsignedGenesisBlock {
42 header: BlockHeader,
43 body: BlockBody,
44}
45
46impl UnsignedGenesisBlock {
47 pub fn header(&self) -> &BlockHeader {
48 &self.header
49 }
50
51 pub fn into_block(self, signature: Signature) -> anyhow::Result<GenesisBlock> {
52 anyhow::ensure!(
53 signature.verify(self.header.commitment(), self.header.validator_key()),
54 "genesis block signature verification failed",
55 );
56
57 Ok(GenesisBlock(SignedBlock::new(self.header, self.body, signature)?))
58 }
59}
60
61impl GenesisBlock {
62 pub fn inner(&self) -> &SignedBlock {
63 &self.0
64 }
65
66 pub fn into_inner(self) -> SignedBlock {
67 self.0
68 }
69}
70
71impl TryFrom<SignedBlock> for GenesisBlock {
72 type Error = anyhow::Error;
73
74 fn try_from(block: SignedBlock) -> anyhow::Result<Self> {
75 anyhow::ensure!(
76 block.header().block_num() == BlockNumber::GENESIS,
77 "expected genesis block number (0), got {}",
78 block.header().block_num(),
79 );
80
81 anyhow::ensure!(
82 block
83 .signature()
84 .verify(block.header().commitment(), block.header().validator_key()),
85 "genesis block signature verification failed",
86 );
87
88 Ok(Self(block))
89 }
90}
91
92impl GenesisState {
93 pub fn new(
94 accounts: Vec<Account>,
95 fee_parameters: FeeParameters,
96 version: u32,
97 timestamp: u32,
98 validator_key: PublicKey,
99 ) -> Self {
100 Self {
101 accounts,
102 fee_parameters,
103 version,
104 timestamp,
105 validator_key,
106 }
107 }
108
109 pub fn into_unsigned_block(self) -> anyhow::Result<UnsignedGenesisBlock> {
111 let accounts: Vec<BlockAccountUpdate> = self
112 .accounts
113 .iter()
114 .map(|account| {
115 let account_update_details = if account.id().is_private() {
116 AccountUpdateDetails::Private
117 } else {
118 AccountUpdateDetails::Delta(AccountDelta::try_from(account.clone())?)
119 };
120
121 Ok(BlockAccountUpdate::new(
122 account.id(),
123 account.to_commitment(),
124 account_update_details,
125 ))
126 })
127 .collect::<Result<Vec<_>, AccountError>>()?;
128
129 let smt_entries = accounts.iter().map(|update| {
131 (
132 AccountIdKey::from(update.account_id()).as_word(),
133 update.final_state_commitment(),
134 )
135 });
136
137 let smt =
138 Smt::with_entries(smt_entries).expect("Failed to create LargeSmt for genesis accounts");
139
140 let account_smt = AccountTree::new(smt).expect("Failed to create AccountTree for genesis");
141
142 let empty_nullifiers: Vec<Nullifier> = Vec::new();
143 let empty_nullifier_tree = Smt::new();
144
145 let empty_output_notes = Vec::new();
146 let empty_block_note_tree = BlockNoteTree::empty();
147
148 let empty_transactions = OrderedTransactionHeaders::new_unchecked(Vec::new());
149
150 let header = BlockHeader::new(
151 self.version,
152 Word::empty(),
153 BlockNumber::GENESIS,
154 MmrPeaks::new(Forest::empty(), Vec::new()).unwrap().hash_peaks(),
155 account_smt.root(),
156 empty_nullifier_tree.root(),
157 empty_block_note_tree.root(),
158 Word::empty(),
159 TransactionKernel.to_commitment(),
160 self.validator_key,
161 self.fee_parameters,
162 self.timestamp,
163 );
164
165 let body = BlockBody::new_unchecked(
166 accounts,
167 empty_output_notes,
168 empty_nullifiers,
169 empty_transactions,
170 );
171
172 Ok(UnsignedGenesisBlock { header, body })
173 }
174
175 pub fn into_block(self, signer: &SigningKey) -> anyhow::Result<GenesisBlock> {
177 let unsigned_block = self.into_unsigned_block()?;
178 let signature = signer.sign(unsigned_block.header().commitment());
179 unsigned_block.into_block(signature)
180 }
181}