use crate::account_changes::AccountChanges;
use alloc::vec::Vec;
pub type BlockAccessList = Vec<AccountChanges>;
#[cfg(feature = "rlp")]
pub fn compute_block_access_list_hash(bal: &[AccountChanges]) -> alloy_primitives::B256 {
let mut buf = Vec::new();
alloy_rlp::encode_list(bal, &mut buf);
alloy_primitives::keccak256(&buf)
}
pub fn total_bal_items(bal: &[AccountChanges]) -> u64 {
let mut bal_items: u64 = 0;
for account in bal {
bal_items += 1;
let mut unique_slots = alloy_primitives::map::HashSet::new();
for change in account.storage_changes() {
unique_slots.insert(change.slot);
}
for slot in account.storage_reads() {
unique_slots.insert(*slot);
}
bal_items += unique_slots.len() as u64;
}
bal_items
}
pub mod bal {
use crate::account_changes::AccountChanges;
use alloc::vec::{IntoIter, Vec};
use core::{
ops::{Deref, Index},
slice::Iter,
};
#[derive(Clone, Debug, Default, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "rlp", derive(alloy_rlp::RlpEncodable, alloy_rlp::RlpDecodable))]
pub struct Bal(Vec<AccountChanges>);
impl From<Bal> for Vec<AccountChanges> {
fn from(this: Bal) -> Self {
this.0
}
}
impl From<Vec<AccountChanges>> for Bal {
fn from(list: Vec<AccountChanges>) -> Self {
Self(list)
}
}
impl Deref for Bal {
type Target = [AccountChanges];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl IntoIterator for Bal {
type Item = AccountChanges;
type IntoIter = IntoIter<AccountChanges>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<'a> IntoIterator for &'a Bal {
type Item = &'a AccountChanges;
type IntoIter = Iter<'a, AccountChanges>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl FromIterator<AccountChanges> for Bal {
fn from_iter<I: IntoIterator<Item = AccountChanges>>(iter: I) -> Self {
Self(iter.into_iter().collect())
}
}
impl<I> Index<I> for Bal
where
I: core::slice::SliceIndex<[AccountChanges]>,
{
type Output = I::Output;
#[inline]
fn index(&self, index: I) -> &Self::Output {
&self.0[index]
}
}
impl Bal {
pub const fn new(account_changes: Vec<AccountChanges>) -> Self {
Self(account_changes)
}
pub fn push(&mut self, account_changes: AccountChanges) {
self.0.push(account_changes)
}
#[inline]
pub const fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[inline]
pub const fn len(&self) -> usize {
self.0.len()
}
#[inline]
pub fn iter(&self) -> Iter<'_, AccountChanges> {
self.0.iter()
}
#[inline]
pub const fn as_slice(&self) -> &[AccountChanges] {
self.0.as_slice()
}
pub fn into_inner(self) -> Vec<AccountChanges> {
self.0
}
#[inline]
pub const fn account_count(&self) -> usize {
self.0.len()
}
pub fn total_storage_changes(&self) -> usize {
self.0.iter().map(|a| a.storage_changes.len()).sum()
}
pub fn total_storage_reads(&self) -> usize {
self.0.iter().map(|a| a.storage_reads.len()).sum()
}
pub fn total_slots(&self) -> usize {
self.0.iter().map(|a| a.storage_changes.len() + a.storage_reads.len()).sum()
}
pub fn total_balance_changes(&self) -> usize {
self.0.iter().map(|a| a.balance_changes.len()).sum()
}
pub fn total_nonce_changes(&self) -> usize {
self.0.iter().map(|a| a.nonce_changes.len()).sum()
}
pub fn total_code_changes(&self) -> usize {
self.0.iter().map(|a| a.code_changes.len()).sum()
}
pub fn change_counts(&self) -> BalChangeCounts {
let mut counts = BalChangeCounts::default();
for account in &self.0 {
counts.accounts += 1;
counts.storage += account.storage_changes.len();
counts.balance += account.balance_changes.len();
counts.nonce += account.nonce_changes.len();
counts.code += account.code_changes.len();
}
counts
}
pub fn total_bal_items(&self) -> u64 {
super::total_bal_items(&self.0)
}
#[cfg(feature = "rlp")]
pub fn compute_hash(&self) -> alloy_primitives::B256 {
super::compute_block_access_list_hash(&self.0)
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct BalChangeCounts {
pub accounts: usize,
pub storage: usize,
pub balance: usize,
pub nonce: usize,
pub code: usize,
}
}