use alloc::collections::BTreeMap;
use alloc::string::ToString;
use alloc::vec::Vec;
use crate::account::AccountId;
use crate::batch::{BatchAccountUpdate, BatchId};
use crate::block::BlockNumber;
use crate::errors::ProvenBatchError;
use crate::note::Nullifier;
use crate::transaction::{InputNoteCommitment, InputNotes, OrderedTransactionHeaders, OutputNote};
use crate::utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable};
use crate::{MIN_PROOF_SECURITY_LEVEL, Word};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProvenBatch {
id: BatchId,
reference_block_commitment: Word,
reference_block_num: BlockNumber,
account_updates: BTreeMap<AccountId, BatchAccountUpdate>,
input_notes: InputNotes<InputNoteCommitment>,
output_notes: Vec<OutputNote>,
batch_expiration_block_num: BlockNumber,
transactions: OrderedTransactionHeaders,
}
impl ProvenBatch {
pub fn new(
id: BatchId,
reference_block_commitment: Word,
reference_block_num: BlockNumber,
account_updates: BTreeMap<AccountId, BatchAccountUpdate>,
input_notes: InputNotes<InputNoteCommitment>,
output_notes: Vec<OutputNote>,
batch_expiration_block_num: BlockNumber,
transactions: OrderedTransactionHeaders,
) -> Result<Self, ProvenBatchError> {
if batch_expiration_block_num <= reference_block_num {
return Err(ProvenBatchError::InvalidBatchExpirationBlockNum {
batch_expiration_block_num,
reference_block_num,
});
}
Ok(Self {
id,
reference_block_commitment,
reference_block_num,
account_updates,
input_notes,
output_notes,
batch_expiration_block_num,
transactions,
})
}
pub fn id(&self) -> BatchId {
self.id
}
pub fn reference_block_commitment(&self) -> Word {
self.reference_block_commitment
}
pub fn reference_block_num(&self) -> BlockNumber {
self.reference_block_num
}
pub fn batch_expiration_block_num(&self) -> BlockNumber {
self.batch_expiration_block_num
}
pub fn updated_accounts(&self) -> impl Iterator<Item = AccountId> + use<'_> {
self.account_updates.keys().copied()
}
pub fn proof_security_level(&self) -> u32 {
MIN_PROOF_SECURITY_LEVEL
}
pub fn account_updates(&self) -> &BTreeMap<AccountId, BatchAccountUpdate> {
&self.account_updates
}
pub fn input_notes(&self) -> &InputNotes<InputNoteCommitment> {
&self.input_notes
}
pub fn created_nullifiers(&self) -> impl Iterator<Item = Nullifier> + use<'_> {
self.input_notes.iter().map(InputNoteCommitment::nullifier)
}
pub fn output_notes(&self) -> &[OutputNote] {
&self.output_notes
}
pub fn transactions(&self) -> &OrderedTransactionHeaders {
&self.transactions
}
pub fn into_transactions(self) -> OrderedTransactionHeaders {
self.transactions
}
}
impl Serializable for ProvenBatch {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
self.id.write_into(target);
self.reference_block_commitment.write_into(target);
self.reference_block_num.write_into(target);
self.account_updates.write_into(target);
self.input_notes.write_into(target);
self.output_notes.write_into(target);
self.batch_expiration_block_num.write_into(target);
self.transactions.write_into(target);
}
}
impl Deserializable for ProvenBatch {
fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
let id = BatchId::read_from(source)?;
let reference_block_commitment = Word::read_from(source)?;
let reference_block_num = BlockNumber::read_from(source)?;
let account_updates = BTreeMap::read_from(source)?;
let input_notes = InputNotes::<InputNoteCommitment>::read_from(source)?;
let output_notes = Vec::<OutputNote>::read_from(source)?;
let batch_expiration_block_num = BlockNumber::read_from(source)?;
let transactions = OrderedTransactionHeaders::read_from(source)?;
Self::new(
id,
reference_block_commitment,
reference_block_num,
account_updates,
input_notes,
output_notes,
batch_expiration_block_num,
transactions,
)
.map_err(|e| DeserializationError::UnknownError(e.to_string()))
}
}