diff --git a/objects/src/accounts/delta/vault.rs b/objects/src/accounts/delta/vault.rs index 3f360243a..e8626187a 100644 --- a/objects/src/accounts/delta/vault.rs +++ b/objects/src/accounts/delta/vault.rs @@ -4,6 +4,8 @@ use alloc::{ vec::Vec, }; +use vm_core::{Felt, FieldElement}; + use super::{ AccountDeltaError, ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable, }; @@ -293,7 +295,12 @@ impl Serializable for FungibleAssetDelta { } fn get_size_hint(&self) -> usize { - self.0.len().get_size_hint() + self.0.len() * FungibleAsset::SERIALIZED_SIZE + // The serialized size of a fungible asset as it is serialized here. + // Usually, it is serialized including zeroes which is less efficient - see its Serializable + // implementation. + const SERIALIZED_FUNGIBLE_ASSET_COMPACT_SIZE: usize = + Felt::ELEMENT_BYTES + core::mem::size_of::(); + self.0.len().get_size_hint() + self.0.len() * SERIALIZED_FUNGIBLE_ASSET_COMPACT_SIZE } } diff --git a/objects/src/assets/fungible.rs b/objects/src/assets/fungible.rs index 1622ed1d0..b81425030 100644 --- a/objects/src/assets/fungible.rs +++ b/objects/src/assets/fungible.rs @@ -1,7 +1,8 @@ use alloc::string::ToString; use core::fmt; -use vm_core::FieldElement; +use vm_core::utils::{ByteReader, ByteWriter, Deserializable, Serializable}; +use vm_processor::DeserializationError; use super::{ is_not_a_non_fungible_asset, parse_word, AccountId, AccountType, Asset, AssetError, Felt, Word, @@ -28,8 +29,8 @@ impl FungibleAsset { /// The serialized size of a [`FungibleAsset`] in bytes. /// - /// Currently an account id (felt) plus an amount (u64). - pub const SERIALIZED_SIZE: usize = Felt::ELEMENT_BYTES + core::mem::size_of::(); + /// Currently an account id (felt) plus an amount (u64) padded to a word with zeroes. + pub const SERIALIZED_SIZE: usize = 32; // CONSTRUCTOR // -------------------------------------------------------------------------------------------- @@ -145,9 +146,9 @@ impl From for Word { } } -impl From for [u8; 32] { +impl From for [u8; FungibleAsset::SERIALIZED_SIZE] { fn from(asset: FungibleAsset) -> Self { - let mut result = [0_u8; 32]; + let mut result = [0_u8; FungibleAsset::SERIALIZED_SIZE]; let id_bytes: [u8; 8] = asset.faucet_id.into(); result[..8].copy_from_slice(&asset.amount.to_le_bytes()); result[24..].copy_from_slice(&id_bytes); @@ -155,6 +156,12 @@ impl From for [u8; 32] { } } +impl From<&FungibleAsset> for [u8; FungibleAsset::SERIALIZED_SIZE] { + fn from(value: &FungibleAsset) -> Self { + (*value).into() + } +} + impl From for Asset { fn from(asset: FungibleAsset) -> Self { Asset::Fungible(asset) @@ -175,10 +182,10 @@ impl TryFrom for FungibleAsset { } } -impl TryFrom<[u8; 32]> for FungibleAsset { +impl TryFrom<[u8; FungibleAsset::SERIALIZED_SIZE]> for FungibleAsset { type Error = AssetError; - fn try_from(value: [u8; 32]) -> Result { + fn try_from(value: [u8; FungibleAsset::SERIALIZED_SIZE]) -> Result { let word = parse_word(value)?; Self::try_from(word) } @@ -189,3 +196,22 @@ impl fmt::Display for FungibleAsset { write!(f, "{:?}", self) } } + +impl Serializable for FungibleAsset { + fn write_into(&self, target: &mut W) { + let data: [u8; FungibleAsset::SERIALIZED_SIZE] = self.into(); + target.write_bytes(&data); + } + + fn get_size_hint(&self) -> usize { + FungibleAsset::SERIALIZED_SIZE + } +} + +impl Deserializable for FungibleAsset { + fn read_from(source: &mut R) -> Result { + let value: Word = source.read()?; + + Self::try_from(value).map_err(|err| DeserializationError::InvalidValue(err.to_string())) + } +}