A proof-of-work toolbox for Rust with optional backends and a near-stateless protocol helper. Enable
features = ["equix"]to use the EquiX solver.
- Default features are now empty. Opt in to algorithms and toolkits explicitly to keep compile size and transitive deps small.
- EquiX backend is feature-gated (
features = ["equix"]). Other algorithms will be added behind their own features once the public API stabilizes. - Near-stateless PoW toolkit (
features = ["near-stateless"]) offers helper traits and types for the time-bound, replay-protected workflow described below (time windows must be whole seconds to avoid silent truncation). The verifier now owns theserver_secret, so helpers (issue_params) require no extra secret arguments. - Progress reporting:
EquixEngineexposes anArc<AtomicU64>counter you can wire into a progress bar during long searches.
| Feature | Default | What it enables |
|---|---|---|
equix |
❌ | EquiX engine, proofs, bundles, tests |
near-stateless |
❌ | Near-stateless server/client helpers (depends on equix) |
Add the crate with the features you need:
rspow = { version = "0.4", features = ["equix"] }
# rspow = { version = "0.4", features = ["equix", "near-stateless"] }Raising leading-zero difficulty increases expected attempts exponentially (2^bits) and also widens variance, so different clients see very different solve times. Bundling proofs scales linearly: requiring N independent proofs gives roughly N× work and shrinks relative variance, yielding steadier user experience. ProofBundle encodes the required proof count and the master challenge, letting servers verify each proof in O(1) time.
Enable
features = ["equix"]. Examples require explicit features.
Progress bars: read progress.load(Ordering::Relaxed) to track how many challenges have been attempted (when provided to EquixEngine).
features = ["near-stateless"] exposes building blocks for a time-windowed, replay-protected flow where servers keep almost no issuance state:
- Deterministic nonce provider (
DeterministicNonceProvider): default is keyed BLAKE3 with tag"rspow:nonce:v1". - Replay cache (
ReplayCache): default in-memoryMokaReplayCache; pluggable for Redis/Memcached. If the cache is capacity-bound, evictions can allow replays—size it for your load or provide your own implementation. - Time provider (
TimeProvider): injectable clock for tests. - Verifier configuration (
VerifierConfig):time_window >= 1sand an integral number of seconds,min_difficulty,min_required_proofs; hot-swappable at runtime viaset_config(internally lock-free reads with left-right). - Submission:
{ timestamp, client_nonce, ProofBundle }from the client.
Protocol sketch (details in docs/near_stateless_pow.md):
- Server computes
deterministic_nonce = F(secret, timestamp)(keyed BLAKE3) for requestedtimestampwithin[now - time_window, now]. - Client samples a random
client_nonce, derivesmaster_challenge = BLAKE3("rspow:challenge:v1" || deterministic_nonce || client_nonce), solves for aProofBundle. - Client submits
{timestamp, client_nonce, proof_bundle}. Server recomputes the nonce/challenge, enforces time window, verifies proofs against policy, then recordsclient_noncein the replay cache untiltimestamp + time_window.
Server-side flow in brief: derive deterministic nonce with your secret, enforce the (integral-seconds) time window, check replay cache, recompute master challenge, and call verify_submission; see docs/near_stateless_pow.md for the full walk-through and helper APIs (including issue_params/solve_submission_from_params).
The examples/near_stateless_demo.rs program shows a minimal async client/server flow using the toolkit:
- Server issues deterministic nonce + config (
issue_params), verifies submissions, and blocks replays. - Client derives the master challenge, solves with EquiX, reports progress, and submits a proof bundle.
- Progress bar shows percentage, bar, proofs done, and attempts.
- Uses a single-thread Tokio runtime plus
spawn_blockingfor the CPU-heavy solve.
Run it (features must be enabled explicitly):
cargo r --release -F equix,near-stateless --example near_stateless_demoYou can reuse it as a reference when wiring rspow into your own service: copy the parameter issuance, solve, submit, and verify steps to fit your transport/protocol.
Run the async end-to-end demo (requires --features "equix near-stateless"):
cargo run --example near_stateless_demo --features "equix near-stateless"cargo fmt --all
cargo clippy --workspace --all-features -- -D warnings
cargo test --all-featuresRunning tests without features will compile only the core types; enable the features you use to exercise their code paths.
Apache-2.0 or MIT, at your option.