## Contributing to eth_state_diff
Thank you for your interest in contributing to `eth_state_diff` (published on crates.io as `eth-state-diff`)!
This project is written in Rust, and contributions are welcome. This document covers the conventions and checks I use
when reviewing pull requests.
## Before submitting a pull request
After submitting a PR, GitHub Actions will run the test suite, cargo fmt --check, cargo clippy, and cargo doc. **All CI
checks must pass before a PR can be merged**. If a check fails, please resolve the issues or ask for help in the PR
comments.
To increase the likelihood that your PR passes those checks, please run the following locally:
```
cargo fmt
cargo clippy
cargo doc --no-deps
cargo test
```
Please make sure all of these complete successfully before submitting your PR. While the crate does not currently use
`#![deny(...)]` lints at the crate level, CI will fail on any compiler or Clippy warnings.
## Minimum Supported Rust Version (MSRV)
This crate targets a specific Minimum Supported Rust Version (MSRV), which is defined in the `Cargo.toml` via the
`rust-version` field. Contributions should not use features or standard library APIs stabilized in versions newer than
the current MSRV. If a change requires bumping the MSRV, please open an issue to discuss it first.
## Pull requests
To create a PR:
1. Fork `eth_state_diff`.
2. Create a branch containing your changes.
3. Make your changes and run the checks described above.
4. Push your branch to your fork.
5. Open a pull request against the main repository.
I typically prioritize reviews in the middle of the next work day, so you should generally expect a response within the
week.
## Error handling
`unwrap()` is not allowed in this codebase. Every `Option`/`Result` that could plausibly be `None`/`Err` at runtime —
such as malformed input, an out-of-range index on untrusted data, or a length mismatch — must be handled explicitly:
propagate the error, return `None`, or handle the failure case directly.
Direct indexing and dereferencing that can panic (`slice[i]`, `slice[a..b]`) on untrusted or external data is held to
the same standard and must go through a checked accessor (`.get()`, `.get_mut()`, `try_into()`, etc.). However, direct
indexing is permitted on internal data structures when the bounds are unconditionally verified immediately prior to the
access (e.g., an `assert!` or early return validating the index on the preceding line). If you enable the Clippy
`indexing_slicing` lint to enforce this mechanically, you must use `.get().expect()` to satisfy the linter instead of
direct indexing.
The one exception is `expect()`, used only where a failure would indicate a programmer error or a broken internal
invariant, never an expected runtime condition arising from untrusted or external input. Every `expect()` must carry a
message explaining *why* reaching that point would mean something is already broken. For example: an index derived from
a length you just checked two lines above, or a byte slice whose width was validated immediately before the conversion.
If you're not confident the invariant genuinely can't be violated by data the function didn't produce itself, don't use
`expect()` — handle the case instead.
## Unsafe code
Avoid `unsafe`. In most cases there's a safe alternative (a checked slice access, an iterator adapter, a different data
layout) that costs nothing at the optimization levels this crate is built with, and it should be preferred by default.
If you believe a specific case genuinely requires `unsafe` for correctness or performance that a safe equivalent can't
achieve, please open an issue first to discuss it before submitting a PR. Any `unsafe` block that does land must have a
`// SAFETY:` comment directly above it explaining exactly which invariants make it sound and why the compiler can't
verify them itself.
## Documenting wrappers, shims, and FFI adapters
When a function exists only to delegate to another function — for example, an FFI adapter, thin wrapper, or shim that
adds no behavior of its own — do not duplicate the callee's documentation.
Duplicated documentation tends to drift. When the underlying function changes, every copy has to be found and updated,
and stale documentation can be more misleading than a concise reference to the underlying implementation.
If a wrapper adds meaningful behavior, document that behavior. Otherwise, prefer keeping the documentation in one place.
## Code quality
When contributing, please aim for code that is:
- Idiomatic Rust.
- Explicit about failure modes and invariants.
- Easy to reason about.
- Appropriately documented, particularly where behavior is non-obvious.
- Tested when introducing or changing behavior.
- Consistent with the existing architecture.
For `eth_state_diff` in particular, please avoid introducing abstractions unless they make the behavior or invariants
clearer. Performance-sensitive code should have a clear reason for its complexity.
## Client-specific contributions and performance
Feel free to make contributions that are specific to your client or use case, provided they do not make performance
worse in other situations. For example, an additional if condition is perfectly reasonable if it benefits a particular
client without imposing a meaningful cost on other use cases.
More generally, I'm always willing to merge changes that measurably reduce space or time usage. If a change makes
`eth_state_diff` faster or more memory-efficient without compromising correctness or significantly regressing other
workloads, I'd be very happy to consider it.
## Where can I ask for help?
If you have questions or need help, please open an issue in the issue tracker.
This allows the discussion to benefit the wider community and gives us a searchable knowledge base for future
contributors.
If you're unsure whether an idea is appropriate for the project, opening an issue before doing substantial work is
encouraged.
## Thank you
I'd like to extend a pre-emptive thank you for reading through this and for taking the time to contribute to
`eth_state_diff`!
Every contribution, whether it's a bug fix, optimization, documentation improvement, test, or design discussion, is
appreciated.