Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@
testnet/
.vscode/*
.nvim.lua

# cargo-fuzz build artifacts + generated corpus / crashes
fuzz/target/
fuzz/corpus/
fuzz/artifacts/
fuzz/coverage/
10 changes: 10 additions & 0 deletions docs/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,16 @@ Tests a new validator joining by syncing from genesis with no checkpoint.
- **Flow**: First withdraws one validator (modifying the peer set from genesis config), then generates new keys for a joining validator, sends a deposit, creates a `bootstrappers.toml` for peer discovery, and starts node4 with no checkpoint.
- **Verifies**: The new node syncs the entire chain from genesis, catches up to the current epoch, and joins the active validator set.

## Fuzz Testing

Coverage-guided fuzz testing lives in the `fuzz/` crate and runs under nightly Rust via [`cargo-fuzz`](https://github.com/rust-fuzz/cargo-fuzz). Three categories:

- **Parser targets** — every `Read` impl in `summit-types`. Arbitrary bytes must parse to `Ok` / `Err` without panicking, and successful decodes roundtrip to byte-identical output.
- **Non-codec targets** — `ssz_tree_key::parse_key`, `derive_child_public`, `SszProof::verify` with adversarial inputs.
- **Property-based targets** — `WithdrawalQueue` op-sequence invariants, `ExtPrivateKey` sign-verify roundtrip, SSZ incremental-update-vs-rebuild root equality, and generate→verify proof roundtrip across all proof kinds.

See [`fuzz/README.md`](../fuzz/README.md) for the full target list, running instructions, crash reproduction, and how to add new targets.

## Benchmarks

### Consensus State Benchmark
Expand Down
27 changes: 25 additions & 2 deletions finalizer/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,9 +341,11 @@ impl<V: Variant> Read for Value<V> {
type Cfg = ();

fn read_cfg(buf: &mut impl Buf, _cfg: &Self::Cfg) -> Result<Self, Error> {
let value_type = buf.get_u8();
let value_type = buf.try_get_u8().map_err(|_| Error::EndOfBuffer)?;
match value_type {
0x01 => Ok(Self::U64(buf.get_u64())),
0x01 => Ok(Self::U64(
buf.try_get_u64().map_err(|_| Error::EndOfBuffer)?,
)),
0x05 => Ok(Self::ConsensusState(Box::new(ConsensusState::read_cfg(
buf,
&(),
Expand Down Expand Up @@ -388,6 +390,7 @@ impl<V: Variant> Write for Value<V> {
#[cfg(test)]
mod tests {
use super::*;
use commonware_codec::ReadExt;
use commonware_consensus::simplex::types::{Finalization, Proposal};
use commonware_consensus::types::{Epoch, Round, View};
use commonware_cryptography::bls12381::primitives::{
Expand All @@ -405,6 +408,26 @@ mod tests {
use rand::rngs::StdRng;
use summit_types::Block;

#[test]
fn test_value_read_truncated_input_returns_err() {
// Empty buffer — must not panic.
let empty: &[u8] = &[];
assert!(matches!(
Value::<MinPk>::read(&mut empty.as_ref()),
Err(Error::EndOfBuffer)
));

// Tag 0x01 (U64) with 0..8 payload bytes — all truncated.
for n in 0..8 {
let mut buf = vec![0x01u8];
buf.extend(std::iter::repeat_n(0u8, n));
assert!(matches!(
Value::<MinPk>::read(&mut buf.as_ref()),
Err(Error::EndOfBuffer)
));
}
}

async fn create_test_db_with_context<
E: Clock + Storage + Metrics + commonware_runtime::BufferPooler,
V: Variant,
Expand Down
Loading
Loading