open-standards/smart-byte/smart-byte-rs/crates/smart-byte-tendermint/src/evidence.rs
Transaction Science 5ae7e4ef86 ingest wave E: 3 crates · op-bin + smart-byte-tendermint + eoc-safety
OpenPay (1 crate, 1801 LOC, 57 tests)
  op-bin              BIN/IIN database + range matching + card-network
                      classification. 8-digit normalized prefix Bin +
                      BinRange. Sorted-vec interval tree with O(log N) point
                      lookup + overlap rejection. CardNetwork classify()
                      with structural rules (Visa 4, MC 51-55/2221-2720,
                      Amex 34/37, Discover, JCB, Diners, UnionPay, RuPay,
                      Mir, Troy, Maestro, Elo). Static prefix tables +
                      build_default_tree(). ISO/IEC 7812-1 Annex B Luhn
                      (validate / is_valid / check_digit). Card-type +
                      issuer-country + Durbin regulated-debit. PCI-safe:
                      8-digit cap, no full-PAN APIs.

Smart Byte (1 crate, ~1500 LOC, 20 tests)
  smart-byte-tendermint  BFT consensus. Step enum + Round + propose/prevote/
                         precommit/commit FSM with voting-power tallies.
                         ValidatorSet with 2/3+1 quorum, 1/3+1 trust
                         threshold, round-robin proposer. Block / Header /
                         Commit / CommitSig with Blake3 hashing. Light client
                         (sequential + skipping). ABCI Application trait +
                         EchoApp. DuplicateVoteEvidence + LightClientAttackEvidence.
                         IBC ClientState + ConsensusState + light-client
                         update.

EOC (1 crate, 2084 LOC, 23 tests)
  eoc-safety          AI safety primitives. RegexSet over 16 prompt-injection
                      signatures. 13-family jailbreak detector (DAN/DUDE/
                      Grandma/STAN/AIM/dev-mode/etc.). Presidio-style PII
                      redactor with Luhn-validated CC. Toxicity / bias /
                      NSFW classifier traits + heuristic baselines (5-axis
                      bias, 4-category NSFW with hard-reject for minors).
                      Constitutional AI critique→revise loop. Composable
                      InputGuard / OutputGuard pipelines. JSON-Schema-subset
                      output validator. Token-bucket rate limiter +
                      abuse-window detection. Red-team replay harness.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-24 16:52:07 -04:00

112 lines
3.7 KiB
Rust

//! Tendermint evidence — proofs of validator misbehavior.
//!
//! Tendermint slashes two classes of misbehavior:
//!
//! * **DuplicateVote** — a validator signed two different votes at the
//! same `(height, round, kind)`. This is the prototypical
//! double-signing offense.
//! * **LightClientAttack** — a validator signed a commit on a
//! conflicting fork that a light client could be fooled into
//! trusting (lunatic / equivocation / amnesia variants).
use serde::{Deserialize, Serialize};
use crate::block::Commit;
use crate::error::{Error, Result};
use crate::validator::ValidatorId;
use crate::vote::Vote;
/// Proof of a validator double-signing two distinct votes.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DuplicateVoteEvidence {
/// First conflicting vote.
pub vote_a: Vote,
/// Second conflicting vote.
pub vote_b: Vote,
}
impl DuplicateVoteEvidence {
/// Validate that the two votes are in fact a double-sign.
///
/// They must:
/// * come from the same validator;
/// * share `(height, round, kind)`;
/// * vote for different `block_hash` values.
pub fn verify(&self) -> Result<()> {
if self.vote_a.validator != self.vote_b.validator {
return Err(Error::InvalidEvidence("validator mismatch"));
}
if self.vote_a.height != self.vote_b.height {
return Err(Error::InvalidEvidence("height mismatch"));
}
if self.vote_a.round != self.vote_b.round {
return Err(Error::InvalidEvidence("round mismatch"));
}
if self.vote_a.kind != self.vote_b.kind {
return Err(Error::InvalidEvidence("kind mismatch"));
}
if self.vote_a.block_hash == self.vote_b.block_hash {
return Err(Error::InvalidEvidence("votes agree"));
}
Ok(())
}
/// The misbehaving validator.
pub fn offender(&self) -> ValidatorId {
self.vote_a.validator
}
}
/// Proof that a conflicting block commit exists at the same height.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct LightClientAttackEvidence {
/// The honest, canonical commit.
pub canonical: Commit,
/// The conflicting commit that fooled (or could fool) the light client.
pub conflicting: Commit,
}
impl LightClientAttackEvidence {
/// Validate the evidence: same height, distinct block hashes.
pub fn verify(&self) -> Result<()> {
if self.canonical.height != self.conflicting.height {
return Err(Error::InvalidEvidence("height mismatch"));
}
if self.canonical.block_hash == self.conflicting.block_hash {
return Err(Error::InvalidEvidence("commits agree"));
}
Ok(())
}
/// Compute the intersection of validators that signed both commits —
/// these are the offending validators.
pub fn offenders(&self) -> Vec<ValidatorId> {
let a: std::collections::HashSet<_> =
self.canonical.signatures.iter().map(|s| s.validator).collect();
self.conflicting
.signatures
.iter()
.map(|s| s.validator)
.filter(|id| a.contains(id))
.collect()
}
}
/// Discriminated evidence union submitted to the chain.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Evidence {
/// A validator double-signed.
DuplicateVote(DuplicateVoteEvidence),
/// A light-client attack was detected.
LightClientAttack(LightClientAttackEvidence),
}
impl Evidence {
/// Validate the evidence.
pub fn verify(&self) -> Result<()> {
match self {
Self::DuplicateVote(e) => e.verify(),
Self::LightClientAttack(e) => e.verify(),
}
}
}