Files
serai/coordinator/tributary-sdk/src/tendermint/tx.rs
2025-09-03 16:44:26 -04:00

78 lines
1.9 KiB
Rust

use std::io;
use borsh::BorshDeserialize;
use blake2::{Digest, Blake2s256};
use dalek_ff_group::Ristretto;
use ciphersuite::*;
use crate::{
transaction::{Transaction, TransactionKind, TransactionError},
ReadWrite,
};
use tendermint::{
verify_tendermint_evidence,
ext::{Network, Commit},
};
pub use tendermint::{Evidence, decode_signed_message};
#[allow(clippy::large_enum_variant)]
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum TendermintTx {
SlashEvidence(Evidence),
}
impl ReadWrite for TendermintTx {
fn read<R: io::Read>(reader: &mut R) -> io::Result<Self> {
Evidence::deserialize_reader(reader)
.map(TendermintTx::SlashEvidence)
.map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "invalid evidence format"))
}
fn write<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
match self {
TendermintTx::SlashEvidence(ev) => writer.write_all(&borsh::to_vec(&ev).unwrap()),
}
}
}
impl Transaction for TendermintTx {
fn kind(&self) -> TransactionKind {
// There's an assert elsewhere in the codebase expecting this behavior
// If we do want to add Provided/Signed TendermintTxs, review the implications carefully
TransactionKind::Unsigned
}
fn hash(&self) -> [u8; 32] {
Blake2s256::digest(self.serialize()).into()
}
fn sig_hash(&self, _genesis: [u8; 32]) -> <Ristretto as WrappedGroup>::F {
match self {
TendermintTx::SlashEvidence(_) => panic!("sig_hash called on slash evidence transaction"),
}
}
fn verify(&self) -> Result<(), TransactionError> {
Ok(())
}
}
pub(crate) fn verify_tendermint_tx<N: Network>(
tx: &TendermintTx,
schema: &N::SignatureScheme,
commit: impl Fn(u64) -> Option<Commit<N::SignatureScheme>>,
) -> Result<(), TransactionError> {
tx.verify()?;
match tx {
TendermintTx::SlashEvidence(ev) => verify_tendermint_evidence::<N>(ev, schema, commit)
.map_err(|_| TransactionError::InvalidContent)?,
}
Ok(())
}