use alloc::vec::Vec;
use super::{Account, AccountId, Felt, PartialAccount, ZERO, hash_account};
use crate::Word;
use crate::utils::serde::{Deserializable, Serializable};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AccountHeader {
id: AccountId,
nonce: Felt,
vault_root: Word,
storage_commitment: Word,
code_commitment: Word,
}
impl AccountHeader {
pub fn new(
id: AccountId,
nonce: Felt,
vault_root: Word,
storage_commitment: Word,
code_commitment: Word,
) -> Self {
Self {
id,
nonce,
vault_root,
storage_commitment,
code_commitment,
}
}
pub fn commitment(&self) -> Word {
hash_account(
self.id,
self.nonce,
self.vault_root,
self.storage_commitment,
self.code_commitment,
)
}
pub fn id(&self) -> AccountId {
self.id
}
pub fn nonce(&self) -> Felt {
self.nonce
}
pub fn vault_root(&self) -> Word {
self.vault_root
}
pub fn storage_commitment(&self) -> Word {
self.storage_commitment
}
pub fn code_commitment(&self) -> Word {
self.code_commitment
}
pub fn as_elements(&self) -> Vec<Felt> {
[
&[self.id.suffix(), self.id.prefix().as_felt(), ZERO, self.nonce],
self.vault_root.as_elements(),
self.storage_commitment.as_elements(),
self.code_commitment.as_elements(),
]
.concat()
}
}
impl From<PartialAccount> for AccountHeader {
fn from(account: PartialAccount) -> Self {
(&account).into()
}
}
impl From<&PartialAccount> for AccountHeader {
fn from(account: &PartialAccount) -> Self {
Self {
id: account.id(),
nonce: account.nonce(),
vault_root: account.vault().root(),
storage_commitment: account.storage().commitment(),
code_commitment: account.code().commitment(),
}
}
}
impl From<Account> for AccountHeader {
fn from(account: Account) -> Self {
(&account).into()
}
}
impl From<&Account> for AccountHeader {
fn from(account: &Account) -> Self {
Self {
id: account.id(),
nonce: account.nonce(),
vault_root: account.vault().root(),
storage_commitment: account.storage().commitment(),
code_commitment: account.code().commitment(),
}
}
}
impl Serializable for AccountHeader {
fn write_into<W: miden_core::utils::ByteWriter>(&self, target: &mut W) {
self.id.write_into(target);
self.nonce.write_into(target);
self.vault_root.write_into(target);
self.storage_commitment.write_into(target);
self.code_commitment.write_into(target);
}
}
impl Deserializable for AccountHeader {
fn read_from<R: miden_core::utils::ByteReader>(
source: &mut R,
) -> Result<Self, miden_processor::DeserializationError> {
let id = AccountId::read_from(source)?;
let nonce = Felt::read_from(source)?;
let vault_root = Word::read_from(source)?;
let storage_commitment = Word::read_from(source)?;
let code_commitment = Word::read_from(source)?;
Ok(AccountHeader {
id,
nonce,
vault_root,
storage_commitment,
code_commitment,
})
}
}
#[cfg(test)]
mod tests {
use miden_core::Felt;
use miden_core::utils::{Deserializable, Serializable};
use super::AccountHeader;
use crate::Word;
use crate::account::StorageSlot;
use crate::account::tests::build_account;
use crate::asset::FungibleAsset;
#[test]
fn test_serde_account_storage() {
let init_nonce = Felt::new(1);
let asset_0 = FungibleAsset::mock(99);
let word = Word::from([1, 2, 3, 4u32]);
let storage_slot = StorageSlot::Value(word);
let account = build_account(vec![asset_0], init_nonce, vec![storage_slot]);
let account_header: AccountHeader = account.into();
let header_bytes = account_header.to_bytes();
let deserialized_header = AccountHeader::read_from_bytes(&header_bytes).unwrap();
assert_eq!(deserialized_header, account_header);
}
}