Compare commits
33 Commits
ab416e212f
...
5afe70d831
Author | SHA1 | Date |
---|---|---|
str4d | 5afe70d831 | |
Kris Nuttycombe | 895afe51f7 | |
Jack Grigg | 069109b691 | |
Jack Grigg | 011909d609 | |
Jack Grigg | 66f11ce29f | |
Jack Grigg | 08cd7e20bd | |
Jack Grigg | e574c27755 | |
Jack Grigg | 846d9860f1 | |
Jack Grigg | 03627b1de5 | |
Jack Grigg | d99edccaa3 | |
Jack Grigg | 12334b3a18 | |
Jack Grigg | 6bbd002f59 | |
Jack Grigg | 4eb2df6714 | |
Jack Grigg | 3f11ba5c74 | |
Jack Grigg | f3717d9427 | |
Jack Grigg | afb8b55ed8 | |
Jack Grigg | 672cc9f080 | |
teor | 76131db25a | |
teor | 9391e65c21 | |
teor | 2bd7bc8f8e | |
teor | b737d0fe26 | |
teor | 989f40ee9b | |
teor | d7ccd07d0b | |
teor | 5f77bd79db | |
teor | 3c78bf60a1 | |
teor | 463e7d9958 | |
teor | fe3b269f3a | |
teor | 1b20c15053 | |
Jack Grigg | d07505de71 | |
Jack Grigg | 45e7238b80 | |
Jack Grigg | 3aaeb8b719 | |
Jack Grigg | 7ab6c47d5b | |
Jack Grigg | 45652a21a8 |
|
@ -0,0 +1,30 @@
|
|||
name: Audits
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches: main
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
cargo-vet:
|
||||
name: Vet Rust dependencies
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
id: toolchain
|
||||
- run: rustup override set ${{steps.toolchain.outputs.name}}
|
||||
- run: cargo install cargo-vet --version ~0.9
|
||||
- run: cargo vet --locked
|
||||
|
||||
cargo-deny:
|
||||
name: Check licenses
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: EmbarkStudios/cargo-deny-action@v1
|
||||
with:
|
||||
command: check licenses
|
|
@ -282,9 +282,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.4.1"
|
||||
version = "2.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
|
||||
|
||||
[[package]]
|
||||
name = "bitvec"
|
||||
|
@ -659,6 +659,8 @@ version = "0.2.0"
|
|||
dependencies = [
|
||||
"blake2b_simd",
|
||||
"byteorder",
|
||||
"cc",
|
||||
"hex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1751,7 +1753,7 @@ checksum = "7c003ac8c77cb07bb74f5f198bce836a689bcd5a42574612bf14d17bfd08c20e"
|
|||
dependencies = [
|
||||
"bit-set",
|
||||
"bit-vec",
|
||||
"bitflags 2.4.1",
|
||||
"bitflags 2.4.2",
|
||||
"lazy_static",
|
||||
"num-traits",
|
||||
"rand",
|
||||
|
@ -2034,7 +2036,7 @@ version = "0.29.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "549b9d036d571d42e6e85d1c1425e2ac83491075078ca9a15be021c56b1641f2"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"bitflags 2.4.2",
|
||||
"fallible-iterator",
|
||||
"fallible-streaming-iterator",
|
||||
"hashlink",
|
||||
|
@ -2055,7 +2057,7 @@ version = "0.38.21"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"bitflags 2.4.2",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
|
@ -2265,7 +2267,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "d766257c56a1bdd75479c256b97c92e72788a9afb18b5199f58faf7188dc99d9"
|
||||
dependencies = [
|
||||
"assert_matches",
|
||||
"bitflags 2.4.1",
|
||||
"bitflags 2.4.2",
|
||||
"either",
|
||||
"incrementalmerkletree",
|
||||
"proptest",
|
||||
|
@ -2421,18 +2423,18 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
|
|||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.50"
|
||||
version = "1.0.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
|
||||
checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.50"
|
||||
version = "1.0.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
|
||||
checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
|
@ -9,9 +9,21 @@ license = "MIT OR Apache-2.0"
|
|||
edition = "2021"
|
||||
rust-version = "1.56.1"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
## Builds the C++ tromp solver and Rust FFI layer.
|
||||
solver = ["dep:cc"]
|
||||
|
||||
[dependencies]
|
||||
blake2b_simd = "1"
|
||||
byteorder = "1"
|
||||
|
||||
[build-dependencies]
|
||||
cc = { version = "1", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
hex = "0.4"
|
||||
|
||||
[lib]
|
||||
bench = false
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
//! Build script for the equihash tromp solver in C.
|
||||
|
||||
fn main() {
|
||||
#[cfg(feature = "solver")]
|
||||
build_tromp_solver();
|
||||
}
|
||||
|
||||
#[cfg(feature = "solver")]
|
||||
fn build_tromp_solver() {
|
||||
cc::Build::new()
|
||||
.include("tromp/")
|
||||
.file("tromp/equi_miner.c")
|
||||
.compile("equitromp");
|
||||
|
||||
// Tell Cargo to only rerun this build script if the tromp C files or headers change.
|
||||
println!("cargo:rerun-if-changed=tromp");
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright (c) 2020-2022 The Zcash developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
// This module uses unsafe code for FFI into blake2b.
|
||||
#![allow(unsafe_code)]
|
||||
|
||||
use blake2b_simd::{State, PERSONALBYTES};
|
||||
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn blake2b_init(
|
||||
output_len: usize,
|
||||
personalization: *const [u8; PERSONALBYTES],
|
||||
) -> *mut State {
|
||||
let personalization = unsafe { personalization.as_ref().unwrap() };
|
||||
|
||||
Box::into_raw(Box::new(
|
||||
blake2b_simd::Params::new()
|
||||
.hash_length(output_len)
|
||||
.personal(personalization)
|
||||
.to_state(),
|
||||
))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn blake2b_clone(state: *const State) -> *mut State {
|
||||
unsafe { state.as_ref() }
|
||||
.map(|state| Box::into_raw(Box::new(state.clone())))
|
||||
.unwrap_or(ptr::null_mut())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn blake2b_free(state: *mut State) {
|
||||
if !state.is_null() {
|
||||
drop(unsafe { Box::from_raw(state) });
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn blake2b_update(state: *mut State, input: *const u8, input_len: usize) {
|
||||
let state = unsafe { state.as_mut().unwrap() };
|
||||
let input = unsafe { slice::from_raw_parts(input, input_len) };
|
||||
|
||||
state.update(input);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn blake2b_finalize(state: *mut State, output: *mut u8, output_len: usize) {
|
||||
let state = unsafe { state.as_mut().unwrap() };
|
||||
let output = unsafe { slice::from_raw_parts_mut(output, output_len) };
|
||||
|
||||
// Allow consuming only part of the output.
|
||||
let hash = state.finalize();
|
||||
assert!(output_len <= hash.as_bytes().len());
|
||||
output.copy_from_slice(&hash.as_bytes()[..output_len]);
|
||||
}
|
|
@ -28,3 +28,8 @@ mod verify;
|
|||
mod test_vectors;
|
||||
|
||||
pub use verify::{is_valid_solution, Error};
|
||||
|
||||
#[cfg(feature = "solver")]
|
||||
mod blake2b;
|
||||
#[cfg(feature = "solver")]
|
||||
pub mod tromp;
|
||||
|
|
|
@ -5,6 +5,49 @@ use byteorder::{BigEndian, ReadBytesExt};
|
|||
|
||||
use crate::params::Params;
|
||||
|
||||
// Rough translation of CompressArray() from:
|
||||
// https://github.com/zcash/zcash/blob/6fdd9f1b81d3b228326c9826fa10696fc516444b/src/crypto/equihash.cpp#L39-L76
|
||||
#[cfg(any(feature = "solver", test))]
|
||||
fn compress_array(array: &[u8], bit_len: usize, byte_pad: usize) -> Vec<u8> {
|
||||
let index_bytes = (u32::BITS / 8) as usize;
|
||||
assert!(bit_len >= 8);
|
||||
assert!(8 * index_bytes >= 7 + bit_len);
|
||||
|
||||
let in_width: usize = (bit_len + 7) / 8 + byte_pad;
|
||||
let out_len = bit_len * array.len() / (8 * in_width);
|
||||
|
||||
let mut out = Vec::with_capacity(out_len);
|
||||
let bit_len_mask: u32 = (1 << (bit_len as u32)) - 1;
|
||||
|
||||
// The acc_bits least-significant bits of acc_value represent a bit sequence
|
||||
// in big-endian order.
|
||||
let mut acc_bits: usize = 0;
|
||||
let mut acc_value: u32 = 0;
|
||||
|
||||
let mut j: usize = 0;
|
||||
for _i in 0..out_len {
|
||||
// When we have fewer than 8 bits left in the accumulator, read the next
|
||||
// input element.
|
||||
if acc_bits < 8 {
|
||||
acc_value <<= bit_len;
|
||||
for x in byte_pad..in_width {
|
||||
acc_value |= (
|
||||
// Apply bit_len_mask across byte boundaries
|
||||
(array[j + x] & ((bit_len_mask >> (8 * (in_width - x - 1))) as u8)) as u32
|
||||
)
|
||||
.wrapping_shl(8 * (in_width - x - 1) as u32); // Big-endian
|
||||
}
|
||||
j += in_width;
|
||||
acc_bits += bit_len;
|
||||
}
|
||||
|
||||
acc_bits -= 8;
|
||||
out.push((acc_value >> acc_bits) as u8);
|
||||
}
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
pub(crate) fn expand_array(vin: &[u8], bit_len: usize, byte_pad: usize) -> Vec<u8> {
|
||||
assert!(bit_len >= 8);
|
||||
assert!(u32::BITS as usize >= 7 + bit_len);
|
||||
|
@ -50,6 +93,31 @@ pub(crate) fn expand_array(vin: &[u8], bit_len: usize, byte_pad: usize) -> Vec<u
|
|||
vout
|
||||
}
|
||||
|
||||
// Rough translation of GetMinimalFromIndices() from:
|
||||
// https://github.com/zcash/zcash/blob/6fdd9f1b81d3b228326c9826fa10696fc516444b/src/crypto/equihash.cpp#L130-L145
|
||||
#[cfg(any(feature = "solver", test))]
|
||||
pub(crate) fn minimal_from_indices(p: Params, indices: &[u32]) -> Vec<u8> {
|
||||
let c_bit_len = p.collision_bit_length();
|
||||
let index_bytes = (u32::BITS / 8) as usize;
|
||||
let digit_bytes = ((c_bit_len + 1) + 7) / 8;
|
||||
assert!(digit_bytes <= index_bytes);
|
||||
|
||||
let len_indices = indices.len() * index_bytes;
|
||||
let byte_pad = index_bytes - digit_bytes;
|
||||
|
||||
// Rough translation of EhIndexToArray(index, array_pointer) from:
|
||||
// https://github.com/zcash/zcash/blob/6fdd9f1b81d3b228326c9826fa10696fc516444b/src/crypto/equihash.cpp#L123-L128
|
||||
//
|
||||
// Big-endian so that lexicographic array comparison is equivalent to integer comparison.
|
||||
let array: Vec<u8> = indices
|
||||
.iter()
|
||||
.flat_map(|index| index.to_be_bytes())
|
||||
.collect();
|
||||
assert_eq!(array.len(), len_indices);
|
||||
|
||||
compress_array(&array, c_bit_len + 1, byte_pad)
|
||||
}
|
||||
|
||||
/// Returns `None` if the parameters are invalid for this minimal encoding.
|
||||
pub(crate) fn indices_from_minimal(p: Params, minimal: &[u8]) -> Option<Vec<u32>> {
|
||||
let c_bit_len = p.collision_bit_length();
|
||||
|
@ -76,11 +144,14 @@ pub(crate) fn indices_from_minimal(p: Params, minimal: &[u8]) -> Option<Vec<u32>
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{expand_array, indices_from_minimal, Params};
|
||||
use crate::minimal::minimal_from_indices;
|
||||
|
||||
use super::{compress_array, expand_array, indices_from_minimal, Params};
|
||||
|
||||
#[test]
|
||||
fn array_expansion() {
|
||||
fn array_compression_and_expansion() {
|
||||
let check_array = |(bit_len, byte_pad), compact, expanded| {
|
||||
assert_eq!(compress_array(expanded, bit_len, byte_pad), compact);
|
||||
assert_eq!(expand_array(compact, bit_len, byte_pad), expanded);
|
||||
};
|
||||
|
||||
|
@ -149,10 +220,9 @@ mod tests {
|
|||
#[test]
|
||||
fn minimal_solution_repr() {
|
||||
let check_repr = |minimal, indices| {
|
||||
assert_eq!(
|
||||
indices_from_minimal(Params { n: 80, k: 3 }, minimal).unwrap(),
|
||||
indices,
|
||||
);
|
||||
let p = Params { n: 80, k: 3 };
|
||||
assert_eq!(minimal_from_indices(p, indices), minimal);
|
||||
assert_eq!(indices_from_minimal(p, minimal).unwrap(), indices);
|
||||
};
|
||||
|
||||
// The solutions here are not intended to be valid.
|
||||
|
|
|
@ -0,0 +1,256 @@
|
|||
//! Rust interface to the tromp equihash solver.
|
||||
|
||||
use std::marker::{PhantomData, PhantomPinned};
|
||||
use std::slice;
|
||||
|
||||
use blake2b_simd::State;
|
||||
|
||||
use crate::{blake2b, minimal::minimal_from_indices, params::Params, verify};
|
||||
|
||||
#[repr(C)]
|
||||
struct CEqui {
|
||||
_f: [u8; 0],
|
||||
_m: PhantomData<(*mut u8, PhantomPinned)>,
|
||||
}
|
||||
|
||||
#[link(name = "equitromp")]
|
||||
extern "C" {
|
||||
#[allow(improper_ctypes)]
|
||||
fn equi_new(
|
||||
blake2b_clone: extern "C" fn(state: *const State) -> *mut State,
|
||||
blake2b_free: extern "C" fn(state: *mut State),
|
||||
blake2b_update: extern "C" fn(state: *mut State, input: *const u8, input_len: usize),
|
||||
blake2b_finalize: extern "C" fn(state: *mut State, output: *mut u8, output_len: usize),
|
||||
) -> *mut CEqui;
|
||||
fn equi_free(eq: *mut CEqui);
|
||||
#[allow(improper_ctypes)]
|
||||
fn equi_setstate(eq: *mut CEqui, ctx: *const State);
|
||||
fn equi_clearslots(eq: *mut CEqui);
|
||||
fn equi_digit0(eq: *mut CEqui, id: u32);
|
||||
fn equi_digitodd(eq: *mut CEqui, r: u32, id: u32);
|
||||
fn equi_digiteven(eq: *mut CEqui, r: u32, id: u32);
|
||||
fn equi_digitK(eq: *mut CEqui, id: u32);
|
||||
fn equi_nsols(eq: *const CEqui) -> usize;
|
||||
/// Returns `equi_nsols()` solutions of length `2^K`, in a single memory allocation.
|
||||
fn equi_sols(eq: *const CEqui) -> *const u32;
|
||||
}
|
||||
|
||||
/// Performs a single equihash solver run with equihash parameters `p` and hash state `curr_state`.
|
||||
/// Returns zero or more unique solutions.
|
||||
///
|
||||
/// # SAFETY
|
||||
///
|
||||
/// The parameters to this function must match the hard-coded parameters in the C++ code.
|
||||
///
|
||||
/// This function uses unsafe code for FFI into the tromp solver.
|
||||
#[allow(unsafe_code)]
|
||||
#[allow(clippy::print_stdout)]
|
||||
unsafe fn worker(eq: *mut CEqui, p: Params, curr_state: &State) -> Vec<Vec<u32>> {
|
||||
// SAFETY: caller must supply a valid `eq` instance.
|
||||
//
|
||||
// Review Note: nsols is set to zero in C++ here
|
||||
equi_setstate(eq, curr_state);
|
||||
|
||||
// Initialization done, start algo driver.
|
||||
equi_digit0(eq, 0);
|
||||
equi_clearslots(eq);
|
||||
// SAFETY: caller must supply a `p` instance that matches the hard-coded values in the C code.
|
||||
for r in 1..p.k {
|
||||
if (r & 1) != 0 {
|
||||
equi_digitodd(eq, r, 0)
|
||||
} else {
|
||||
equi_digiteven(eq, r, 0)
|
||||
};
|
||||
equi_clearslots(eq);
|
||||
}
|
||||
// Review Note: nsols is increased here, but only if the solution passes the strictly ordered check.
|
||||
// With 256 nonces, we get to around 6/9 digits strictly ordered.
|
||||
equi_digitK(eq, 0);
|
||||
|
||||
let solutions = {
|
||||
let nsols = equi_nsols(eq);
|
||||
let sols = equi_sols(eq);
|
||||
let solution_len = 1 << p.k;
|
||||
//println!("{nsols} solutions of length {solution_len} at {sols:?}");
|
||||
|
||||
// SAFETY:
|
||||
// - caller must supply a `p` instance that matches the hard-coded values in the C code.
|
||||
// - `sols` is a single allocation containing at least `nsols` solutions.
|
||||
// - this slice is a shared ref to the memory in a valid `eq` instance supplied by the caller.
|
||||
let solutions: &[u32] = slice::from_raw_parts(sols, nsols * solution_len);
|
||||
|
||||
/*
|
||||
println!(
|
||||
"{nsols} solutions of length {solution_len} as a slice of length {:?}",
|
||||
solutions.len()
|
||||
);
|
||||
*/
|
||||
|
||||
let mut chunks = solutions.chunks_exact(solution_len);
|
||||
|
||||
// SAFETY:
|
||||
// - caller must supply a `p` instance that matches the hard-coded values in the C code.
|
||||
// - each solution contains `solution_len` u32 values.
|
||||
// - the temporary slices are shared refs to a valid `eq` instance supplied by the caller.
|
||||
// - the bytes in the shared ref are copied before they are returned.
|
||||
// - dropping `solutions: &[u32]` does not drop the underlying memory owned by `eq`.
|
||||
let mut solutions = (&mut chunks)
|
||||
.map(|solution| solution.to_vec())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(chunks.remainder().len(), 0);
|
||||
|
||||
// Sometimes the solver returns identical solutions.
|
||||
solutions.sort();
|
||||
solutions.dedup();
|
||||
|
||||
solutions
|
||||
};
|
||||
|
||||
/*
|
||||
println!(
|
||||
"{} solutions as cloned vectors of length {:?}",
|
||||
solutions.len(),
|
||||
solutions
|
||||
.iter()
|
||||
.map(|solution| solution.len())
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
*/
|
||||
|
||||
solutions
|
||||
}
|
||||
|
||||
/// Performs multiple equihash solver runs with equihash parameters `200, 9`, initialising the hash with
|
||||
/// the supplied partial `input`. Between each run, generates a new nonce of length `N` using the
|
||||
/// `next_nonce` function.
|
||||
///
|
||||
/// Returns zero or more unique solutions.
|
||||
pub fn solve_200_9<const N: usize>(
|
||||
input: &[u8],
|
||||
mut next_nonce: impl FnMut() -> Option<[u8; N]>,
|
||||
) -> Vec<Vec<u32>> {
|
||||
let p = Params::new(200, 9).expect("should be valid");
|
||||
let mut state = verify::initialise_state(p.n, p.k, p.hash_output());
|
||||
state.update(input);
|
||||
|
||||
// Create solver and initialize it.
|
||||
//
|
||||
// # SAFETY
|
||||
// - the parameters 200,9 match the hard-coded parameters in the C++ code.
|
||||
// - tromp is compiled without multi-threading support, so each instance can only support 1 thread.
|
||||
// - the blake2b functions are in the correct order in Rust and C++ initializers.
|
||||
#[allow(unsafe_code)]
|
||||
let eq = unsafe {
|
||||
equi_new(
|
||||
blake2b::blake2b_clone,
|
||||
blake2b::blake2b_free,
|
||||
blake2b::blake2b_update,
|
||||
blake2b::blake2b_finalize,
|
||||
)
|
||||
};
|
||||
|
||||
let solutions = loop {
|
||||
let nonce = match next_nonce() {
|
||||
Some(nonce) => nonce,
|
||||
None => break vec![],
|
||||
};
|
||||
|
||||
let mut curr_state = state.clone();
|
||||
// Review Note: these hashes are changing when the nonce changes
|
||||
curr_state.update(&nonce);
|
||||
|
||||
// SAFETY:
|
||||
// - the parameters 200,9 match the hard-coded parameters in the C++ code.
|
||||
// - the eq instance is initilized above.
|
||||
#[allow(unsafe_code)]
|
||||
let solutions = unsafe { worker(eq, p, &curr_state) };
|
||||
if !solutions.is_empty() {
|
||||
break solutions;
|
||||
}
|
||||
};
|
||||
|
||||
// SAFETY:
|
||||
// - the eq instance is initilized above, and not used after this point.
|
||||
#[allow(unsafe_code)]
|
||||
unsafe {
|
||||
equi_free(eq)
|
||||
};
|
||||
|
||||
solutions
|
||||
}
|
||||
|
||||
/// Performs multiple equihash solver runs with equihash parameters `200, 9`, initialising the hash with
|
||||
/// the supplied partial `input`. Between each run, generates a new nonce of length `N` using the
|
||||
/// `next_nonce` function.
|
||||
///
|
||||
/// Returns zero or more unique compressed solutions.
|
||||
pub fn solve_200_9_compressed<const N: usize>(
|
||||
input: &[u8],
|
||||
next_nonce: impl FnMut() -> Option<[u8; N]>,
|
||||
) -> Vec<Vec<u8>> {
|
||||
let p = Params::new(200, 9).expect("should be valid");
|
||||
let solutions = solve_200_9(input, next_nonce);
|
||||
|
||||
let mut solutions: Vec<Vec<u8>> = solutions
|
||||
.iter()
|
||||
.map(|solution| minimal_from_indices(p, solution))
|
||||
.collect();
|
||||
|
||||
// Just in case the solver returns solutions that become the same when compressed.
|
||||
solutions.sort();
|
||||
solutions.dedup();
|
||||
|
||||
solutions
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::solve_200_9_compressed;
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::print_stdout)]
|
||||
fn run_solver() {
|
||||
let input = b"Equihash is an asymmetric PoW based on the Generalised Birthday problem.";
|
||||
let mut nonce: [u8; 32] = [
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0,
|
||||
];
|
||||
let mut nonces = 0..=32_u32;
|
||||
let nonce_count = nonces.clone().count();
|
||||
|
||||
let solutions = solve_200_9_compressed(input, || {
|
||||
let variable_nonce = nonces.next()?;
|
||||
println!("Using variable nonce [0..4] of {}", variable_nonce);
|
||||
|
||||
let variable_nonce = variable_nonce.to_le_bytes();
|
||||
nonce[0] = variable_nonce[0];
|
||||
nonce[1] = variable_nonce[1];
|
||||
nonce[2] = variable_nonce[2];
|
||||
nonce[3] = variable_nonce[3];
|
||||
|
||||
Some(nonce)
|
||||
});
|
||||
|
||||
if solutions.is_empty() {
|
||||
// Expected solution rate is documented at:
|
||||
// https://github.com/tromp/equihash/blob/master/README.md
|
||||
panic!("Found no solutions after {nonce_count} runs, expected 1.88 solutions per run",);
|
||||
} else {
|
||||
println!("Found {} solutions:", solutions.len());
|
||||
for (sol_num, solution) in solutions.iter().enumerate() {
|
||||
println!("Validating solution {sol_num}:-\n{}", hex::encode(solution));
|
||||
crate::is_valid_solution(200, 9, input, &nonce, solution).unwrap_or_else(|error| {
|
||||
panic!(
|
||||
"unexpected invalid equihash 200, 9 solution:\n\
|
||||
error: {error:?}\n\
|
||||
input: {input:?}\n\
|
||||
nonce: {nonce:?}\n\
|
||||
solution: {solution:?}"
|
||||
)
|
||||
});
|
||||
println!("Solution {sol_num} is valid!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -114,7 +114,7 @@ impl fmt::Display for Kind {
|
|||
}
|
||||
}
|
||||
|
||||
fn initialise_state(n: u32, k: u32, digest_len: u8) -> Blake2bState {
|
||||
pub(crate) fn initialise_state(n: u32, k: u32, digest_len: u8) -> Blake2bState {
|
||||
let mut personalization: Vec<u8> = Vec::from("ZcashPoW");
|
||||
personalization.write_u32::<LittleEndian>(n).unwrap();
|
||||
personalization.write_u32::<LittleEndian>(k).unwrap();
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright (c) 2020-2022 The Zcash developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
#ifndef ZCASH_RUST_INCLUDE_RUST_BLAKE2B_H
|
||||
#define ZCASH_RUST_INCLUDE_RUST_BLAKE2B_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
struct BLAKE2bState;
|
||||
typedef struct BLAKE2bState BLAKE2bState;
|
||||
#define BLAKE2bPersonalBytes 16U
|
||||
|
||||
/// Initializes a BLAKE2b state with no key and no salt.
|
||||
///
|
||||
/// `personalization` MUST be a pointer to a 16-byte array.
|
||||
///
|
||||
/// Please free this with `blake2b_free` when you are done.
|
||||
typedef BLAKE2bState* (*blake2b_init)(
|
||||
size_t output_len,
|
||||
const unsigned char* personalization);
|
||||
|
||||
/// Clones the given BLAKE2b state.
|
||||
///
|
||||
/// Both states need to be separately freed with `blake2b_free` when you are
|
||||
/// done.
|
||||
typedef BLAKE2bState* (*blake2b_clone)(const BLAKE2bState* state);
|
||||
|
||||
/// Frees a BLAKE2b state returned by `blake2b_init`.
|
||||
typedef void (*blake2b_free)(BLAKE2bState* state);
|
||||
|
||||
/// Adds input to the hash. You can call this any number of times.
|
||||
typedef void (*blake2b_update)(
|
||||
BLAKE2bState* state,
|
||||
const unsigned char* input,
|
||||
size_t input_len);
|
||||
|
||||
/// Finalizes the `state` and stores the result in `output`.
|
||||
///
|
||||
/// `output_len` MUST be less than or equal to the value that was passed as the
|
||||
/// first parameter to `blake2b_init`.
|
||||
///
|
||||
/// This method is idempotent, and calling it multiple times will give the same
|
||||
/// result. It's also possible to call `blake2b_update` with more input in
|
||||
/// between.
|
||||
typedef void (*blake2b_finalize)(
|
||||
BLAKE2bState* state,
|
||||
unsigned char* output,
|
||||
size_t output_len);
|
||||
|
||||
#endif // ZCASH_RUST_INCLUDE_RUST_BLAKE2B_H
|
|
@ -0,0 +1,47 @@
|
|||
// Equihash solver
|
||||
// Copyright (c) 2016-2016 John Tromp, The Zcash developers
|
||||
|
||||
#ifndef ZCASH_POW_TROMP_EQUI_H
|
||||
#define ZCASH_POW_TROMP_EQUI_H
|
||||
|
||||
#include <stdbool.h> // for type bool
|
||||
#include <stdint.h> // for types uint32_t,uint64_t
|
||||
#include <string.h> // for functions memset
|
||||
#include <stdlib.h> // for function qsort
|
||||
|
||||
#include "blake2b.h"
|
||||
|
||||
typedef uint32_t u32;
|
||||
typedef unsigned char uchar;
|
||||
|
||||
// algorithm parameters, prefixed with W to reduce include file conflicts
|
||||
|
||||
#ifndef WN
|
||||
#define WN 200
|
||||
#endif
|
||||
|
||||
#ifndef WK
|
||||
#define WK 9
|
||||
#endif
|
||||
|
||||
#define NDIGITS (WK+1)
|
||||
#define DIGITBITS (WN/(NDIGITS))
|
||||
|
||||
#define PROOFSIZE (1<<WK)
|
||||
#define BASE (1<<DIGITBITS)
|
||||
#define NHASHES (2*BASE)
|
||||
#define HASHESPERBLAKE (512/WN)
|
||||
#define HASHOUT (HASHESPERBLAKE*WN/8)
|
||||
|
||||
typedef u32 proof[PROOFSIZE];
|
||||
|
||||
|
||||
enum verify_code { POW_OK, POW_DUPLICATE, POW_OUT_OF_ORDER, POW_NONZERO_XOR };
|
||||
const char *errstr[] = { "OK", "duplicate index", "indices out of order", "nonzero xor" };
|
||||
|
||||
int compu32(const void *pa, const void *pb) {
|
||||
u32 a = *(u32 *)pa, b = *(u32 *)pb;
|
||||
return a<b ? -1 : a==b ? 0 : +1;
|
||||
}
|
||||
|
||||
#endif // ZCASH_POW_TROMP_EQUI_H
|
|
@ -0,0 +1,737 @@
|
|||
// Equihash solver
|
||||
// Copyright (c) 2016 John Tromp, The Zcash developers
|
||||
|
||||
// Fix N, K, such that n = N/(k+1) is integer
|
||||
// Fix M = 2^{n+1} hashes each of length N bits,
|
||||
// H_0, ... , H_{M-1}, generated from (n+1)-bit indices.
|
||||
// Problem: find binary tree on 2^K distinct indices,
|
||||
// for which the exclusive-or of leaf hashes is all 0s.
|
||||
// Additionally, it should satisfy the Wagner conditions:
|
||||
// for each height i subtree, the exclusive-or
|
||||
// of its 2^i corresponding hashes starts with i*n 0 bits,
|
||||
// and for i>0 the leftmost leaf of its left subtree
|
||||
// is less than the leftmost leaf of its right subtree
|
||||
|
||||
// The algorithm below solves this by maintaining the trees
|
||||
// in a graph of K layers, each split into buckets
|
||||
// with buckets indexed by the first n-RESTBITS bits following
|
||||
// the i*n 0s, each bucket having 4 * 2^RESTBITS slots,
|
||||
// twice the number of subtrees expected to land there.
|
||||
|
||||
#ifndef ZCASH_POW_TROMP_EQUI_MINER_H
|
||||
#define ZCASH_POW_TROMP_EQUI_MINER_H
|
||||
|
||||
#include "equi.h"
|
||||
|
||||
// Provides htole32() on macOS and Windows
|
||||
#include "portable_endian.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
typedef uint16_t u16;
|
||||
typedef uint64_t u64;
|
||||
|
||||
#ifdef EQUIHASH_TROMP_ATOMIC
|
||||
#include <stdatomic.h>
|
||||
typedef atomic_uint au32;
|
||||
#else
|
||||
typedef u32 au32;
|
||||
#endif
|
||||
|
||||
#ifndef RESTBITS
|
||||
#define RESTBITS 8
|
||||
#endif
|
||||
|
||||
// 2_log of number of buckets
|
||||
#define BUCKBITS (DIGITBITS-RESTBITS)
|
||||
|
||||
#ifndef SAVEMEM
|
||||
#if RESTBITS == 4
|
||||
// can't save memory in such small buckets
|
||||
#define SAVEMEM 1
|
||||
#elif RESTBITS >= 8
|
||||
// take advantage of law of large numbers (sum of 2^8 random numbers)
|
||||
// this reduces (200,9) memory to under 144MB, with negligible discarding
|
||||
#define SAVEMEM 9/14
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// number of buckets
|
||||
#define NBUCKETS (1<<BUCKBITS)
|
||||
// 2_log of number of slots per bucket
|
||||
#define SLOTBITS (RESTBITS+1+1)
|
||||
#define SLOTRANGE (1<<SLOTBITS)
|
||||
#ifdef SLOTDIFF
|
||||
static const u32 SLOTMSB = 1<<(SLOTBITS-1);
|
||||
#endif
|
||||
// number of slots per bucket
|
||||
#define NSLOTS (SLOTRANGE * SAVEMEM)
|
||||
// number of per-xhash slots
|
||||
#define XFULL 16
|
||||
// SLOTBITS mask
|
||||
static const u32 SLOTMASK = SLOTRANGE-1;
|
||||
// number of possible values of xhash (rest of n) bits
|
||||
#define NRESTS (1<<RESTBITS)
|
||||
// number of blocks of hashes extracted from single 512 bit blake2b output
|
||||
#define NBLOCKS ((NHASHES+HASHESPERBLAKE-1)/HASHESPERBLAKE)
|
||||
// nothing larger found in 100000 runs
|
||||
static const u32 MAXSOLS = 8;
|
||||
|
||||
// tree node identifying its children as two different slots in
|
||||
// a bucket on previous layer with the same rest bits (x-tra hash)
|
||||
struct tree {
|
||||
u32 bid_s0_s1; // manual bitfields
|
||||
};
|
||||
typedef struct tree tree;
|
||||
|
||||
tree tree_from_idx(const u32 idx) {
|
||||
tree t;
|
||||
t.bid_s0_s1 = idx;
|
||||
return t;
|
||||
}
|
||||
tree tree_from_bid(const u32 bid, const u32 s0, const u32 s1) {
|
||||
tree t;
|
||||
#ifdef SLOTDIFF
|
||||
u32 ds10 = (s1 - s0) & SLOTMASK;
|
||||
if (ds10 & SLOTMSB) {
|
||||
bid_s0_s1 = (((bid << SLOTBITS) | s1) << (SLOTBITS-1)) | (SLOTMASK & ~ds10);
|
||||
} else {
|
||||
bid_s0_s1 = (((bid << SLOTBITS) | s0) << (SLOTBITS-1)) | (ds10 - 1);
|
||||
}
|
||||
#else
|
||||
t.bid_s0_s1 = (((bid << SLOTBITS) | s0) << SLOTBITS) | s1;
|
||||
#endif
|
||||
return t;
|
||||
}
|
||||
u32 getindex(const tree *t) {
|
||||
return t->bid_s0_s1;
|
||||
}
|
||||
u32 bucketid(const tree *t) {
|
||||
#ifdef SLOTDIFF
|
||||
return t->bid_s0_s1 >> (2 * SLOTBITS - 1);
|
||||
#else
|
||||
return t->bid_s0_s1 >> (2 * SLOTBITS);
|
||||
#endif
|
||||
}
|
||||
u32 slotid0(const tree *t) {
|
||||
#ifdef SLOTDIFF
|
||||
return (t->bid_s0_s1 >> (SLOTBITS-1)) & SLOTMASK;
|
||||
#else
|
||||
return (t->bid_s0_s1 >> SLOTBITS) & SLOTMASK;
|
||||
#endif
|
||||
}
|
||||
u32 slotid1(const tree *t) {
|
||||
#ifdef SLOTDIFF
|
||||
return (slotid0() + 1 + (t->bid_s0_s1 & (SLOTMASK>>1))) & SLOTMASK;
|
||||
#else
|
||||
return t->bid_s0_s1 & SLOTMASK;
|
||||
#endif
|
||||
}
|
||||
|
||||
union hashunit {
|
||||
u32 word;
|
||||
uchar bytes[sizeof(u32)];
|
||||
};
|
||||
typedef union hashunit hashunit;
|
||||
|
||||
#define WORDS(bits) ((bits + 31) / 32)
|
||||
#define HASHWORDS0 WORDS(WN - DIGITBITS + RESTBITS)
|
||||
#define HASHWORDS1 WORDS(WN - 2*DIGITBITS + RESTBITS)
|
||||
|
||||
struct slot0 {
|
||||
tree attr;
|
||||
hashunit hash[HASHWORDS0];
|
||||
};
|
||||
typedef struct slot0 slot0;
|
||||
|
||||
struct slot1 {
|
||||
tree attr;
|
||||
hashunit hash[HASHWORDS1];
|
||||
};
|
||||
typedef struct slot1 slot1;
|
||||
|
||||
// a bucket is NSLOTS treenodes
|
||||
typedef slot0 bucket0[NSLOTS];
|
||||
typedef slot1 bucket1[NSLOTS];
|
||||
// the N-bit hash consists of K+1 n-bit "digits"
|
||||
// each of which corresponds to a layer of NBUCKETS buckets
|
||||
typedef bucket0 digit0[NBUCKETS];
|
||||
typedef bucket1 digit1[NBUCKETS];
|
||||
|
||||
// size (in bytes) of hash in round 0 <= r < WK
|
||||
u32 hashsize(const u32 r) {
|
||||
const u32 hashbits = WN - (r+1) * DIGITBITS + RESTBITS;
|
||||
return (hashbits + 7) / 8;
|
||||
}
|
||||
|
||||
u32 hashwords(u32 bytes) {
|
||||
return (bytes + 3) / 4;
|
||||
}
|
||||
|
||||
// manages hash and tree data
|
||||
struct htalloc {
|
||||
u32 *heap0;
|
||||
u32 *heap1;
|
||||
bucket0 *trees0[(WK+1)/2];
|
||||
bucket1 *trees1[WK/2];
|
||||
u32 alloced;
|
||||
};
|
||||
typedef struct htalloc htalloc;
|
||||
htalloc htalloc_new() {
|
||||
htalloc hta;
|
||||
hta.alloced = 0;
|
||||
return hta;
|
||||
}
|
||||
void *htalloc_alloc(htalloc *hta, const u32 n, const u32 sz);
|
||||
void alloctrees(htalloc *hta) {
|
||||
// optimize xenoncat's fixed memory layout, avoiding any waste
|
||||
// digit trees hashes trees hashes
|
||||
// 0 0 A A A A A A . . . . . .
|
||||
// 1 0 A A A A A A 1 B B B B B
|
||||
// 2 0 2 C C C C C 1 B B B B B
|
||||
// 3 0 2 C C C C C 1 3 D D D D
|
||||
// 4 0 2 4 E E E E 1 3 D D D D
|
||||
// 5 0 2 4 E E E E 1 3 5 F F F
|
||||
// 6 0 2 4 6 . G G 1 3 5 F F F
|
||||
// 7 0 2 4 6 . G G 1 3 5 7 H H
|
||||
// 8 0 2 4 6 8 . I 1 3 5 7 H H
|
||||
assert(DIGITBITS >= 16); // ensures hashes shorten by 1 unit every 2 digits
|
||||
hta->heap0 = (u32 *)htalloc_alloc(hta, 1, sizeof(digit0));
|
||||
hta->heap1 = (u32 *)htalloc_alloc(hta, 1, sizeof(digit1));
|
||||
for (int r=0; r<WK; r++)
|
||||
if ((r&1) == 0)
|
||||
hta->trees0[r/2] = (bucket0 *)(hta->heap0 + r/2);
|
||||
else
|
||||
hta->trees1[r/2] = (bucket1 *)(hta->heap1 + r/2);
|
||||
}
|
||||
void dealloctrees(htalloc *hta) {
|
||||
if (hta == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
free(hta->heap0);
|
||||
free(hta->heap1);
|
||||
// Avoid use-after-free and double-free
|
||||
hta->heap0 = NULL;
|
||||
hta->heap1 = NULL;
|
||||
|
||||
for (int r=0; r<WK; r++)
|
||||
if ((r&1) == 0)
|
||||
hta->trees0[r/2] = NULL;
|
||||
else
|
||||
hta->trees1[r/2] = NULL;
|
||||
hta->alloced = 0;
|
||||
}
|
||||
void *htalloc_alloc(htalloc *hta, const u32 n, const u32 sz) {
|
||||
void *mem = calloc(n, sz);
|
||||
assert(mem);
|
||||
hta->alloced += n * sz;
|
||||
return mem;
|
||||
}
|
||||
|
||||
typedef au32 bsizes[NBUCKETS];
|
||||
|
||||
u32 minu32(const u32 a, const u32 b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
struct equi {
|
||||
BLAKE2bState* blake_ctx;
|
||||
blake2b_clone blake2b_clone;
|
||||
blake2b_free blake2b_free;
|
||||
blake2b_update blake2b_update;
|
||||
blake2b_finalize blake2b_finalize;
|
||||
htalloc hta;
|
||||
bsizes *nslots; // PUT IN BUCKET STRUCT
|
||||
proof *sols;
|
||||
au32 nsols;
|
||||
u32 xfull;
|
||||
u32 hfull;
|
||||
u32 bfull;
|
||||
};
|
||||
typedef struct equi equi;
|
||||
void equi_clearslots(equi *eq);
|
||||
equi *equi_new(
|
||||
blake2b_clone blake2b_clone,
|
||||
blake2b_free blake2b_free,
|
||||
blake2b_update blake2b_update,
|
||||
blake2b_finalize blake2b_finalize
|
||||
) {
|
||||
assert(sizeof(hashunit) == 4);
|
||||
equi *eq = malloc(sizeof(equi));
|
||||
eq->blake2b_clone = blake2b_clone;
|
||||
eq->blake2b_free = blake2b_free;
|
||||
eq->blake2b_update = blake2b_update;
|
||||
eq->blake2b_finalize = blake2b_finalize;
|
||||
|
||||
alloctrees(&eq->hta);
|
||||
eq->nslots = (bsizes *)htalloc_alloc(&eq->hta, 2 * NBUCKETS, sizeof(au32));
|
||||
eq->sols = (proof *)htalloc_alloc(&eq->hta, MAXSOLS, sizeof(proof));
|
||||
|
||||
// C malloc() does not guarantee zero-initialized memory (but calloc() does)
|
||||
eq->blake_ctx = NULL;
|
||||
eq->nsols = 0;
|
||||
equi_clearslots(eq);
|
||||
|
||||
return eq;
|
||||
}
|
||||
void equi_free(equi *eq) {
|
||||
if (eq == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
dealloctrees(&eq->hta);
|
||||
|
||||
free(eq->nslots);
|
||||
free(eq->sols);
|
||||
eq->blake2b_free(eq->blake_ctx);
|
||||
// Avoid use-after-free and double-free
|
||||
eq->nslots = NULL;
|
||||
eq->sols = NULL;
|
||||
eq->blake_ctx = NULL;
|
||||
|
||||
free(eq);
|
||||
}
|
||||
void equi_setstate(equi *eq, const BLAKE2bState *ctx) {
|
||||
if (eq->blake_ctx) {
|
||||
eq->blake2b_free(eq->blake_ctx);
|
||||
}
|
||||
|
||||
eq->blake_ctx = eq->blake2b_clone(ctx);
|
||||
memset(eq->nslots, 0, NBUCKETS * sizeof(au32)); // only nslots[0] needs zeroing
|
||||
equi_clearslots(eq);
|
||||
eq->nsols = 0;
|
||||
}
|
||||
void equi_clearslots(equi *eq) {
|
||||
eq->xfull = eq->bfull = eq->hfull = 0;
|
||||
}
|
||||
u32 getslot(equi *eq, const u32 r, const u32 bucketi) {
|
||||
#ifdef EQUIHASH_TROMP_ATOMIC
|
||||
return std::atomic_fetch_add_explicit(&eq->nslots[r&1][bucketi], 1U, std::memory_order_relaxed);
|
||||
#else
|
||||
return eq->nslots[r&1][bucketi]++;
|
||||
#endif
|
||||
}
|
||||
u32 getnslots(equi *eq, const u32 r, const u32 bid) { // SHOULD BE METHOD IN BUCKET STRUCT
|
||||
au32 *nslot = &eq->nslots[r&1][bid];
|
||||
const u32 n = minu32(*nslot, NSLOTS);
|
||||
*nslot = 0;
|
||||
return n;
|
||||
}
|
||||
void orderindices(u32 *indices, u32 size) {
|
||||
if (indices[0] > indices[size]) {
|
||||
for (u32 i=0; i < size; i++) {
|
||||
const u32 tmp = indices[i];
|
||||
indices[i] = indices[size+i];
|
||||
indices[size+i] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
void listindices1(equi *eq, u32 r, const tree t, u32 *indices);
|
||||
void listindices0(equi *eq, u32 r, const tree t, u32 *indices) {
|
||||
if (r == 0) {
|
||||
*indices = getindex(&t);
|
||||
return;
|
||||
}
|
||||
const bucket1 *buck = &eq->hta.trees1[--r/2][bucketid(&t)];
|
||||
const u32 size = 1 << r;
|
||||
u32 *indices1 = indices + size;
|
||||
listindices1(eq, r, (*buck)[slotid0(&t)].attr, indices);
|
||||
listindices1(eq, r, (*buck)[slotid1(&t)].attr, indices1);
|
||||
orderindices(indices, size);
|
||||
}
|
||||
void listindices1(equi *eq, u32 r, const tree t, u32 *indices) {
|
||||
const bucket0 *buck = &eq->hta.trees0[--r/2][bucketid(&t)];
|
||||
const u32 size = 1 << r;
|
||||
u32 *indices1 = indices + size;
|
||||
listindices0(eq, r, (*buck)[slotid0(&t)].attr, indices);
|
||||
listindices0(eq, r, (*buck)[slotid1(&t)].attr, indices1);
|
||||
orderindices(indices, size);
|
||||
}
|
||||
void candidate(equi *eq, const tree t) {
|
||||
proof prf;
|
||||
listindices1(eq, WK, t, prf); // assume WK odd
|
||||
qsort(prf, PROOFSIZE, sizeof(u32), &compu32);
|
||||
for (u32 i=1; i<PROOFSIZE; i++)
|
||||
if (prf[i] <= prf[i-1]) {
|
||||
/*
|
||||
printf(
|
||||
"failed dup indexes check: wanted: proof[%d] > proof[%d], actual: %d <= %d\n",
|
||||
i, i-1, prf[i], prf[i-1]
|
||||
);
|
||||
*/
|
||||
return;
|
||||
}
|
||||
#ifdef EQUIHASH_TROMP_ATOMIC
|
||||
u32 soli = std::atomic_fetch_add_explicit(&eq->nsols, 1U, std::memory_order_relaxed);
|
||||
#else
|
||||
u32 soli = eq->nsols++;
|
||||
#endif
|
||||
if (soli < MAXSOLS)
|
||||
listindices1(eq, WK, t, eq->sols[soli]); // assume WK odd
|
||||
}
|
||||
#ifdef EQUIHASH_SHOW_BUCKET_SIZES
|
||||
void showbsizes(equi *eq, u32 r) {
|
||||
#if defined(HIST) || defined(SPARK) || defined(LOGSPARK)
|
||||
u32 binsizes[65];
|
||||
memset(binsizes, 0, 65 * sizeof(u32));
|
||||
for (u32 bucketid = 0; bucketid < NBUCKETS; bucketid++) {
|
||||
u32 bsize = minu32(eq->nslots[r&1][bucketid], NSLOTS) >> (SLOTBITS-6);
|
||||
binsizes[bsize]++;
|
||||
}
|
||||
for (u32 i=0; i < 65; i++) {
|
||||
#ifdef HIST
|
||||
// printf(" %d:%d", i, binsizes[i]);
|
||||
#else
|
||||
#ifdef SPARK
|
||||
u32 sparks = binsizes[i] / SPARKSCALE;
|
||||
#else
|
||||
u32 sparks = 0;
|
||||
for (u32 bs = binsizes[i]; bs; bs >>= 1) sparks++;
|
||||
sparks = sparks * 7 / SPARKSCALE;
|
||||
#endif
|
||||
// printf("\342\226%c", '\201' + sparks);
|
||||
#endif
|
||||
}
|
||||
// printf("\n");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
struct htlayout {
|
||||
htalloc hta;
|
||||
u32 prevhashunits;
|
||||
u32 nexthashunits;
|
||||
u32 dunits;
|
||||
u32 prevbo;
|
||||
u32 nextbo;
|
||||
};
|
||||
typedef struct htlayout htlayout;
|
||||
|
||||
htlayout htlayout_new(equi *eq, u32 r) {
|
||||
htlayout htl;
|
||||
htl.hta = eq->hta;
|
||||
htl.prevhashunits = 0;
|
||||
htl.dunits = 0;
|
||||
u32 nexthashbytes = hashsize(r);
|
||||
htl.nexthashunits = hashwords(nexthashbytes);
|
||||
htl.prevbo = 0;
|
||||
htl.nextbo = htl.nexthashunits * sizeof(hashunit) - nexthashbytes; // 0-3
|
||||
if (r) {
|
||||
u32 prevhashbytes = hashsize(r-1);
|
||||
htl.prevhashunits = hashwords(prevhashbytes);
|
||||
htl.prevbo = htl.prevhashunits * sizeof(hashunit) - prevhashbytes; // 0-3
|
||||
htl.dunits = htl.prevhashunits - htl.nexthashunits;
|
||||
}
|
||||
return htl;
|
||||
}
|
||||
u32 getxhash0(const htlayout *htl, const slot0* pslot) {
|
||||
#if WN == 200 && RESTBITS == 4
|
||||
return pslot->hash->bytes[htl->prevbo] >> 4;
|
||||
#elif WN == 200 && RESTBITS == 8
|
||||
return (pslot->hash->bytes[htl->prevbo] & 0xf) << 4 | pslot->hash->bytes[htl->prevbo+1] >> 4;
|
||||
#elif WN == 200 && RESTBITS == 9
|
||||
return (pslot->hash->bytes[htl->prevbo] & 0x1f) << 4 | pslot->hash->bytes[htl->prevbo+1] >> 4;
|
||||
#elif WN == 144 && RESTBITS == 4
|
||||
return pslot->hash->bytes[htl->prevbo] & 0xf;
|
||||
#else
|
||||
#error non implemented
|
||||
#endif
|
||||
}
|
||||
u32 getxhash1(const htlayout *htl, const slot1* pslot) {
|
||||
#if WN == 200 && RESTBITS == 4
|
||||
return pslot->hash->bytes[htl->prevbo] & 0xf;
|
||||
#elif WN == 200 && RESTBITS == 8
|
||||
return pslot->hash->bytes[htl->prevbo];
|
||||
#elif WN == 200 && RESTBITS == 9
|
||||
return (pslot->hash->bytes[htl->prevbo]&1) << 8 | pslot->hash->bytes[htl->prevbo+1];
|
||||
#elif WN == 144 && RESTBITS == 4
|
||||
return pslot->hash->bytes[htl->prevbo] & 0xf;
|
||||
#else
|
||||
#error non implemented
|
||||
#endif
|
||||
}
|
||||
bool htlayout_equal(const htlayout *htl, const hashunit *hash0, const hashunit *hash1) {
|
||||
return hash0[htl->prevhashunits-1].word == hash1[htl->prevhashunits-1].word;
|
||||
}
|
||||
|
||||
#if RESTBITS <= 6
|
||||
typedef uchar xslot;
|
||||
#else
|
||||
typedef u16 xslot;
|
||||
#endif
|
||||
struct collisiondata {
|
||||
#ifdef XBITMAP
|
||||
#if NSLOTS > 64
|
||||
#error cant use XBITMAP with more than 64 slots
|
||||
#endif
|
||||
u64 xhashmap[NRESTS];
|
||||
u64 xmap;
|
||||
#else
|
||||
xslot nxhashslots[NRESTS];
|
||||
xslot xhashslots[NRESTS][XFULL];
|
||||
xslot *xx;
|
||||
u32 n0;
|
||||
u32 n1;
|
||||
#endif
|
||||
u32 s0;
|
||||
};
|
||||
typedef struct collisiondata collisiondata;
|
||||
|
||||
void collisiondata_clear(collisiondata *cd) {
|
||||
#ifdef XBITMAP
|
||||
memset(cd->xhashmap, 0, NRESTS * sizeof(u64));
|
||||
#else
|
||||
memset(cd->nxhashslots, 0, NRESTS * sizeof(xslot));
|
||||
#endif
|
||||
}
|
||||
bool addslot(collisiondata *cd, u32 s1, u32 xh) {
|
||||
#ifdef XBITMAP
|
||||
xmap = xhashmap[xh];
|
||||
xhashmap[xh] |= (u64)1 << s1;
|
||||
s0 = -1;
|
||||
return true;
|
||||
#else
|
||||
cd->n1 = (u32)cd->nxhashslots[xh]++;
|
||||
if (cd->n1 >= XFULL)
|
||||
return false;
|
||||
cd->xx = cd->xhashslots[xh];
|
||||
cd->xx[cd->n1] = s1;
|
||||
cd->n0 = 0;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
bool nextcollision(const collisiondata *cd) {
|
||||
#ifdef XBITMAP
|
||||
return cd->xmap != 0;
|
||||
#else
|
||||
return cd->n0 < cd->n1;
|
||||
#endif
|
||||
}
|
||||
u32 slot(collisiondata *cd) {
|
||||
#ifdef XBITMAP
|
||||
const u32 ffs = __builtin_ffsll(cd->xmap);
|
||||
s0 += ffs; cd->xmap >>= ffs;
|
||||
return s0;
|
||||
#else
|
||||
return (u32)cd->xx[cd->n0++];
|
||||
#endif
|
||||
}
|
||||
|
||||
void equi_digit0(equi *eq, const u32 id) {
|
||||
uchar hash[HASHOUT];
|
||||
BLAKE2bState* state;
|
||||
htlayout htl = htlayout_new(eq, 0);
|
||||
const u32 hashbytes = hashsize(0);
|
||||
for (u32 block = id; block < NBLOCKS; block++) {
|
||||
state = eq->blake2b_clone(eq->blake_ctx);
|
||||
u32 leb = htole32(block);
|
||||
eq->blake2b_update(state, (uchar *)&leb, sizeof(u32));
|
||||
eq->blake2b_finalize(state, hash, HASHOUT);
|
||||
eq->blake2b_free(state);
|
||||
// Avoid use-after-free and double-free
|
||||
state = NULL;
|
||||
|
||||
for (u32 i = 0; i<HASHESPERBLAKE; i++) {
|
||||
const uchar *ph = hash + i * WN/8;
|
||||
#if BUCKBITS == 16 && RESTBITS == 4
|
||||
const u32 bucketid = ((u32)ph[0] << 8) | ph[1];
|
||||
#elif BUCKBITS == 12 && RESTBITS == 8
|
||||
const u32 bucketid = ((u32)ph[0] << 4) | ph[1] >> 4;
|
||||
#elif BUCKBITS == 11 && RESTBITS == 9
|
||||
const u32 bucketid = ((u32)ph[0] << 3) | ph[1] >> 5;
|
||||
#elif BUCKBITS == 20 && RESTBITS == 4
|
||||
const u32 bucketid = ((((u32)ph[0] << 8) | ph[1]) << 4) | ph[2] >> 4;
|
||||
#elif BUCKBITS == 12 && RESTBITS == 4
|
||||
const u32 bucketid = ((u32)ph[0] << 4) | ph[1] >> 4;
|
||||
const u32 xhash = ph[1] & 0xf;
|
||||
#else
|
||||
#error not implemented
|
||||
#endif
|
||||
const u32 slot = getslot(eq, 0, bucketid);
|
||||
if (slot >= NSLOTS) {
|
||||
eq->bfull++;
|
||||
continue;
|
||||
}
|
||||
slot0 *s = &eq->hta.trees0[0][bucketid][slot];
|
||||
s->attr = tree_from_idx(block * HASHESPERBLAKE + i);
|
||||
memcpy(s->hash->bytes+htl.nextbo, ph+WN/8-hashbytes, hashbytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void equi_digitodd(equi *eq, const u32 r, const u32 id) {
|
||||
htlayout htl = htlayout_new(eq, r);
|
||||
collisiondata cd;
|
||||
for (u32 bucketid=id; bucketid < NBUCKETS; bucketid++) {
|
||||
collisiondata_clear(&cd);
|
||||
slot0 *buck = htl.hta.trees0[(r-1)/2][bucketid]; // optimize by updating previous buck?!
|
||||
u32 bsize = getnslots(eq, r-1, bucketid); // optimize by putting bucketsize with block?!
|
||||
for (u32 s1 = 0; s1 < bsize; s1++) {
|
||||
const slot0 *pslot1 = buck + s1; // optimize by updating previous pslot1?!
|
||||
if (!addslot(&cd, s1, getxhash0(&htl, pslot1))) {
|
||||
eq->xfull++;
|
||||
continue;
|
||||
}
|
||||
for (; nextcollision(&cd); ) {
|
||||
const u32 s0 = slot(&cd);
|
||||
const slot0 *pslot0 = buck + s0;
|
||||
if (htlayout_equal(&htl, pslot0->hash, pslot1->hash)) {
|
||||
eq->hfull++;
|
||||
continue;
|
||||
}
|
||||
u32 xorbucketid;
|
||||
const uchar *bytes0 = pslot0->hash->bytes, *bytes1 = pslot1->hash->bytes;
|
||||
#if WN == 200 && BUCKBITS == 12 && RESTBITS == 8
|
||||
xorbucketid = (((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) & 0xf) << 8)
|
||||
| (bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2]);
|
||||
#elif WN == 200 && BUCKBITS == 11 && RESTBITS == 9
|
||||
xorbucketid = (((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) & 0xf) << 7)
|
||||
| (bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2]) >> 1;
|
||||
#elif WN == 144 && BUCKBITS == 20 && RESTBITS == 4
|
||||
xorbucketid = ((((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) << 8)
|
||||
| (bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2])) << 4)
|
||||
| (bytes0[htl.prevbo+3] ^ bytes1[htl.prevbo+3]) >> 4;
|
||||
#elif WN == 96 && BUCKBITS == 12 && RESTBITS == 4
|
||||
xorbucketid = ((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) << 4)
|
||||
| (bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2]) >> 4;
|
||||
#else
|
||||
#error not implemented
|
||||
#endif
|
||||
const u32 xorslot = getslot(eq, r, xorbucketid);
|
||||
if (xorslot >= NSLOTS) {
|
||||
eq->bfull++;
|
||||
continue;
|
||||
}
|
||||
slot1 *xs = &htl.hta.trees1[r/2][xorbucketid][xorslot];
|
||||
xs->attr = tree_from_bid(bucketid, s0, s1);
|
||||
for (u32 i=htl.dunits; i < htl.prevhashunits; i++)
|
||||
xs->hash[i-htl.dunits].word = pslot0->hash[i].word ^ pslot1->hash[i].word;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void equi_digiteven(equi *eq, const u32 r, const u32 id) {
|
||||
htlayout htl = htlayout_new(eq, r);
|
||||
collisiondata cd;
|
||||
for (u32 bucketid=id; bucketid < NBUCKETS; bucketid++) {
|
||||
collisiondata_clear(&cd);
|
||||
slot1 *buck = htl.hta.trees1[(r-1)/2][bucketid]; // OPTIMIZE BY UPDATING PREVIOUS
|
||||
u32 bsize = getnslots(eq, r-1, bucketid);
|
||||
for (u32 s1 = 0; s1 < bsize; s1++) {
|
||||
const slot1 *pslot1 = buck + s1; // OPTIMIZE BY UPDATING PREVIOUS
|
||||
if (!addslot(&cd, s1, getxhash1(&htl, pslot1))) {
|
||||
eq->xfull++;
|
||||
continue;
|
||||
}
|
||||
for (; nextcollision(&cd); ) {
|
||||
const u32 s0 = slot(&cd);
|
||||
const slot1 *pslot0 = buck + s0;
|
||||
if (htlayout_equal(&htl, pslot0->hash, pslot1->hash)) {
|
||||
eq->hfull++;
|
||||
continue;
|
||||
}
|
||||
u32 xorbucketid;
|
||||
const uchar *bytes0 = pslot0->hash->bytes, *bytes1 = pslot1->hash->bytes;
|
||||
#if WN == 200 && BUCKBITS == 12 && RESTBITS == 8
|
||||
xorbucketid = ((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) << 4)
|
||||
| (bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2]) >> 4;
|
||||
#elif WN == 200 && BUCKBITS == 11 && RESTBITS == 9
|
||||
xorbucketid = ((u32)(bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2]) << 3)
|
||||
| (bytes0[htl.prevbo+3] ^ bytes1[htl.prevbo+3]) >> 5;
|
||||
#elif WN == 144 && BUCKBITS == 20 && RESTBITS == 4
|
||||
xorbucketid = ((((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) << 8)
|
||||
| (bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2])) << 4)
|
||||
| (bytes0[htl.prevbo+3] ^ bytes1[htl.prevbo+3]) >> 4;
|
||||
#elif WN == 96 && BUCKBITS == 12 && RESTBITS == 4
|
||||
xorbucketid = ((u32)(bytes0[htl.prevbo+1] ^ bytes1[htl.prevbo+1]) << 4)
|
||||
| (bytes0[htl.prevbo+2] ^ bytes1[htl.prevbo+2]) >> 4;
|
||||
#else
|
||||
#error not implemented
|
||||
#endif
|
||||
const u32 xorslot = getslot(eq, r, xorbucketid);
|
||||
if (xorslot >= NSLOTS) {
|
||||
eq->bfull++;
|
||||
continue;
|
||||
}
|
||||
slot0 *xs = &htl.hta.trees0[r/2][xorbucketid][xorslot];
|
||||
xs->attr = tree_from_bid(bucketid, s0, s1);
|
||||
for (u32 i=htl.dunits; i < htl.prevhashunits; i++)
|
||||
xs->hash[i-htl.dunits].word = pslot0->hash[i].word ^ pslot1->hash[i].word;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void equi_digitK(equi *eq, const u32 id) {
|
||||
collisiondata cd;
|
||||
htlayout htl = htlayout_new(eq, WK);
|
||||
u32 nc = 0;
|
||||
for (u32 bucketid = id; bucketid < NBUCKETS; bucketid++) {
|
||||
collisiondata_clear(&cd);
|
||||
slot0 *buck = htl.hta.trees0[(WK-1)/2][bucketid];
|
||||
u32 bsize = getnslots(eq, WK-1, bucketid);
|
||||
for (u32 s1 = 0; s1 < bsize; s1++) {
|
||||
const slot0 *pslot1 = buck + s1;
|
||||
if (!addslot(&cd, s1, getxhash0(&htl, pslot1))) // assume WK odd
|
||||
continue;
|
||||
for (; nextcollision(&cd); ) {
|
||||
const u32 s0 = slot(&cd);
|
||||
if (htlayout_equal(&htl, buck[s0].hash, pslot1->hash))
|
||||
nc++, candidate(eq, tree_from_bid(bucketid, s0, s1));
|
||||
}
|
||||
}
|
||||
}
|
||||
//printf(" %d candidates\n", nc);
|
||||
}
|
||||
|
||||
size_t equi_nsols(const equi *eq) {
|
||||
return eq->nsols;
|
||||
}
|
||||
proof *equi_sols(const equi *eq) {
|
||||
return eq->sols;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
u32 id;
|
||||
equi *eq;
|
||||
} thread_ctx;
|
||||
|
||||
void *worker(void *vp) {
|
||||
thread_ctx *tp = (thread_ctx *)vp;
|
||||
equi *eq = tp->eq;
|
||||
|
||||
// if (tp->id == 0)
|
||||
// printf("Digit 0\n");
|
||||
if (tp->id == 0) {
|
||||
equi_clearslots(eq);
|
||||
}
|
||||
equi_digit0(eq, tp->id);
|
||||
if (tp->id == 0) {
|
||||
equi_clearslots(eq);
|
||||
#ifdef EQUIHASH_SHOW_BUCKET_SIZES
|
||||
showbsizes(eq, 0);
|
||||
#endif
|
||||
}
|
||||
for (u32 r = 1; r < WK; r++) {
|
||||
// if (tp->id == 0)
|
||||
// printf("Digit %d", r);
|
||||
r&1 ? equi_digitodd(eq, r, tp->id) : equi_digiteven(eq, r, tp->id);
|
||||
if (tp->id == 0) {
|
||||
// printf(" x%d b%d h%d\n", eq->xfull, eq->bfull, eq->hfull);
|
||||
equi_clearslots(eq);
|
||||
#ifdef EQUIHASH_SHOW_BUCKET_SIZES
|
||||
showbsizes(eq, r);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
// if (tp->id == 0)
|
||||
// printf("Digit %d\n", WK);
|
||||
equi_digitK(eq, tp->id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // ZCASH_POW_TROMP_EQUI_MINER_H
|
|
@ -0,0 +1,130 @@
|
|||
//
|
||||
// endian.h
|
||||
//
|
||||
// https://gist.github.com/panzi/6856583
|
||||
//
|
||||
// I, Mathias Panzenböck, place this file hereby into the public domain. Use
|
||||
// it at your own risk for whatever you like. In case there are
|
||||
// jurisdictions that don't support putting things in the public domain you
|
||||
// can also consider it to be "dual licensed" under the BSD, MIT and Apache
|
||||
// licenses, if you want to. This code is trivial anyway. Consider it an
|
||||
// example on how to get the endian conversion functions on different
|
||||
// platforms.
|
||||
|
||||
// Downloaded from https://raw.githubusercontent.com/mikepb/endian.h/master/endian.h
|
||||
// on 12 January 2024.
|
||||
|
||||
#ifndef PORTABLE_ENDIAN_H__
|
||||
#define PORTABLE_ENDIAN_H__
|
||||
|
||||
#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__)
|
||||
|
||||
# define __WINDOWS__
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(__CYGWIN__)
|
||||
|
||||
# include <endian.h>
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
# include <libkern/OSByteOrder.h>
|
||||
|
||||
# define htobe16(x) OSSwapHostToBigInt16(x)
|
||||
# define htole16(x) OSSwapHostToLittleInt16(x)
|
||||
# define be16toh(x) OSSwapBigToHostInt16(x)
|
||||
# define le16toh(x) OSSwapLittleToHostInt16(x)
|
||||
|
||||
# define htobe32(x) OSSwapHostToBigInt32(x)
|
||||
# define htole32(x) OSSwapHostToLittleInt32(x)
|
||||
# define be32toh(x) OSSwapBigToHostInt32(x)
|
||||
# define le32toh(x) OSSwapLittleToHostInt32(x)
|
||||
|
||||
# define htobe64(x) OSSwapHostToBigInt64(x)
|
||||
# define htole64(x) OSSwapHostToLittleInt64(x)
|
||||
# define be64toh(x) OSSwapBigToHostInt64(x)
|
||||
# define le64toh(x) OSSwapLittleToHostInt64(x)
|
||||
|
||||
# define __BYTE_ORDER BYTE_ORDER
|
||||
# define __BIG_ENDIAN BIG_ENDIAN
|
||||
# define __LITTLE_ENDIAN LITTLE_ENDIAN
|
||||
# define __PDP_ENDIAN PDP_ENDIAN
|
||||
|
||||
#elif defined(__OpenBSD__)
|
||||
|
||||
# include <sys/endian.h>
|
||||
|
||||
#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
|
||||
# include <sys/endian.h>
|
||||
|
||||
# define be16toh(x) betoh16(x)
|
||||
# define le16toh(x) letoh16(x)
|
||||
|
||||
# define be32toh(x) betoh32(x)
|
||||
# define le32toh(x) letoh32(x)
|
||||
|
||||
# define be64toh(x) betoh64(x)
|
||||
# define le64toh(x) letoh64(x)
|
||||
|
||||
#elif defined(__WINDOWS__)
|
||||
|
||||
# include <winsock2.h>
|
||||
|
||||
// Not available in librustzcash CI
|
||||
//# include <sys/param.h>
|
||||
|
||||
# if BYTE_ORDER == LITTLE_ENDIAN
|
||||
|
||||
# define htobe16(x) htons(x)
|
||||
# define htole16(x) (x)
|
||||
# define be16toh(x) ntohs(x)
|
||||
# define le16toh(x) (x)
|
||||
|
||||
# define htobe32(x) htonl(x)
|
||||
# define htole32(x) (x)
|
||||
# define be32toh(x) ntohl(x)
|
||||
# define le32toh(x) (x)
|
||||
|
||||
# define htobe64(x) htonll(x)
|
||||
# define htole64(x) (x)
|
||||
# define be64toh(x) ntohll(x)
|
||||
# define le64toh(x) (x)
|
||||
|
||||
# elif BYTE_ORDER == BIG_ENDIAN
|
||||
|
||||
/* that would be xbox 360 */
|
||||
# define htobe16(x) (x)
|
||||
# define htole16(x) __builtin_bswap16(x)
|
||||
# define be16toh(x) (x)
|
||||
# define le16toh(x) __builtin_bswap16(x)
|
||||
|
||||
# define htobe32(x) (x)
|
||||
# define htole32(x) __builtin_bswap32(x)
|
||||
# define be32toh(x) (x)
|
||||
# define le32toh(x) __builtin_bswap32(x)
|
||||
|
||||
# define htobe64(x) (x)
|
||||
# define htole64(x) __builtin_bswap64(x)
|
||||
# define be64toh(x) (x)
|
||||
# define le64toh(x) __builtin_bswap64(x)
|
||||
|
||||
# else
|
||||
|
||||
# error byte order not supported
|
||||
|
||||
# endif
|
||||
|
||||
# define __BYTE_ORDER BYTE_ORDER
|
||||
# define __BIG_ENDIAN BIG_ENDIAN
|
||||
# define __LITTLE_ENDIAN LITTLE_ENDIAN
|
||||
# define __PDP_ENDIAN PDP_ENDIAN
|
||||
|
||||
#else
|
||||
|
||||
# error platform not supported
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,51 @@
|
|||
# Configuration file for cargo-deny
|
||||
|
||||
[graph]
|
||||
targets = [
|
||||
# Targets used by zcashd
|
||||
{ triple = "aarch64-unknown-linux-gnu" },
|
||||
{ triple = "x86_64-apple-darwin" },
|
||||
{ triple = "x86_64-pc-windows-gnu" },
|
||||
{ triple = "x86_64-unknown-freebsd" },
|
||||
{ triple = "x86_64-unknown-linux-gnu" },
|
||||
# Targets used by zcash-android-wallet-sdk
|
||||
{ triple = "aarch64-linux-android" },
|
||||
{ triple = "armv7-linux-androideabi" },
|
||||
{ triple = "i686-linux-android" },
|
||||
{ triple = "x86_64-linux-android" },
|
||||
# Targets used by zcash-swift-wallet-sdk
|
||||
{ triple = "aarch64-apple-darwin" },
|
||||
{ triple = "aarch64-apple-ios" },
|
||||
{ triple = "aarch64-apple-ios-sim" },
|
||||
{ triple = "x86_64-apple-darwin" },
|
||||
{ triple = "x86_64-apple-ios" },
|
||||
]
|
||||
all-features = true
|
||||
exclude-dev = true
|
||||
|
||||
[licenses]
|
||||
version = 2
|
||||
allow = [
|
||||
"Apache-2.0",
|
||||
"MIT",
|
||||
]
|
||||
exceptions = [
|
||||
{ name = "arrayref", allow = ["BSD-2-Clause"] },
|
||||
{ name = "matchit", allow = ["BSD-3-Clause"] },
|
||||
{ name = "minreq", allow = ["ISC"] },
|
||||
{ name = "ring", allow = ["LicenseRef-ring"] },
|
||||
{ name = "rustls-webpki", allow = ["ISC"] },
|
||||
{ name = "secp256k1", allow = ["CC0-1.0"] },
|
||||
{ name = "secp256k1-sys", allow = ["CC0-1.0"] },
|
||||
{ name = "subtle", allow = ["BSD-3-Clause"] },
|
||||
{ name = "unicode-ident", allow = ["Unicode-DFS-2016"] },
|
||||
{ name = "untrusted", allow = ["ISC"] },
|
||||
{ name = "webpki-roots", allow = ["MPL-2.0"] },
|
||||
]
|
||||
|
||||
[[licenses.clarify]]
|
||||
name = "ring"
|
||||
expression = "LicenseRef-ring"
|
||||
license-files = [
|
||||
{ path = "LICENSE", hash = 0xbd0eed23 },
|
||||
]
|
|
@ -0,0 +1,238 @@
|
|||
|
||||
# cargo-vet audits file
|
||||
|
||||
[criteria.crypto-reviewed]
|
||||
description = "The cryptographic code in this crate has been reviewed for correctness by a member of a designated set of cryptography experts within the project."
|
||||
|
||||
[criteria.license-reviewed]
|
||||
description = "The license of this crate has been reviewed for compatibility with its usage in this repository."
|
||||
|
||||
[audits]
|
||||
|
||||
[[trusted.equihash]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 6289 # str4d
|
||||
start = "2020-06-26"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.f4jumble]]
|
||||
criteria = ["safe-to-deploy", "crypto-reviewed"]
|
||||
user-id = 6289 # str4d
|
||||
start = "2021-09-22"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.halo2_gadgets]]
|
||||
criteria = ["safe-to-deploy", "crypto-reviewed"]
|
||||
user-id = 1244 # ebfull
|
||||
start = "2022-05-10"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.halo2_legacy_pdqsort]]
|
||||
criteria = ["safe-to-deploy", "crypto-reviewed"]
|
||||
user-id = 199950 # Daira Emma Hopwood (daira)
|
||||
start = "2023-02-24"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.halo2_proofs]]
|
||||
criteria = ["safe-to-deploy", "crypto-reviewed"]
|
||||
user-id = 1244 # ebfull
|
||||
start = "2022-05-10"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.incrementalmerkletree]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 6289 # str4d
|
||||
start = "2021-12-17"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.incrementalmerkletree]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 1244 # ebfull
|
||||
start = "2021-06-24"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.incrementalmerkletree]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 169181 # Kris Nuttycombe (nuttycom)
|
||||
start = "2023-02-28"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.orchard]]
|
||||
criteria = ["safe-to-deploy", "crypto-reviewed", "license-reviewed"]
|
||||
user-id = 6289 # str4d
|
||||
start = "2021-01-07"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.orchard]]
|
||||
criteria = ["safe-to-deploy", "crypto-reviewed", "license-reviewed"]
|
||||
user-id = 1244 # ebfull
|
||||
start = "2022-10-19"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.sapling-crypto]]
|
||||
criteria = ["safe-to-deploy", "crypto-reviewed"]
|
||||
user-id = 6289 # str4d
|
||||
start = "2024-01-26"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.shardtree]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 169181 # Kris Nuttycombe (nuttycom)
|
||||
start = "2022-12-15"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.windows-sys]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 64539 # Kenny Kerr (kennykerr)
|
||||
start = "2021-11-15"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.windows-targets]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 64539 # Kenny Kerr (kennykerr)
|
||||
start = "2022-09-09"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.windows_aarch64_gnullvm]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 64539 # Kenny Kerr (kennykerr)
|
||||
start = "2022-09-01"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.windows_aarch64_msvc]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 64539 # Kenny Kerr (kennykerr)
|
||||
start = "2021-11-05"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.windows_i686_gnu]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 64539 # Kenny Kerr (kennykerr)
|
||||
start = "2021-10-28"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.windows_i686_msvc]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 64539 # Kenny Kerr (kennykerr)
|
||||
start = "2021-10-27"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.windows_x86_64_gnu]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 64539 # Kenny Kerr (kennykerr)
|
||||
start = "2021-10-28"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.windows_x86_64_gnullvm]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 64539 # Kenny Kerr (kennykerr)
|
||||
start = "2022-09-01"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.windows_x86_64_msvc]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 64539 # Kenny Kerr (kennykerr)
|
||||
start = "2021-10-27"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.zcash_address]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 1244 # ebfull
|
||||
start = "2022-10-19"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.zcash_address]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 6289 # str4d
|
||||
start = "2021-03-07"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.zcash_client_backend]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 169181 # Kris Nuttycombe (nuttycom)
|
||||
start = "2024-03-25"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.zcash_client_sqlite]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 169181 # Kris Nuttycombe (nuttycom)
|
||||
start = "2024-03-25"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.zcash_encoding]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 1244 # ebfull
|
||||
start = "2022-10-19"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.zcash_extensions]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 6289 # str4d
|
||||
start = "2020-04-24"
|
||||
end = "2025-04-23"
|
||||
|
||||
[[trusted.zcash_history]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 1244 # ebfull
|
||||
start = "2020-03-04"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.zcash_history]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 6289 # str4d
|
||||
start = "2024-03-01"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.zcash_keys]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 169181 # Kris Nuttycombe (nuttycom)
|
||||
start = "2024-01-15"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.zcash_note_encryption]]
|
||||
criteria = ["safe-to-deploy", "crypto-reviewed"]
|
||||
user-id = 169181 # Kris Nuttycombe (nuttycom)
|
||||
start = "2023-03-22"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.zcash_primitives]]
|
||||
criteria = ["safe-to-deploy", "crypto-reviewed", "license-reviewed"]
|
||||
user-id = 6289 # str4d
|
||||
start = "2021-03-26"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.zcash_primitives]]
|
||||
criteria = ["safe-to-deploy", "crypto-reviewed", "license-reviewed"]
|
||||
user-id = 1244 # ebfull
|
||||
start = "2019-10-08"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.zcash_proofs]]
|
||||
criteria = ["safe-to-deploy", "crypto-reviewed", "license-reviewed"]
|
||||
user-id = 6289 # str4d
|
||||
start = "2021-03-26"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.zcash_protocol]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 169181 # Kris Nuttycombe (nuttycom)
|
||||
start = "2024-01-27"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.zcash_spec]]
|
||||
criteria = ["safe-to-deploy", "crypto-reviewed", "license-reviewed"]
|
||||
user-id = 6289 # str4d
|
||||
start = "2023-12-07"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.zip32]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 6289 # str4d
|
||||
start = "2023-12-06"
|
||||
end = "2025-04-22"
|
||||
|
||||
[[trusted.zip321]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 169181 # Kris Nuttycombe (nuttycom)
|
||||
start = "2024-01-15"
|
||||
end = "2025-04-22"
|
|
@ -0,0 +1,881 @@
|
|||
|
||||
# cargo-vet config file
|
||||
|
||||
[cargo-vet]
|
||||
version = "0.9"
|
||||
|
||||
[imports.bytecode-alliance]
|
||||
url = "https://raw.githubusercontent.com/bytecodealliance/wasmtime/main/supply-chain/audits.toml"
|
||||
|
||||
[imports.embark-studios]
|
||||
url = "https://raw.githubusercontent.com/EmbarkStudios/rust-ecosystem/main/audits.toml"
|
||||
|
||||
[imports.fermyon]
|
||||
url = "https://raw.githubusercontent.com/fermyon/spin/main/supply-chain/audits.toml"
|
||||
|
||||
[imports.google]
|
||||
url = "https://raw.githubusercontent.com/google/supply-chain/main/audits.toml"
|
||||
|
||||
[imports.isrg]
|
||||
url = "https://raw.githubusercontent.com/divviup/libprio-rs/main/supply-chain/audits.toml"
|
||||
|
||||
[imports.mozilla]
|
||||
url = "https://raw.githubusercontent.com/mozilla/supply-chain/main/audits.toml"
|
||||
|
||||
[imports.zcash]
|
||||
url = "https://raw.githubusercontent.com/zcash/rust-ecosystem/main/supply-chain/audits.toml"
|
||||
|
||||
[policy.equihash]
|
||||
audit-as-crates-io = true
|
||||
|
||||
[policy.f4jumble]
|
||||
audit-as-crates-io = true
|
||||
|
||||
[policy.zcash_address]
|
||||
audit-as-crates-io = true
|
||||
|
||||
[policy.zcash_client_backend]
|
||||
audit-as-crates-io = true
|
||||
|
||||
[policy.zcash_client_sqlite]
|
||||
audit-as-crates-io = true
|
||||
|
||||
[policy.zcash_encoding]
|
||||
audit-as-crates-io = true
|
||||
|
||||
[policy.zcash_extensions]
|
||||
audit-as-crates-io = true
|
||||
|
||||
[policy.zcash_history]
|
||||
audit-as-crates-io = true
|
||||
|
||||
[policy.zcash_keys]
|
||||
audit-as-crates-io = true
|
||||
|
||||
[policy.zcash_primitives]
|
||||
audit-as-crates-io = true
|
||||
|
||||
[policy.zcash_proofs]
|
||||
audit-as-crates-io = true
|
||||
|
||||
[policy.zcash_protocol]
|
||||
audit-as-crates-io = true
|
||||
|
||||
[policy.zip321]
|
||||
audit-as-crates-io = true
|
||||
|
||||
[[exemptions.addr2line]]
|
||||
version = "0.21.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.aead]]
|
||||
version = "0.5.2"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.aes]]
|
||||
version = "0.8.3"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.ahash]]
|
||||
version = "0.8.6"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.aho-corasick]]
|
||||
version = "1.1.2"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.allocator-api2]]
|
||||
version = "0.2.16"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.arrayvec]]
|
||||
version = "0.7.4"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.assert_matches]]
|
||||
version = "1.5.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.async-trait]]
|
||||
version = "0.1.78"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.axum]]
|
||||
version = "0.6.20"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.axum-core]]
|
||||
version = "0.3.4"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.backtrace]]
|
||||
version = "0.3.69"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.base64ct]]
|
||||
version = "1.0.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.bech32]]
|
||||
version = "0.9.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.bellman]]
|
||||
version = "0.14.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.bip0039]]
|
||||
version = "0.10.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.bitflags]]
|
||||
version = "1.3.2"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.bitvec]]
|
||||
version = "1.0.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.blake2b_simd]]
|
||||
version = "1.0.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.blake2s_simd]]
|
||||
version = "1.0.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.bls12_381]]
|
||||
version = "0.8.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.bs58]]
|
||||
version = "0.5.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.bytemuck]]
|
||||
version = "1.14.0"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.byteorder]]
|
||||
version = "1.5.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.bytes]]
|
||||
version = "1.5.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.cast]]
|
||||
version = "0.3.0"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.cbc]]
|
||||
version = "0.1.2"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.chacha20]]
|
||||
version = "0.9.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.chacha20poly1305]]
|
||||
version = "0.10.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.ciborium]]
|
||||
version = "0.2.1"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.ciborium-io]]
|
||||
version = "0.2.1"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.ciborium-ll]]
|
||||
version = "0.2.1"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.cipher]]
|
||||
version = "0.4.4"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.clap]]
|
||||
version = "3.2.25"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.cpp_demangle]]
|
||||
version = "0.4.3"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.cpufeatures]]
|
||||
version = "0.2.11"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.criterion]]
|
||||
version = "0.4.0"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.criterion-plot]]
|
||||
version = "0.5.0"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.crossbeam-channel]]
|
||||
version = "0.5.8"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.crossbeam-deque]]
|
||||
version = "0.8.3"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.crossbeam-epoch]]
|
||||
version = "0.9.15"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.crossbeam-utils]]
|
||||
version = "0.8.16"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.daggy]]
|
||||
version = "0.8.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.digest]]
|
||||
version = "0.10.7"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.errno]]
|
||||
version = "0.3.6"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.fallible-iterator]]
|
||||
version = "0.2.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.fallible-streaming-iterator]]
|
||||
version = "0.1.9"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.ff]]
|
||||
version = "0.13.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.findshlibs]]
|
||||
version = "0.10.2"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.fixed-hash]]
|
||||
version = "0.8.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.fixedbitset]]
|
||||
version = "0.4.2"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.fpe]]
|
||||
version = "0.6.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.funty]]
|
||||
version = "2.0.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.futures-macro]]
|
||||
version = "0.3.29"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.futures-sink]]
|
||||
version = "0.3.29"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.futures-task]]
|
||||
version = "0.3.29"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.futures-util]]
|
||||
version = "0.3.29"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.generic-array]]
|
||||
version = "0.14.7"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.getrandom]]
|
||||
version = "0.2.11"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.gimli]]
|
||||
version = "0.28.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.group]]
|
||||
version = "0.13.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.gumdrop]]
|
||||
version = "0.8.1"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.gumdrop_derive]]
|
||||
version = "0.8.1"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.h2]]
|
||||
version = "0.3.21"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.hashbrown]]
|
||||
version = "0.14.2"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.hashlink]]
|
||||
version = "0.8.4"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.hdwallet]]
|
||||
version = "0.4.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.hermit-abi]]
|
||||
version = "0.1.19"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.hermit-abi]]
|
||||
version = "0.3.3"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.home]]
|
||||
version = "0.5.5"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.http]]
|
||||
version = "0.2.9"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.http-body]]
|
||||
version = "0.4.5"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.httparse]]
|
||||
version = "1.8.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.hyper]]
|
||||
version = "0.14.27"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.hyper-timeout]]
|
||||
version = "0.4.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.indexmap]]
|
||||
version = "1.9.3"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.indexmap]]
|
||||
version = "2.1.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.inferno]]
|
||||
version = "0.11.17"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.itertools]]
|
||||
version = "0.11.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.itoa]]
|
||||
version = "1.0.9"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.js-sys]]
|
||||
version = "0.3.65"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.jubjub]]
|
||||
version = "0.10.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.libc]]
|
||||
version = "0.2.150"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.libm]]
|
||||
version = "0.2.2"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.libsqlite3-sys]]
|
||||
version = "0.26.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.linux-raw-sys]]
|
||||
version = "0.4.11"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.lock_api]]
|
||||
version = "0.4.11"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.matchit]]
|
||||
version = "0.7.3"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.memchr]]
|
||||
version = "2.6.4"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.memmap2]]
|
||||
version = "0.5.10"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.memoffset]]
|
||||
version = "0.9.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.memuse]]
|
||||
version = "0.2.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.mime]]
|
||||
version = "0.3.17"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.minimal-lexical]]
|
||||
version = "0.2.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.minreq]]
|
||||
version = "2.11.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.mio]]
|
||||
version = "0.8.9"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.multimap]]
|
||||
version = "0.8.3"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.nonempty]]
|
||||
version = "0.7.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.num-format]]
|
||||
version = "0.4.4"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.num_cpus]]
|
||||
version = "1.16.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.object]]
|
||||
version = "0.32.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.once_cell]]
|
||||
version = "1.18.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.os_str_bytes]]
|
||||
version = "6.6.1"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.pairing]]
|
||||
version = "0.23.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.parking_lot_core]]
|
||||
version = "0.9.9"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.password-hash]]
|
||||
version = "0.3.2"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.pasta_curves]]
|
||||
version = "0.5.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.pbkdf2]]
|
||||
version = "0.10.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.petgraph]]
|
||||
version = "0.6.4"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.pin-project]]
|
||||
version = "1.1.3"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.pin-project-internal]]
|
||||
version = "1.1.3"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.pkg-config]]
|
||||
version = "0.3.27"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.plotters]]
|
||||
version = "0.3.5"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.plotters-backend]]
|
||||
version = "0.3.5"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.plotters-svg]]
|
||||
version = "0.3.5"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.poly1305]]
|
||||
version = "0.8.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.pprof]]
|
||||
version = "0.11.1"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.ppv-lite86]]
|
||||
version = "0.2.17"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.prettyplease]]
|
||||
version = "0.2.15"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.primitive-types]]
|
||||
version = "0.12.2"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.proptest]]
|
||||
version = "1.3.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.prost]]
|
||||
version = "0.12.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.prost-build]]
|
||||
version = "0.12.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.prost-derive]]
|
||||
version = "0.12.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.prost-types]]
|
||||
version = "0.12.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.quick-error]]
|
||||
version = "1.2.3"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.quick-xml]]
|
||||
version = "0.26.0"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.radium]]
|
||||
version = "0.7.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.rand]]
|
||||
version = "0.8.5"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.reddsa]]
|
||||
version = "0.5.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.redox_syscall]]
|
||||
version = "0.4.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.regex]]
|
||||
version = "1.10.2"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.regex-automata]]
|
||||
version = "0.4.3"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.regex-syntax]]
|
||||
version = "0.7.5"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.rgb]]
|
||||
version = "0.8.37"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.ring]]
|
||||
version = "0.16.20"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.ring]]
|
||||
version = "0.17.5"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.ripemd]]
|
||||
version = "0.1.3"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.rusqlite]]
|
||||
version = "0.29.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.rustix]]
|
||||
version = "0.38.21"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.rustls]]
|
||||
version = "0.21.8"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.rustls-webpki]]
|
||||
version = "0.101.7"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.rusty-fork]]
|
||||
version = "0.3.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.ryu]]
|
||||
version = "1.0.15"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.schemer]]
|
||||
version = "0.2.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.schemer-rusqlite]]
|
||||
version = "0.2.2"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.scopeguard]]
|
||||
version = "1.2.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.sct]]
|
||||
version = "0.7.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.secp256k1]]
|
||||
version = "0.26.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.secp256k1-sys]]
|
||||
version = "0.8.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.secrecy]]
|
||||
version = "0.8.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.serde]]
|
||||
version = "1.0.192"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.serde_derive]]
|
||||
version = "1.0.192"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.sha2]]
|
||||
version = "0.10.8"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.slab]]
|
||||
version = "0.4.9"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.smallvec]]
|
||||
version = "1.11.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.socket2]]
|
||||
version = "0.4.10"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.socket2]]
|
||||
version = "0.5.5"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.spin]]
|
||||
version = "0.5.2"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.spin]]
|
||||
version = "0.9.8"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.str_stack]]
|
||||
version = "0.1.0"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.subtle]]
|
||||
version = "2.4.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.symbolic-common]]
|
||||
version = "10.2.1"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.symbolic-demangle]]
|
||||
version = "10.2.1"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.syn]]
|
||||
version = "2.0.53"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.sync_wrapper]]
|
||||
version = "0.1.2"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.tempfile]]
|
||||
version = "3.8.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.time]]
|
||||
version = "0.3.23"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.tinytemplate]]
|
||||
version = "1.2.1"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.tokio]]
|
||||
version = "1.35.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.tokio-io-timeout]]
|
||||
version = "1.2.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.tokio-util]]
|
||||
version = "0.7.10"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.tonic]]
|
||||
version = "0.10.2"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.tonic-build]]
|
||||
version = "0.10.2"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.tower]]
|
||||
version = "0.4.13"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.tower-layer]]
|
||||
version = "0.3.2"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.tower-service]]
|
||||
version = "0.3.2"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.tracing]]
|
||||
version = "0.1.40"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.tracing-attributes]]
|
||||
version = "0.1.27"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.tracing-core]]
|
||||
version = "0.1.32"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.typenum]]
|
||||
version = "1.17.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.uint]]
|
||||
version = "0.9.5"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.unarray]]
|
||||
version = "0.1.4"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.untrusted]]
|
||||
version = "0.9.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.uuid]]
|
||||
version = "1.5.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.wait-timeout]]
|
||||
version = "0.2.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.walkdir]]
|
||||
version = "2.4.0"
|
||||
criteria = "safe-to-run"
|
||||
|
||||
[[exemptions.wasi]]
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.wasm-bindgen]]
|
||||
version = "0.2.88"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.wasm-bindgen-backend]]
|
||||
version = "0.2.88"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.wasm-bindgen-macro]]
|
||||
version = "0.2.88"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.wasm-bindgen-macro-support]]
|
||||
version = "0.2.88"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.wasm-bindgen-shared]]
|
||||
version = "0.2.88"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.web-sys]]
|
||||
version = "0.3.65"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.which]]
|
||||
version = "4.4.2"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.winapi]]
|
||||
version = "0.3.9"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.winapi-i686-pc-windows-gnu]]
|
||||
version = "0.4.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.winapi-x86_64-pc-windows-gnu]]
|
||||
version = "0.4.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.wyz]]
|
||||
version = "0.5.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.xdg]]
|
||||
version = "2.5.2"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.zerocopy]]
|
||||
version = "0.7.25"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.zerocopy-derive]]
|
||||
version = "0.7.25"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.zeroize]]
|
||||
version = "1.6.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.zeroize_derive]]
|
||||
version = "1.4.2"
|
||||
criteria = "safe-to-deploy"
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue