Skip to content
Open
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
4 changes: 4 additions & 0 deletions .github/actions/setup-rbmt/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ runs:
- name: Install Rust Toolchains
shell: bash
run: cargo rbmt toolchains

- name: Intall cargo-rbmt Tools
shell: bash
run: cargo rbmt tools
14 changes: 9 additions & 5 deletions .github/workflows/audit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,16 @@ jobs:

steps:
- name: Checkout Repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
persist-credentials: false

- name: Setup Rust Cache
uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1

- name: Install uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
- name: Setup cargo-rbmt
uses: ./.github/actions/setup-rbmt

- name: Run Zizmor
run: uvx zizmor .
shell: bash
run: zizmor .
21 changes: 0 additions & 21 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,24 +70,3 @@ jobs:

- name: Run Tests
run: cargo rbmt test --toolchain ${{ matrix.toolchain }} --lockfile ${{ matrix.lockfile }}

test-no-std:
name: Test - no-std, MSRV toolchain, Minimal Lockfile
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Setup Build Cache
uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1

- name: Setup cargo-rbmt
uses: ./.github/actions/setup-rbmt

- name: Add no_std Target
run: rustup target add thumbv7m-none-eabi --toolchain 1.74.0

- name: Run no_std Tests
run: cargo rbmt test --toolchain msrv --lockfile minimal
195 changes: 159 additions & 36 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ authors = ["Calvin Kim <calvin@kcalvinalvin.info>", "Davidson Souza <contact@dls
repository = "https://github.com/mit-dci/rustreexo"
license = "MIT OR Apache-2.0"
readme = "README.md"
edition = "2018"
edition = "2021"
rust-version = "1.74.0" # MSRV
autobenches = false

Expand All @@ -17,6 +17,18 @@ default = ["std"]
std = ["bitcoin_hashes/std", "hex-conservative/std", "hashbrown/default-hasher"]
with-serde = ["serde"]

[[bench]]
name = "accumulator"
harness = false

[[bench]]
name = "proof"
harness = false

[[bench]]
name = "stump"
harness = false

[dependencies]
bitcoin_hashes = { version = "0.20", default-features = false }
hex-conservative = { version = "1", default-features = false }
Expand Down Expand Up @@ -45,41 +57,17 @@ bumpalo = { version = "3.11.1" } # blame: criterion v0.5.1 (RUSTSEC-2022-0078)
rayon = { version = "1.5.3" } # blame: criterion v0.5.1 (RUSTSEC-2022-0021, RUSTSEC-2023-0045)
errno-dragonfly = { version = "0.1.2" } # blame: criterion v0.5.1 (RUSTSEC-2025-0121)

[[bench]]
name = "accumulator"
harness = false

[[bench]]
name = "proof"
harness = false

[[bench]]
name = "stump"
harness = false

[lints.clippy]
use_self = "warn"

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(bench)'] }
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[package.metadata.rbmt.toolchains]
stable = "1.96.0"
nightly = "nightly-2026-06-23"
[package.metadata.rbmt]
toolchains = { stable = "1.96.0", nightly = "nightly-2026-06-23" }
tools = { cargo-audit = "=0.22.2", zizmor = "=1.26.1" }
lint = { allowed_duplicates = [] }

[package.metadata.rbmt.test]
# Test all possible auto-discovered feature combinations.
sample_strategy = "all"

# Features to exclude from auto-discovery.
# Use for internal or alias features that should not be tested in isolation.
exclude_features = ["default"]

# Examples to run with different feature configurations.
#
# Supported formats:
# * "name" - runs with no-default-features.
# * "name:feature1 feature2" - runs with specific features.
examples = [
"stump_modify",
"stump_modify:std",
Expand All @@ -95,7 +83,142 @@ examples = [
"custom_hash:with-serde std",
]

# Allow packages of different versions in the dependency tree.
[package.metadata.rbmt.lint]
allowed_duplicates = [
]
[lints.rust]
# TODO(@luisschwab): redocument the whole crate
#missing_docs = "warn"
unreachable_pub = "warn"
unused_qualifications = "warn"

# Copied over from rust-bitcoin
[lints.clippy]
# Exclude lints we don't think are valuable.
needless_question_mark = "allow" # https://github.com/rust-bitcoin/rust-bitcoin/pull/2134
manual_range_contains = "allow" # More readable than clippy's format.
# Exhaustive list of pedantic clippy lints
assigning_clones = "warn"
bool_to_int_with_if = "warn"
borrow_as_ptr = "warn"
case_sensitive_file_extension_comparisons = "warn"
cast_lossless = "warn"
cast_possible_truncation = "allow" # All casts should include a code comment (except test code).
cast_possible_wrap = "allow" # Same as above re code comment.
cast_precision_loss = "warn"
cast_ptr_alignment = "warn"
cast_sign_loss = "allow" # All casts should include a code comment (except in test code).
checked_conversions = "warn"
cloned_instead_of_copied = "warn"
copy_iterator = "warn"
default_trait_access = "warn"
doc_link_with_quotes = "warn"
doc_markdown = "warn"
empty_enums = "warn"
enum_glob_use = "warn"
expl_impl_clone_on_copy = "warn"
explicit_deref_methods = "warn"
explicit_into_iter_loop = "warn"
explicit_iter_loop = "warn"
filter_map_next = "warn"
flat_map_option = "warn"
float_cmp = "allow" # Bitcoin floats are typically limited to 8 decimal places and we want them exact.
fn_params_excessive_bools = "warn"
if_not_else = "warn"
ignored_unit_patterns = "warn"
implicit_clone = "warn"
implicit_hasher = "warn"
inconsistent_struct_constructor = "warn"
index_refutable_slice = "warn"
inefficient_to_string = "warn"
inline_always = "warn"
into_iter_without_iter = "warn"
invalid_upcast_comparisons = "warn"
items_after_statements = "warn"
iter_filter_is_ok = "warn"
iter_filter_is_some = "warn"
iter_not_returning_iterator = "warn"
iter_without_into_iter = "warn"
large_digit_groups = "warn"
large_futures = "warn"
large_stack_arrays = "warn"
large_types_passed_by_value = "warn"
linkedlist = "warn"
macro_use_imports = "warn"
manual_assert = "warn"
manual_instant_elapsed = "warn"
manual_is_power_of_two = "warn"
manual_is_variant_and = "warn"
manual_let_else = "warn"
manual_ok_or = "warn"
manual_string_new = "warn"
many_single_char_names = "warn"
map_unwrap_or = "warn"
match_bool = "allow" # Adds extra indentation and LOC.
match_same_arms = "allow" # Collapses things that are conceptually unrelated to each other.
match_wild_err_arm = "warn"
match_wildcard_for_single_variants = "warn"
maybe_infinite_iter = "warn"
mismatching_type_param_order = "warn"
# TODO(@luisschwab): redocument the whole crate
#missing_errors_doc = "warn"
missing_fields_in_debug = "warn"
# TODO(@luisschwab): redocument the whole crate
#missing_panics_doc = "warn"
missing_safety_doc = "warn"
# TODO(@luisschwab): redocument the whole crate
#missing_docs_in_private_items = "warn"
must_use_candidate = "allow" # Useful for audit but many false positives.
mut_mut = "warn"
naive_bytecount = "warn"
needless_bitwise_bool = "warn"
needless_continue = "warn"
needless_for_each = "warn"
needless_pass_by_value = "warn"
needless_raw_string_hashes = "warn"
no_effect_underscore_binding = "warn"
no_mangle_with_rust_abi = "warn"
option_as_ref_cloned = "warn"
option_option = "warn"
ptr_as_ptr = "warn"
ptr_cast_constness = "warn"
pub_underscore_fields = "warn"
range_minus_one = "warn"
range_plus_one = "warn"
redundant_clone = "warn"
redundant_closure_for_method_calls = "warn"
redundant_else = "warn"
ref_as_ptr = "warn"
ref_binding_to_reference = "warn"
ref_option = "warn"
ref_option_ref = "warn"
return_self_not_must_use = "warn"
same_functions_in_if_condition = "warn"
semicolon_if_nothing_returned = "warn"
should_panic_without_expect = "warn"
similar_names = "allow" # Too many (subjectively) false positives.
single_char_pattern = "warn"
single_match_else = "warn"
stable_sort_primitive = "warn"
str_split_at_newline = "warn"
string_add_assign = "warn"
struct_excessive_bools = "warn"
struct_field_names = "allow" # dumb
too_many_lines = "warn"
transmute_ptr_to_ptr = "warn"
trivially_copy_pass_by_ref = "warn"
unchecked_time_subtraction = "warn"
unicode_not_nfc = "warn"
uninlined_format_args = "allow" # This is a subjective style choice.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually like this one

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which one?

unnecessary_box_returns = "warn"
unnecessary_join = "warn"
unnecessary_literal_bound = "warn"
unnecessary_wraps = "warn"
unnested_or_patterns = "warn"
unreadable_literal = "warn"
unsafe_derive_deserialize = "warn"
unused_async = "warn"
unused_self = "warn"
use_self = "warn"
used_underscore_binding = "warn"
used_underscore_items = "warn"
verbose_bit_mask = "warn"
wildcard_imports = "warn"
zero_sized_map_values = "warn"
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,10 @@ Available recipes:
fmt # Format code [alias: f]
lock # Regenerate Cargo-recent.lock and Cargo-minimal.lock [alias: l]
pre-push # Run pre-push suite: lock, fmt, check, test, and test-no-std [alias: p]
shellcheck # Run ShellCheck
test # Run tests across all toolchains and lockfiles [alias: t]
test-no-std # Run no_std build check with the MSRV toolchain (1.74.0) [alias: tns]
tools # Install cargo-rbmt tools
zizmor # Run Zizmor Static Analysis
```

## Minimum Supported Rust Version (MSRV)
Expand Down
11 changes: 7 additions & 4 deletions benches/accumulator.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
//! # Accumulator Benchmarks
//!
//! Benchmarks for the [`Pollard`] and [`MemForest`] Utreexo accumulators.

use std::hint::black_box;

use criterion::criterion_group;
Expand Down Expand Up @@ -31,7 +35,7 @@ fn memforest_proof_generation(c: &mut Criterion) {
let mut forest = MemForest::new();
forest.modify(&hashes, &[]).unwrap();

for target_count in [1, 10].iter() {
for target_count in &[1, 10] {
let targets = &hashes[..*target_count];

group.throughput(Throughput::Elements(*target_count as u64));
Expand All @@ -57,7 +61,7 @@ fn memforest_verification(c: &mut Criterion) {
let mut forest = MemForest::new();
forest.modify(&hashes, &[]).unwrap();

for target_count in [1, 10].iter() {
for target_count in &[1, 10] {
let targets = &hashes[..*target_count];
let proof = forest.prove(targets).unwrap();

Expand All @@ -82,11 +86,10 @@ fn pollard_operations(c: &mut Criterion) {
let base_size = 100;
let hashes = generate_test_hashes(base_size, 42);
let roots = vec![hashes[0]]; // Simplified root structure
let pollard = Pollard::from_roots(roots, base_size as u64);
let pollard = Pollard::from_roots(&roots, base_size as u64);

{
let batch_size = &10;
let _del_hashes = &hashes[..*batch_size / 2];

group.throughput(Throughput::Elements(*batch_size as u64));
group.bench_with_input(
Expand Down
9 changes: 7 additions & 2 deletions benches/proof.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
//! # Proof Benchmarks
//!
//! Benchmarks for the [`Proof`] data structure.

use std::hint::black_box;

use criterion::criterion_group;
Expand Down Expand Up @@ -27,7 +31,7 @@ fn generate_test_hashes(count: usize, seed: u64) -> Vec<BitcoinNodeHash> {
fn proof_creation(c: &mut Criterion) {
let mut group = c.benchmark_group("proof_creation");

for target_count in [1, 10].iter() {
for target_count in &[1, 10] {
let targets: Vec<u64> = (0..*target_count).collect();
let proof_hashes = generate_test_hashes((*target_count * 3) as usize, 42); // Approximate proof size

Expand All @@ -47,6 +51,7 @@ fn proof_creation(c: &mut Criterion) {
group.finish();
}

#[allow(clippy::cast_precision_loss)]
#[allow(clippy::unnecessary_cast)]
fn proof_verification(c: &mut Criterion) {
let mut group = c.benchmark_group("proof_verification");
Expand All @@ -57,7 +62,7 @@ fn proof_verification(c: &mut Criterion) {
let stump = Stump::new();
let (stump, _) = stump.modify(&hashes, &[], &Proof::default()).unwrap();

for target_count in [1, 10].iter() {
for target_count in &[1, 10] {
let del_hashes = hashes[..*target_count].to_vec();
let targets: Vec<u64> = (0..*target_count as u64).collect();

Expand Down
8 changes: 6 additions & 2 deletions benches/stump.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
//! # Stump Benchmarks
//!
//! Benchmarks for the [`Stump`] accumulator.

use std::hint::black_box;

use criterion::criterion_group;
Expand Down Expand Up @@ -26,7 +30,7 @@ fn generate_test_hashes(count: usize, seed: u64) -> Vec<BitcoinNodeHash> {
fn stump_modify_add_only(c: &mut Criterion) {
let mut group = c.benchmark_group("stump_modify_add_only");

for size in [10, 100].iter() {
for size in &[10, 100] {
group.throughput(Throughput::Elements(*size as u64));
group.bench_with_input(BenchmarkId::new("add_elements", size), size, |b, &size| {
let hashes = generate_test_hashes(size, 42);
Expand All @@ -52,7 +56,7 @@ fn stump_verify(c: &mut Criterion) {
let stump = Stump::new();
let (stump, _) = stump.modify(&hashes, &[], &Proof::default()).unwrap();

for proof_size in [1, 10, 100].iter() {
for proof_size in &[1, 10, 100] {
let del_hashes = hashes[..*proof_size].to_vec();
let proof = Proof::new(
(0..*proof_size as u64).collect(),
Expand Down
Loading
Loading