open-standards/smart-byte/smart-byte-rs/crates/smart-byte-tendermint/tests/consensus_3of4.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

144 lines
4.2 KiB
Rust

use smart_byte_tendermint::consensus::{ConsensusState, Step};
use smart_byte_tendermint::proposal::Proposal;
use smart_byte_tendermint::validator::{Validator, ValidatorId, ValidatorSet};
use smart_byte_tendermint::vote::{Signature, Vote, VoteType};
fn vid(b: u8) -> ValidatorId {
ValidatorId::from_bytes([b; 32])
}
fn empty_sig() -> Signature {
Signature::from_bytes([0u8; 64])
}
fn vote(
kind: VoteType,
height: u64,
round: u32,
block: Option<[u8; 32]>,
v: ValidatorId,
) -> Vote {
Vote {
kind,
height,
round,
block_hash: block,
validator: v,
signature: empty_sig(),
}
}
/// 4-validator network with equal voting power. 3 of 4 sign the
/// commit, satisfying the 2/3+1 BFT quorum (which is exactly 3 for
/// total power = 4).
#[test]
fn three_of_four_validators_commit_a_block() {
let validators: Vec<_> = (0..4).map(|i| Validator::new(vid(i), 1)).collect();
let vs = ValidatorSet::new(validators).unwrap();
assert_eq!(vs.quorum(), 3);
let mut state = ConsensusState::new("smart-byte-test", 1, vs.clone());
let proposer = state.validators().proposer(1, 0).unwrap().id;
let block: [u8; 32] = [0xAA; 32];
let proposal = Proposal {
height: 1,
round: 0,
block_hash: block,
pol_round: None,
proposer,
signature: empty_sig(),
};
state.apply_proposal(proposal).unwrap();
assert_eq!(state.step(), Step::Prevote);
// 3 prevotes for the block from 3 distinct validators
for i in 0..3u8 {
let _ = state
.apply_vote(vote(VoteType::Prevote, 1, 0, Some(block), vid(i)))
.unwrap();
}
assert_eq!(state.step(), Step::Precommit);
assert_eq!(state.prevote_power(Some(block)), 3);
// 3 precommits → commit
let mut committed = false;
for i in 0..3u8 {
committed |= state
.apply_vote(vote(VoteType::Precommit, 1, 0, Some(block), vid(i)))
.unwrap();
}
assert!(committed);
assert_eq!(state.step(), Step::Commit);
assert_eq!(state.committed(), Some(block));
assert!(state.is_committed());
}
#[test]
fn two_of_four_validators_do_not_commit() {
let vs =
ValidatorSet::new((0..4).map(|i| Validator::new(vid(i as u8), 1))).unwrap();
let mut state = ConsensusState::new("smart-byte-test", 5, vs.clone());
let proposer = state.validators().proposer(5, 0).unwrap().id;
let block: [u8; 32] = [0xCC; 32];
state
.apply_proposal(Proposal {
height: 5,
round: 0,
block_hash: block,
pol_round: None,
proposer,
signature: empty_sig(),
})
.unwrap();
// Only 2 prevotes — below quorum of 3
for i in 0..2u8 {
let _ = state
.apply_vote(vote(VoteType::Prevote, 5, 0, Some(block), vid(i)))
.unwrap();
}
assert_eq!(state.step(), Step::Prevote);
assert!(!state.is_committed());
}
#[test]
fn duplicate_vote_from_same_validator_rejected() {
let vs =
ValidatorSet::new((0..4).map(|i| Validator::new(vid(i as u8), 1))).unwrap();
let mut state = ConsensusState::new("smart-byte-test", 1, vs);
let proposer = state.validators().proposer(1, 0).unwrap().id;
let block: [u8; 32] = [0xDD; 32];
state
.apply_proposal(Proposal {
height: 1,
round: 0,
block_hash: block,
pol_round: None,
proposer,
signature: empty_sig(),
})
.unwrap();
state
.apply_vote(vote(VoteType::Prevote, 1, 0, Some(block), vid(0)))
.unwrap();
let err = state
.apply_vote(vote(VoteType::Prevote, 1, 0, Some(block), vid(0)))
.unwrap_err();
let s = format!("{err}");
assert!(s.contains("duplicate"), "expected duplicate error, got {s}");
}
#[test]
fn next_round_clears_tallies_preserves_lock() {
let vs =
ValidatorSet::new((0..4).map(|i| Validator::new(vid(i as u8), 1))).unwrap();
let mut state = ConsensusState::new("smart-byte-test", 9, vs);
assert_eq!(state.round(), 0);
state.next_round();
assert_eq!(state.round(), 1);
assert_eq!(state.step(), Step::Propose);
}