mirror of
https://github.com/TecharoHQ/anubis.git
synced 2026-04-08 01:28:44 +00:00
233
Cargo.lock
generated
233
Cargo.lock
generated
@@ -10,30 +10,22 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "argon2"
|
||||
version = "0.5.3"
|
||||
name = "arrayvec"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"blake2",
|
||||
"cpufeatures",
|
||||
"password-hash",
|
||||
]
|
||||
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
||||
|
||||
[[package]]
|
||||
name = "argon2id"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anubis",
|
||||
"argon2",
|
||||
]
|
||||
name = "autocfg"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.8.0"
|
||||
name = "bitflags"
|
||||
version = "2.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba"
|
||||
checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394"
|
||||
|
||||
[[package]]
|
||||
name = "blake2"
|
||||
@@ -62,6 +54,12 @@ dependencies = [
|
||||
"hybrid-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
@@ -130,6 +128,58 @@ dependencies = [
|
||||
"crypto-common 0.2.0-rc.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dynasm"
|
||||
version = "3.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f7d4c414c94bc830797115b8e5f434d58e7e80cb42ba88508c14bc6ea270625"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"lazy_static",
|
||||
"proc-macro-error2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dynasmrt"
|
||||
version = "3.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "602f7458a3859195fb840e6e0cce5f4330dd9dfbfece0edaf31fe427af346f55"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"dynasm",
|
||||
"fnv",
|
||||
"memmap2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equix"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b48d834668afc862e90cda69065c0d85c192fe0a9364d1c5c05baf21c7454fc9"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"hashx 0.4.0",
|
||||
"num-traits",
|
||||
"thiserror",
|
||||
"visibility",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixed-capacity-vec"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b31a14f5ee08ed1a40e1252b35af18bed062e3f39b69aab34decde36bc43e40"
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
@@ -140,6 +190,36 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashx"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anubis",
|
||||
"equix",
|
||||
"hashx 0.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashx"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8af708f5ff697572d409331c8714984a0ec1bb2eac190dd5bd75785bad6e764"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"blake2",
|
||||
"dynasmrt",
|
||||
"fixed-capacity-vec",
|
||||
"hex",
|
||||
"rand_core",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "hybrid-array"
|
||||
version = "0.4.2"
|
||||
@@ -149,12 +229,27 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.175"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
|
||||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "843a98750cd611cc2965a8213b53b43e715f13c37a9e096c6408e69990961db7"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memory_units"
|
||||
version = "0.4.0"
|
||||
@@ -162,21 +257,59 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3"
|
||||
|
||||
[[package]]
|
||||
name = "password-hash"
|
||||
version = "0.5.0"
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"rand_core",
|
||||
"subtle",
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr2"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error2"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.101"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
@@ -203,18 +336,66 @@ version = "2.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "2.0.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "2.0.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "visibility"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d674d135b4a8c1d7e813e2f8d1c9a58308aee4a680323066025e53132218bd91"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wee_alloc"
|
||||
version = "0.4.5"
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
//go:generate go tool github.com/a-h/templ/cmd/templ generate
|
||||
|
||||
func init() {
|
||||
chall.Register("argon2id", &Impl{algorithm: "argon2id"})
|
||||
chall.Register("hashx", &Impl{algorithm: "argon2id"})
|
||||
chall.Register("sha256", &Impl{algorithm: "sha256"})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "argon2id"
|
||||
name = "hashx"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
@@ -7,7 +7,8 @@ edition = "2024"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
argon2 = "0.5"
|
||||
equix = "0.3"
|
||||
hashx = "0.4"
|
||||
|
||||
anubis = { path = "../../anubis" }
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
use anubis::{DATA_BUFFER, DATA_LENGTH, update_nonce};
|
||||
use argon2::Argon2;
|
||||
use hashx::HashX;
|
||||
use std::boxed::Box;
|
||||
use std::sync::{LazyLock, Mutex};
|
||||
|
||||
/// SHA-256 hashes are 32 bytes (256 bits). These are stored in static buffers due to the
|
||||
/// fact that you cannot easily pass data from host space to WebAssembly space.
|
||||
pub static RESULT_HASH: LazyLock<Mutex<[u8; 32]>> = LazyLock::new(|| Mutex::new([0; 32]));
|
||||
pub static RESULT_HASH: LazyLock<Box<Mutex<[u8; 32]>>> =
|
||||
LazyLock::new(|| Box::new(Mutex::new([0; 32])));
|
||||
|
||||
pub static VERIFICATION_HASH: LazyLock<Box<Mutex<[u8; 32]>>> =
|
||||
LazyLock::new(|| Box::new(Mutex::new([0; 32])));
|
||||
@@ -44,40 +45,43 @@ fn validate(hash: &[u8], difficulty: u32) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
/// Computes hash for given nonce.
|
||||
///
|
||||
/// This differs from the JavaScript implementations by constructing the hash differently. In
|
||||
/// JavaScript implementations, the SHA-256 input is the result of appending the nonce as an
|
||||
/// integer to the hex-formatted challenge, eg:
|
||||
///
|
||||
/// sha256(`${challenge}${nonce}`);
|
||||
///
|
||||
/// This **does work**, however I think that this can be done a bit better by operating on the
|
||||
/// challenge bytes _directly_ and treating the nonce as a salt.
|
||||
///
|
||||
/// The nonce is also randomly encoded in either big or little endian depending on the last
|
||||
/// byte of the data buffer in an effort to make it more annoying to automate with GPUs.
|
||||
fn compute_hash(nonce: u32) -> [u8; 32] {
|
||||
fn anubis_work_inner(
|
||||
difficulty: u32,
|
||||
initial_nonce: u32,
|
||||
iterand: u32,
|
||||
) -> Result<u32, hashx::Error> {
|
||||
let mut nonce: u32 = initial_nonce;
|
||||
|
||||
let data = &DATA_BUFFER;
|
||||
let data_len = *DATA_LENGTH.lock().unwrap();
|
||||
let use_le = data[data_len - 1] >= 128;
|
||||
let mut result = [0u8; 32];
|
||||
|
||||
let nonce = nonce as u64;
|
||||
|
||||
let data_slice = &data[..data_len];
|
||||
|
||||
let nonce = if use_le {
|
||||
nonce.to_le_bytes()
|
||||
} else {
|
||||
nonce.to_be_bytes()
|
||||
};
|
||||
let h = HashX::new(data_slice)?;
|
||||
|
||||
let argon2 = Argon2::default();
|
||||
argon2
|
||||
.hash_password_into(&data_slice, &nonce, &mut result)
|
||||
.unwrap();
|
||||
result
|
||||
loop {
|
||||
let hash = h.hash_to_bytes(nonce as u64);
|
||||
|
||||
if validate(&hash, difficulty) {
|
||||
// If the challenge worked, copy the bytes into `RESULT_HASH` so the runtime
|
||||
// can pick it up.
|
||||
let mut challenge = RESULT_HASH.lock().unwrap();
|
||||
challenge.copy_from_slice(&hash);
|
||||
return Ok(nonce);
|
||||
}
|
||||
|
||||
let old_nonce = nonce;
|
||||
nonce = nonce.wrapping_add(iterand);
|
||||
|
||||
// send a progress update every 1024 iterations. since each thread checks
|
||||
// separate values, one simple way to do this is by bit masking the
|
||||
// nonce for multiples of 1024. unfortunately, if the number of threads
|
||||
// is not prime, only some of the threads will be sending the status
|
||||
// update and they will get behind the others. this is slightly more
|
||||
// complicated but ensures an even distribution between threads.
|
||||
if nonce > old_nonce | 1023 && (nonce >> 10) % iterand == initial_nonce {
|
||||
update_nonce(nonce);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This function is the main entrypoint for the Anubis proof of work implementation.
|
||||
@@ -100,32 +104,7 @@ fn compute_hash(nonce: u32) -> [u8; 32] {
|
||||
/// wasting CPU time retrying a hash+nonce pair that likely won't work.
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn anubis_work(difficulty: u32, initial_nonce: u32, iterand: u32) -> u32 {
|
||||
let mut nonce = initial_nonce;
|
||||
|
||||
loop {
|
||||
let hash = compute_hash(nonce);
|
||||
|
||||
if validate(&hash, difficulty) {
|
||||
// If the challenge worked, copy the bytes into `RESULT_HASH` so the runtime
|
||||
// can pick it up.
|
||||
let mut challenge = RESULT_HASH.lock().unwrap();
|
||||
challenge.copy_from_slice(&hash);
|
||||
return nonce;
|
||||
}
|
||||
|
||||
let old_nonce = nonce;
|
||||
nonce = nonce.wrapping_add(iterand);
|
||||
|
||||
// send a progress update every 1024 iterations. since each thread checks
|
||||
// separate values, one simple way to do this is by bit masking the
|
||||
// nonce for multiples of 1024. unfortunately, if the number of threads
|
||||
// is not prime, only some of the threads will be sending the status
|
||||
// update and they will get behind the others. this is slightly more
|
||||
// complicated but ensures an even distribution between threads.
|
||||
if nonce > old_nonce + 1023 && (nonce >> 10) % iterand == initial_nonce {
|
||||
update_nonce(nonce);
|
||||
}
|
||||
}
|
||||
anubis_work_inner(difficulty, initial_nonce, iterand).unwrap()
|
||||
}
|
||||
|
||||
/// This function is called by the server in order to validate a proof-of-work challenge.
|
||||
@@ -138,7 +117,12 @@ pub extern "C" fn anubis_work(difficulty: u32, initial_nonce: u32, iterand: u32)
|
||||
/// for now.
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn anubis_validate(nonce: u32, difficulty: u32) -> bool {
|
||||
let computed = compute_hash(nonce);
|
||||
let data = &DATA_BUFFER;
|
||||
let data_len = *DATA_LENGTH.lock().unwrap();
|
||||
let data_slice = &data[..data_len];
|
||||
|
||||
let h: HashX = HashX::new(data_slice).unwrap();
|
||||
let computed = h.hash_to_bytes(nonce as u64);
|
||||
let valid = validate(&computed, difficulty);
|
||||
if !valid {
|
||||
return false;
|
||||
@@ -58,9 +58,8 @@ func TestAlgos(t *testing.T) {
|
||||
|
||||
for _, kind := range []string{"baseline", "simd128"} {
|
||||
for _, fname := range fnames {
|
||||
fname := fname
|
||||
t.Run(fname.Name(), func(t *testing.T) {
|
||||
abiTest(t, kind, fname.Name(), 4)
|
||||
t.Run(kind+"/"+fname.Name(), func(t *testing.T) {
|
||||
abiTest(t, kind, fname.Name(), 16)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -112,10 +111,10 @@ func BenchmarkSHA256(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkArgon2ID(b *testing.B) {
|
||||
func BenchmarkHashX(b *testing.B) {
|
||||
for _, kind := range []string{"baseline", "simd128"} {
|
||||
b.Run(kind, func(b *testing.B) {
|
||||
bench(b, kind, "argon2id.wasm", []uint32{4, 6, 8})
|
||||
bench(b, kind, "hashx.wasm", []uint32{4, 6, 8, 10, 12, 14, 16})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user