use alloc::boxed::Box;
use alloc::vec::Vec;
use super::{AccountId, AccountIdKey, AccountIdPrefix, AccountTree, AccountTreeError};
use crate::Word;
use crate::crypto::merkle::MerkleError;
#[cfg(feature = "std")]
use crate::crypto::merkle::smt::{LargeSmt, LargeSmtError, SmtStorage};
use crate::crypto::merkle::smt::{LeafIndex, MutationSet, SMT_DEPTH, Smt, SmtLeaf, SmtProof};
pub trait AccountTreeBackend: Sized {
type Error: core::error::Error + Send + 'static;
fn num_leaves(&self) -> usize;
fn leaves<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = (LeafIndex<SMT_DEPTH>, SmtLeaf)>>;
fn open(&self, key: &Word) -> SmtProof;
fn apply_mutations(
&mut self,
set: MutationSet<SMT_DEPTH, Word, Word>,
) -> Result<(), Self::Error>;
fn apply_mutations_with_reversion(
&mut self,
set: MutationSet<SMT_DEPTH, Word, Word>,
) -> Result<MutationSet<SMT_DEPTH, Word, Word>, Self::Error>;
fn compute_mutations(
&self,
updates: Vec<(Word, Word)>,
) -> Result<MutationSet<SMT_DEPTH, Word, Word>, Self::Error>;
fn insert(&mut self, key: Word, value: Word) -> Result<Word, Self::Error>;
fn get_value(&self, key: &Word) -> Word;
fn get_leaf(&self, key: &Word) -> SmtLeaf;
fn root(&self) -> Word;
}
impl AccountTreeBackend for Smt {
type Error = MerkleError;
fn num_leaves(&self) -> usize {
Smt::num_leaves(self)
}
fn leaves<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = (LeafIndex<SMT_DEPTH>, SmtLeaf)>> {
Box::new(Smt::leaves(self).map(|(idx, leaf)| (idx, leaf.clone())))
}
fn open(&self, key: &Word) -> SmtProof {
Smt::open(self, key)
}
fn apply_mutations(
&mut self,
set: MutationSet<SMT_DEPTH, Word, Word>,
) -> Result<(), Self::Error> {
Smt::apply_mutations(self, set)
}
fn apply_mutations_with_reversion(
&mut self,
set: MutationSet<SMT_DEPTH, Word, Word>,
) -> Result<MutationSet<SMT_DEPTH, Word, Word>, Self::Error> {
Smt::apply_mutations_with_reversion(self, set)
}
fn compute_mutations(
&self,
updates: Vec<(Word, Word)>,
) -> Result<MutationSet<SMT_DEPTH, Word, Word>, Self::Error> {
Smt::compute_mutations(self, updates)
}
fn insert(&mut self, key: Word, value: Word) -> Result<Word, Self::Error> {
Smt::insert(self, key, value)
}
fn get_value(&self, key: &Word) -> Word {
Smt::get_value(self, key)
}
fn get_leaf(&self, key: &Word) -> SmtLeaf {
Smt::get_leaf(self, key)
}
fn root(&self) -> Word {
Smt::root(self)
}
}
#[cfg(feature = "std")]
impl<Backend> AccountTreeBackend for LargeSmt<Backend>
where
Backend: SmtStorage,
{
type Error = MerkleError;
fn num_leaves(&self) -> usize {
LargeSmt::num_leaves(self)
}
fn leaves<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = (LeafIndex<SMT_DEPTH>, SmtLeaf)>> {
Box::new(LargeSmt::leaves(self).expect("Only IO can error out here"))
}
fn open(&self, key: &Word) -> SmtProof {
LargeSmt::open(self, key)
}
fn apply_mutations(
&mut self,
set: MutationSet<SMT_DEPTH, Word, Word>,
) -> Result<(), Self::Error> {
LargeSmt::apply_mutations(self, set).map_err(large_smt_error_to_merkle_error)
}
fn apply_mutations_with_reversion(
&mut self,
set: MutationSet<SMT_DEPTH, Word, Word>,
) -> Result<MutationSet<SMT_DEPTH, Word, Word>, Self::Error> {
LargeSmt::apply_mutations_with_reversion(self, set).map_err(large_smt_error_to_merkle_error)
}
fn compute_mutations(
&self,
updates: Vec<(Word, Word)>,
) -> Result<MutationSet<SMT_DEPTH, Word, Word>, Self::Error> {
LargeSmt::compute_mutations(self, updates).map_err(large_smt_error_to_merkle_error)
}
fn insert(&mut self, key: Word, value: Word) -> Result<Word, Self::Error> {
LargeSmt::insert(self, key, value)
}
fn get_value(&self, key: &Word) -> Word {
LargeSmt::get_value(self, key)
}
fn get_leaf(&self, key: &Word) -> SmtLeaf {
LargeSmt::get_leaf(self, key)
}
fn root(&self) -> Word {
LargeSmt::root(self)
}
}
impl AccountTree<Smt> {
pub fn with_entries<I>(
entries: impl IntoIterator<Item = (AccountId, Word), IntoIter = I>,
) -> Result<Self, AccountTreeError>
where
I: ExactSizeIterator<Item = (AccountId, Word)>,
{
let smt = Smt::with_entries(
entries
.into_iter()
.map(|(id, commitment)| (AccountIdKey::from(id).as_word(), commitment)),
)
.map_err(|err| {
let MerkleError::DuplicateValuesForIndex(leaf_idx) = err else {
unreachable!("the only error returned by Smt::with_entries is of this type");
};
AccountTreeError::DuplicateStateCommitments {
prefix: AccountIdPrefix::new_unchecked(
crate::Felt::try_from(leaf_idx).expect("leaf index should be a valid felt"),
),
}
})?;
AccountTree::new(smt)
}
}
#[cfg(feature = "std")]
fn large_smt_error_to_merkle_error(err: LargeSmtError) -> MerkleError {
match err {
LargeSmtError::Storage(storage_err) => {
panic!("Storage error encountered: {:?}", storage_err)
},
LargeSmtError::StorageNotEmpty => {
panic!("StorageNotEmpty error encountered: {:?}", err)
},
LargeSmtError::Merkle(merkle_err) => merkle_err,
LargeSmtError::RootMismatch { expected, actual } => MerkleError::ConflictingRoots {
expected_root: expected,
actual_root: actual,
},
}
}