use prism::replay::{certify_from_trace, Trace};
use prism::seal::Grounded;
use crate::label::{KappaLabel, LabelDecodeError};
pub const ADDRESS_TRACE_EVENTS: usize = 256;
#[derive(Debug)]
pub struct AddressOutcome<const N: usize, const FP: usize = 32> {
pub witness: AddressWitness<N, FP>,
pub address: KappaLabel<N>,
}
impl<const N: usize, const FP: usize> AddressOutcome<N, FP> {
pub fn from_grounded<S, const NIN: usize>(
grounded: &Grounded<'_, S, NIN, FP>,
) -> Result<Self, LabelDecodeError>
where
S: prism::std_types::GroundedShape,
{
let address = KappaLabel::<N>::from_bytes(grounded.output_bytes())?;
let trace: Trace<ADDRESS_TRACE_EVENTS, FP> = grounded.derivation().replay();
let mut fingerprint = [0u8; FP];
let fp = grounded.content_fingerprint();
let fp_bytes = fp.as_bytes();
let n = fp_bytes.len().min(FP);
fingerprint[..n].copy_from_slice(&fp_bytes[..n]);
Ok(Self {
witness: AddressWitness {
address,
trace,
fingerprint,
},
address,
})
}
}
pub struct AddressWitness<const N: usize, const FP: usize = 32> {
address: KappaLabel<N>,
trace: Trace<ADDRESS_TRACE_EVENTS, FP>,
fingerprint: [u8; FP],
}
impl<const N: usize, const FP: usize> AddressWitness<N, FP> {
#[must_use]
pub fn kappa_label(&self) -> KappaLabel<N> {
self.address
}
#[must_use]
pub fn content_fingerprint(&self) -> &[u8; FP] {
&self.fingerprint
}
pub fn verify(&self) -> Result<KappaLabel<N>, VerifyError> {
let certified = certify_from_trace(&self.trace).map_err(|_| VerifyError::ReplayFailed)?;
if certified.certificate().content_fingerprint().as_bytes()[..] != self.fingerprint[..] {
return Err(VerifyError::FingerprintMismatch);
}
Ok(self.address)
}
}
impl<const N: usize, const FP: usize> core::fmt::Debug for AddressWitness<N, FP> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("AddressWitness")
.field("address", &self.address)
.finish_non_exhaustive()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum VerifyError {
ReplayFailed,
FingerprintMismatch,
}