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]>
126 lines
4.1 KiB
Rust
126 lines
4.1 KiB
Rust
//! Tendermint light client.
|
|
//!
|
|
//! A light client maintains a "trusted" header at some height and
|
|
//! verifies later headers by one of two paths:
|
|
//!
|
|
//! * **Sequential** — verify that the next height's commit is signed
|
|
//! by 2/3+1 of the trusted validator set, and the new header's
|
|
//! `last_commit_hash` matches.
|
|
//! * **Skipping** — jump multiple heights forward if at least a
|
|
//! 1/3+1 *trust threshold* of the current trusted validator set
|
|
//! has also signed the target commit. This is the mechanism used
|
|
//! by IBC clients to bridge sparse update frequencies.
|
|
|
|
use crate::block::{Commit, Header};
|
|
use crate::error::{Error, Result};
|
|
use crate::validator::ValidatorSet;
|
|
|
|
/// Light-client trust state.
|
|
#[derive(Debug, Clone)]
|
|
pub struct TrustedState {
|
|
/// The most recently trusted header.
|
|
pub header: Header,
|
|
/// Validator set the trusted header was signed under.
|
|
pub validators: ValidatorSet,
|
|
}
|
|
|
|
impl TrustedState {
|
|
/// Construct a fresh trusted state (e.g. from a genesis header).
|
|
pub fn new(header: Header, validators: ValidatorSet) -> Self {
|
|
Self { header, validators }
|
|
}
|
|
}
|
|
|
|
/// Verify a sequential header update.
|
|
///
|
|
/// `commit` must commit `new_header.hash()` and the precommit signers
|
|
/// must hold 2/3+1 of `trusted.validators` voting power.
|
|
pub fn verify_sequential(
|
|
trusted: &TrustedState,
|
|
new_header: &Header,
|
|
commit: &Commit,
|
|
) -> Result<()> {
|
|
if new_header.height != trusted.header.height + 1 {
|
|
return Err(Error::LightClient("not sequential"));
|
|
}
|
|
if new_header.last_block_hash != trusted.header.hash() {
|
|
return Err(Error::LightClient("last_block_hash mismatch"));
|
|
}
|
|
if commit.height != new_header.height {
|
|
return Err(Error::LightClient("commit height mismatch"));
|
|
}
|
|
if commit.block_hash != new_header.hash() {
|
|
return Err(Error::LightClient("commit block_hash mismatch"));
|
|
}
|
|
let signers: Vec<_> = commit.signatures.iter().map(|s| &s.validator).collect();
|
|
if !trusted.validators.has_quorum(signers) {
|
|
return Err(Error::LightClient("no 2/3+1 quorum"));
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
/// Verify a skipping header update.
|
|
///
|
|
/// `commit` must commit `new_header.hash()`. The skip is permitted if
|
|
/// signers of `commit` hold at least 1/3+1 of `trusted.validators`
|
|
/// voting power *and* hold 2/3+1 of `new_validators` voting power.
|
|
pub fn verify_skipping(
|
|
trusted: &TrustedState,
|
|
new_header: &Header,
|
|
new_validators: &ValidatorSet,
|
|
commit: &Commit,
|
|
) -> Result<()> {
|
|
if new_header.height <= trusted.header.height {
|
|
return Err(Error::LightClient("not forward"));
|
|
}
|
|
if commit.height != new_header.height {
|
|
return Err(Error::LightClient("commit height mismatch"));
|
|
}
|
|
if commit.block_hash != new_header.hash() {
|
|
return Err(Error::LightClient("commit block_hash mismatch"));
|
|
}
|
|
let signers: Vec<_> = commit.signatures.iter().map(|s| &s.validator).collect();
|
|
|
|
// 1/3+1 of TRUSTED set
|
|
let trusted_power = trusted
|
|
.validators
|
|
.iter()
|
|
.filter(|v| signers.iter().any(|s| **s == v.id))
|
|
.map(|v| v.voting_power)
|
|
.sum::<u64>();
|
|
if trusted_power < trusted.validators.trust_threshold() {
|
|
return Err(Error::LightClient("trust threshold not met"));
|
|
}
|
|
|
|
// 2/3+1 of NEW set
|
|
if !new_validators.has_quorum(signers) {
|
|
return Err(Error::LightClient("new validator quorum not met"));
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
/// Update a `TrustedState` after a verified sequential step.
|
|
pub fn apply_sequential(
|
|
trusted: &mut TrustedState,
|
|
new_header: Header,
|
|
new_validators: ValidatorSet,
|
|
commit: &Commit,
|
|
) -> Result<()> {
|
|
verify_sequential(trusted, &new_header, commit)?;
|
|
trusted.header = new_header;
|
|
trusted.validators = new_validators;
|
|
Ok(())
|
|
}
|
|
|
|
/// Update a `TrustedState` after a verified skipping step.
|
|
pub fn apply_skipping(
|
|
trusted: &mut TrustedState,
|
|
new_header: Header,
|
|
new_validators: ValidatorSet,
|
|
commit: &Commit,
|
|
) -> Result<()> {
|
|
verify_skipping(trusted, &new_header, &new_validators, commit)?;
|
|
trusted.header = new_header;
|
|
trusted.validators = new_validators;
|
|
Ok(())
|
|
}
|