use std_shims::{vec::Vec, io};
use zeroize::Zeroize;
use crate::{
ringct::PrunedRctProofs,
transaction::{Input, Timelock, Pruned, Transaction},
send::SignableTransaction,
};
#[derive(Clone, PartialEq, Eq, Debug, Zeroize)]
pub struct Eventuality(SignableTransaction);
impl From<SignableTransaction> for Eventuality {
fn from(tx: SignableTransaction) -> Eventuality {
Eventuality(tx)
}
}
impl Eventuality {
pub fn extra(&self) -> Vec<u8> {
self.0.extra()
}
#[must_use]
pub fn matches(&self, tx: &Transaction<Pruned>) -> bool {
if self.0.extra() != tx.prefix().extra {
return false;
}
if tx.prefix().additional_timelock != Timelock::None {
return false;
}
if tx.prefix().inputs.len() != self.0.inputs.len() {
return false;
}
let Ok(key_images) = tx
.prefix()
.inputs
.iter()
.map(|input| match input {
Input::Gen(_) => Err(()),
Input::ToKey { key_image, .. } => Ok(*key_image),
})
.collect::<Result<Vec<_>, _>>()
else {
return false;
};
if self.0.outputs(&key_images) != tx.prefix().outputs {
return false;
}
let commitments_and_encrypted_amounts = self.0.commitments_and_encrypted_amounts(&key_images);
let Transaction::V2 { proofs: Some(PrunedRctProofs { ref base, .. }), .. } = tx else {
return false;
};
if base.commitments !=
commitments_and_encrypted_amounts
.iter()
.map(|(commitment, _)| commitment.commit().compress())
.collect::<Vec<_>>()
{
return false;
}
if base.encrypted_amounts !=
commitments_and_encrypted_amounts.into_iter().map(|(_, amount)| amount).collect::<Vec<_>>()
{
return false;
}
true
}
pub fn write<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
self.0.write(w)
}
pub fn serialize(&self) -> Vec<u8> {
self.0.serialize()
}
pub fn read<R: io::Read>(r: &mut R) -> io::Result<Eventuality> {
Ok(Eventuality(SignableTransaction::read(r)?))
}
}