# RSPOW
[](https://crates.io/crates/rspow)
[](https://crates.io/crates/rspow)
[](https://crates.io/crates/rspow)
[](https://zolagonano.github.io/support)
A simple multi-algorithm proof-of-work library for Rust.
## Algorithms
- [x] SHA-256
- [x] SHA-512
- [x] RIPEMD-320
- [x] Scrypt
- [x] Argon2id
API references are available at [docs.rs/rspow](https://docs.rs/rspow).
## Difficulty Modes
RSPOW supports two difficulty modes:
- AsciiZeroPrefix (default): the hash must start with `difficulty` bytes of ASCII `'0'` (`0x30`).
- Expected attempts grow by ~256 per additional byte.
- Simple to explain, but coarse-grained and often too steep for memory-hard hashes.
- LeadingZeroBits: the hash must have at least `difficulty` leading zero bits.
- Expected attempts ≈ `2^difficulty`.
- Fine-grained control suitable for tuning across a wide range.
Notes:
- `PoW::calculate_target()` returns the ASCII `'0'` prefix and is meaningful only for `AsciiZeroPrefix`.
- In `LeadingZeroBits` mode, the `target` slice is ignored; pass an empty slice for clarity.
## Examples
### ASCII `'0'` prefix (default)
```rust
use rspow::{PoW, PoWAlgorithm};
let data = "hello world";
let difficulty = 2; // requires prefix "00"
let algorithm = PoWAlgorithm::Sha2_512;
let pow = PoW::new(data, difficulty, algorithm).unwrap();
let target = pow.calculate_target(); // [0x30; difficulty]
let (hash, nonce) = pow.calculate_pow(&target);
assert!(hash.starts_with(&target[..difficulty]));
assert!(pow.verify_pow(&target, (hash, nonce)));
```
### Leading zero bits (fine-grained)
```rust
use rspow::{PoW, PoWAlgorithm, DifficultyMode};
let data = "hello world";
let bits = 12; // expected attempts ~ 2^12 = 4096
let algorithm = PoWAlgorithm::Sha2_256;
let pow = PoW::with_mode(data, bits, algorithm, DifficultyMode::LeadingZeroBits).unwrap();
let (hash, nonce) = pow.calculate_pow(&[]); // target is ignored in bits mode
assert!(rspow::meets_leading_zero_bits(&hash, bits as u32));
assert!(pow.verify_pow(&[], (hash, nonce)));
```
### Argon2id with custom parameters
```rust
use rspow::{PoW, PoWAlgorithm, Argon2Params, DifficultyMode};
let data = b"hello world";
// Example parameters only; tune for your threat model.
let params = Argon2Params::new(/* m_cost KiB */ 64 * 1024, /* t_cost */ 3, /* p */ 1, None).unwrap();
let algorithm = PoWAlgorithm::Argon2id(params);
// Prefer LeadingZeroBits for smoother tuning with memory-hard functions
let bits = 8; // expected attempts ~ 256
let pow = PoW::with_mode(data, bits, algorithm, DifficultyMode::LeadingZeroBits).unwrap();
let (hash, nonce) = pow.calculate_pow(&[]);
assert!(rspow::meets_leading_zero_bits(&hash, bits as u32));
```
## Tuning Guidance
- LeadingZeroBits: each additional bit doubles expected attempts; choose `bits` to match your time budget.
- AsciiZeroPrefix: each additional byte multiplies attempts by ~256; easy but coarse.
- Memory-hard algorithms (e.g., Argon2id, Scrypt) may make multi-byte ASCII prefix targets impractical; prefer `LeadingZeroBits`.
## Compatibility
- Existing code using `PoW::new` and `calculate_target()` keeps the legacy behavior by default.
- New code is encouraged to adopt `DifficultyMode::LeadingZeroBits` for precise difficulty control.