rspow 0.2.0

A multi-algorithm proof-of-work library in rust
Documentation

RSPOW

b b b b

A simple multi-algorithm proof-of-work library for Rust.

Algorithms

  • SHA-256
  • SHA-512
  • RIPEMD-320
  • Scrypt
  • Argon2id

API references are available at 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)

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)

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

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.