use std::collections::{HashMap, HashSet};
use diesel::prelude::*;
use miden_node_db::DatabaseError;
use miden_protocol::Word;
use miden_protocol::account::AccountId;
use miden_protocol::block::BlockNumber;
use miden_protocol::crypto::merkle::mmr::PartialMmr;
use miden_protocol::transaction::TransactionId;
use super::account_effect::NetworkAccountEffect;
use crate::committed_block::CommittedBlockEffects;
mod accounts;
pub use accounts::*;
mod chain_state;
pub use chain_state::*;
mod note_scripts;
pub use note_scripts::*;
mod notes;
pub use notes::*;
#[cfg(test)]
mod tests;
pub fn apply_committed_block(
conn: &mut SqliteConnection,
effects: &CommittedBlockEffects,
chain_mmr: &PartialMmr,
) -> Result<Vec<AccountId>, DatabaseError> {
let mut affected_accounts: HashSet<AccountId> = HashSet::new();
let last_tx: HashMap<AccountId, _> = effects.account_transactions.iter().copied().collect();
let is_genesis = effects.header.block_num() == BlockNumber::GENESIS;
for (account_id, details) in &effects.network_account_updates {
let Some(effect) = NetworkAccountEffect::from_protocol(details) else {
continue;
};
let last_tx_id = last_tx.get(account_id).copied().unwrap_or_else(|| {
assert!(
is_genesis,
"a committed account update must originate from a transaction in the block",
);
TransactionId::from_raw(Word::empty())
});
match effect {
NetworkAccountEffect::Created(account) => {
upsert_account(conn, *account_id, &account, last_tx_id)?;
},
NetworkAccountEffect::Updated(delta) => {
let Some(mut current) = get_account(conn, *account_id)? else {
continue;
};
current
.apply_delta(&delta)
.expect("network account delta should apply since the block was committed");
upsert_account(conn, *account_id, ¤t, last_tx_id)?;
},
}
affected_accounts.insert(*account_id);
}
for note in &effects.network_notes {
affected_accounts.insert(note.target_account_id());
}
insert_network_notes(conn, &effects.network_notes)?;
mark_notes_consumed(conn, &effects.nullifiers, effects.header.block_num())?;
update_chain_state_tip(conn, effects.header.block_num(), &effects.header, chain_mmr)?;
Ok(affected_accounts.into_iter().collect())
}