No description
Find a file
2024-08-13 15:34:36 +05:30
.github feat: feature gate incremental function 2023-10-27 06:08:05 +05:30
.reuse feat: reuse init 2023-10-14 23:40:14 +05:30
docs/third-party feat: add NLnet funding details 2023-03-08 17:21:54 +05:30
examples chore: rename pow_sha256 crate (this) to mcaptcha_pow_sha256 2023-10-14 23:49:44 +05:30
fuzz fix(deps): update rust crate sha2 to 0.10 2024-06-04 08:06:05 +00:00
LICENSES feat: reuse init 2023-10-14 23:40:14 +05:30
src feat: feature gate incremental function 2023-10-27 06:08:05 +05:30
.gitignore feat: Makefile with common workflows 2023-07-04 19:08:58 +05:30
.woodpecker.yml fix: woodpecker config 2023-10-14 23:43:58 +05:30
Cargo.lock fix(deps): update rust crate serde to v1.0.207 2024-08-12 20:36:37 +00:00
Cargo.toml fix(deps): update rust crate derive_builder to 0.20 2024-06-04 08:06:03 +00:00
CHANGELOG.md feat: prep 0.5.0 2023-10-29 02:33:36 +05:30
code_of_conduct.md added code_of_conduct.md 2021-05-02 18:15:00 +05:30
Makefile feat: feature gate incremental function 2023-10-27 06:08:05 +05:30
README.md chore: rename pow_sha256 crate (this) to mcaptcha_pow_sha256 2023-10-14 23:49:44 +05:30
renovate.json Add renovate.json 2024-06-04 07:36:27 +00:00

PoW-SHA256

PoW-SHA256 - SHA256 based Proof-of-Work

status-badge

NOTE: All versions prior to 0.3.1 produce broken PoWs, upgrade to latest version

mcaptcha_pow_sha256 is a copy of pow_sha256 by robkorn which is a modified version of pow library. All copyrights belong to the original authors.

Rust crate which generates SHA256 Proofs of Work on serializable datatypes.

Whether for blockchain-related projects or Hashcash-like schemes, this crate can be used to prove work was done on a given serializable input. The input merely needs to implement serde::Deserialize to be used.

This is a fork of the pow library by @robkorn) with some new additions. Primary of these being:

  • PoW datatype now offers a constructor
  • Salt is no longer hard coded into the library, users can provide unique salts.

Other small changes have also been included of various importance but mostly just stylistic/ease of use improvements.

Documentation

https://docs.rs/mcaptcha_pow_sha256

Examples

Prove work specifically targeting a phrase.


use mcaptcha_pow_sha256::{ConfigBuilder, PoW};

fn main() {
    let config = ConfigBuilder::default()
        .salt("myrandomsaltisnotlongenoug".into())
        .build()
        .unwrap();

    let phrase = "ironmansucks";

    const DIFFICULTY: u32 = 1000;

    let work = config.prove_work(&phrase, DIFFICULTY).unwrap();
    assert!(config.calculate(&work, &phrase).unwrap() >= DIFFICULTY);
    assert!(config.is_valid_proof(&work, &phrase));
    assert!(config.is_sufficient_difficulty(&work, DIFFICULTY));
}

Prove more difficult work. This time targeting a time.

// Greater difficulty this time around. Takes around 100,000 hashes
// to find a nonce of the correct difficulty.


use mcaptcha_pow_sha256::{ConfigBuilder, PoW};

fn main() {
    let config = ConfigBuilder::default()
        .salt("myrandomsaltisnotlongenoug".into())
        .build()
        .unwrap();

    let phrase = "ironmansucks";

    const DIFFICULTY: u32 = 100_000;

    let work = config.prove_work(&phrase, DIFFICULTY).unwrap();

    assert!(config.calculate(&work, &phrase).unwrap() >= DIFFICULTY);
    assert!(config.is_valid_proof(&work, &phrase));
    assert!(config.is_sufficient_difficulty(&work, DIFFICULTY));
}

Hashing Scheme

SALT is used as prefix to prevent PoW reuse from other systems such as proof of work blockchains.

SHA256 is calculated over the concatenation of the:

  • SALT
  • Serialized Input T
  • Nonce

The first 16 bytes of the resulting hash are interpreted as a 128 bit unsigned integer and saved as the final result.

Choosing a difficulty setting.

Depending on your use case, difficulty settings often are best set dynamically a la bitcoin.

However if your use case requires manual setting then it is trivial to set one yourself. One way to do so is to choose the average number of hashes desired with a function like this:

fn get_difficulty(average: u128) -> u128 {
    debug_assert_ne!(average, 0, "It is impossible to prove work in zero attempts.");
    let m = u128::max_value();
    m - m / average
}

Conversely we can use the same equation to calculate the probable number of hashes required to satisfy a given difficulty:

fn est_average(difficulty: u128) -> u128 {
    let m = u128::max_value();
    if difficulty == m {
        return m;
    }
    m / (m - difficulty)
}

Changelog

See CHANGELOG.md

License

This project is dual-licensed under Apache License Version 2.0 or MIT license.

Funding

NLnet

NLnet NGIZero logo

2023 development is funded through the NGI0 Entrust Fund, via NLnet. Please see here for more details.