Skip to content

fix(hasher): make the deterministic hasher endian-independent#142

Merged
vincent-k2026 merged 1 commit into
mainfrom
krabat/fix/hasher-le-determinism
Jul 11, 2026
Merged

fix(hasher): make the deterministic hasher endian-independent#142
vincent-k2026 merged 1 commit into
mainfrom
krabat/fix/hasher-le-determinism

Conversation

@vincent-k2026

Copy link
Copy Markdown
Collaborator

Summary

  • Fixes bug: bucket_id hash is non-deterministic on big-endian targets #127: the vendored AHash fallback read byte slices via zerocopy::transmute!, i.e. in native endianness, so bucket_id — a consensus-critical hash — would map the same key to different buckets on big-endian targets.
  • ReadFromSlice now uses explicit u{16,32,64,128}::from_le_bytes. Little-endian is the canonical interpretation: every current deployment target (x86_64 sequencer, riscv64 fault-proof/zkVM clients, wasm32) is little-endian, so this is bit-identical on all of them.
  • The rest of the pipeline was audited and is already endian-independent: fallback.rs is pure integer arithmetic, hash_with_nonce already uses to_le_bytes for the nonce, and write_usize widens by value (also safe on 32-bit wasm).
  • The Convert trait with its ~40 transmute! impls was dead vendored code beyond these four slice reads, and this was salt's only use of zerocopy, so both are removed (Cargo.lock updated accordingly).

Why this is consensus-safe to merge

The mutation-testing PR (#140) pinned the exact outputs of hash(), hash_with_nonce(), bucket_id(), and read_small() as unit tests. Those tests passing in CI proves the network format is byte-for-byte unchanged on little-endian; big-endian targets now compute the same canonical values instead of diverging.

🤖 Generated with Claude Code

The vendored AHash fallback reinterpreted byte slices in native
endianness (zerocopy::transmute), so the consensus-critical bucket_id
hash would assign the same key to different buckets on big-endian
targets. Read u16/u32/u64/u128 with explicit from_le_bytes instead:
bit-identical on every current (little-endian) target - the pinned
hash-value tests prove the network format is unchanged - and
deterministic everywhere else.

Beyond these four slice reads, the Convert trait and its ~40 transmute
impls were dead vendored code, and zerocopy was salt's only use of the
crate, so both are removed.

Closes #127.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Performance Benchmark Comparison

Compared 5 benchmark(s) against the latest main baseline.

Detailed Comparison
Benchmark Baseline Throughput (Kelem/s) New Throughput (Kelem/s) Change
update 10000 KVs/1 threads 75.23 70.14 -6.76%
update 10000 KVs/2 threads 139.09 129.81 -6.67%
update 10000 KVs/4 threads 252.19 238.13 -5.58%
update 10000 KVs/8 threads 437.08 402.89 -7.82%
update 10000 KVs/16 threads 586.88 543.50 -7.39%

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Mutation testing - PASS

Mutation score: 100.0% (36/36 viable mutants killed)

  • caught: 36
  • survived, real gaps: 0
  • timed out, inconclusive: 0
  • suppressed: 0
  • unviable: 0
  • timeout total: 0

No unsuppressed survivors or timeouts remain.

@vincent-k2026
vincent-k2026 requested review from Troublor and flyq July 8, 2026 14:27

@flyq flyq left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Stale doc line. salt/src/state/ahash/mod.rs:11 still reads "Convert utilities extracted from AHash for efficient byte operations" — the Convert trait is gone. Suggest something like "Little-endian byte-slice readers for the deterministic hasher." (Keeping the convert.rs filename itself is fine — it matches the upstream AHash file and aids diffing against it.)

@vincent-k2026
vincent-k2026 merged commit 19419f4 into main Jul 11, 2026
13 checks passed
@vincent-k2026
vincent-k2026 deleted the krabat/fix/hasher-le-determinism branch July 11, 2026 11:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: bucket_id hash is non-deterministic on big-endian targets

3 participants