use alloc::boxed::Box;
use crate::Word;
use crate::account::AccountId;
use crate::account::delta::AccountUpdateDetails;
use crate::errors::BatchAccountUpdateError;
use crate::transaction::ProvenTransaction;
use crate::utils::serde::{
ByteReader,
ByteWriter,
Deserializable,
DeserializationError,
Serializable,
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BatchAccountUpdate {
account_id: AccountId,
initial_state_commitment: Word,
final_state_commitment: Word,
details: AccountUpdateDetails,
}
impl BatchAccountUpdate {
pub fn from_transaction(transaction: &ProvenTransaction) -> Self {
Self {
account_id: transaction.account_id(),
initial_state_commitment: transaction.account_update().initial_state_commitment(),
final_state_commitment: transaction.account_update().final_state_commitment(),
details: transaction.account_update().details().clone(),
}
}
#[cfg(any(feature = "testing", test))]
pub fn new_unchecked(
account_id: AccountId,
initial_state_commitment: Word,
final_state_commitment: Word,
details: AccountUpdateDetails,
) -> Self {
Self {
account_id,
initial_state_commitment,
final_state_commitment,
details,
}
}
pub fn account_id(&self) -> AccountId {
self.account_id
}
pub fn initial_state_commitment(&self) -> Word {
self.initial_state_commitment
}
pub fn final_state_commitment(&self) -> Word {
self.final_state_commitment
}
pub fn details(&self) -> &AccountUpdateDetails {
&self.details
}
pub fn is_private(&self) -> bool {
self.details.is_private()
}
pub fn merge_proven_tx(
&mut self,
tx: &ProvenTransaction,
) -> Result<(), BatchAccountUpdateError> {
if self.account_id != tx.account_id() {
return Err(BatchAccountUpdateError::AccountUpdateIdMismatch {
transaction: tx.id(),
expected_account_id: self.account_id,
actual_account_id: tx.account_id(),
});
}
if self.final_state_commitment != tx.account_update().initial_state_commitment() {
return Err(BatchAccountUpdateError::AccountUpdateInitialStateMismatch(tx.id()));
}
self.details = self.details.clone().merge(tx.account_update().details().clone()).map_err(
|source_err| {
BatchAccountUpdateError::TransactionUpdateMergeError(tx.id(), Box::new(source_err))
},
)?;
self.final_state_commitment = tx.account_update().final_state_commitment();
Ok(())
}
pub fn into_update(self) -> AccountUpdateDetails {
self.details
}
}
impl Serializable for BatchAccountUpdate {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
self.account_id.write_into(target);
self.initial_state_commitment.write_into(target);
self.final_state_commitment.write_into(target);
self.details.write_into(target);
}
}
impl Deserializable for BatchAccountUpdate {
fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
Ok(Self {
account_id: AccountId::read_from(source)?,
initial_state_commitment: Word::read_from(source)?,
final_state_commitment: Word::read_from(source)?,
details: AccountUpdateDetails::read_from(source)?,
})
}
}