Repalce md5 with keccak256, and change nonces from u32 to u64.

This commit is contained in:
FiveMovesAhead 2024-08-15 04:28:46 +08:00
parent 5110aef66c
commit ec71c8e719
17 changed files with 91 additions and 78 deletions

View File

@ -14,11 +14,11 @@ pub async fn execute() -> Result<Option<(String, Vec<SolutionData>)>> {
continue;
}
if let Some(state) = &benchmarks[benchmark_id].state {
let sampled_nonces: HashSet<u32> =
let sampled_nonces: HashSet<u64> =
state.sampled_nonces.clone().unwrap().into_iter().collect();
let mut solutions_data = proof.solutions_data.take().unwrap();
solutions_data.retain(|x| sampled_nonces.contains(&x.nonce));
let extracted_nonces: HashSet<u32> = solutions_data.iter().map(|x| x.nonce).collect();
let extracted_nonces: HashSet<u64> = solutions_data.iter().map(|x| x.nonce).collect();
if extracted_nonces != sampled_nonces {
return Err(format!(
"No solutions for sampled nonces: '{:?}'",

View File

@ -67,54 +67,54 @@ pub struct Job {
pub benchmark_id: String,
pub settings: BenchmarkSettings,
pub solution_signature_threshold: u32,
pub sampled_nonces: Option<Vec<u32>>,
pub sampled_nonces: Option<Vec<u64>>,
pub wasm_vm_config: WasmVMConfig,
}
#[derive(Serialize, Debug, Clone)]
pub struct NonceIterator {
nonces: Option<Vec<u32>>,
current: u32,
attempts: u32,
nonces: Option<Vec<u64>>,
current: u64,
attempts: u64,
}
impl NonceIterator {
pub fn from_vec(nonces: Vec<u32>) -> Self {
pub fn from_vec(nonces: Vec<u64>) -> Self {
Self {
nonces: Some(nonces),
current: 0,
attempts: 0,
}
}
pub fn from_u32(start: u32) -> Self {
pub fn from_u64(start: u64) -> Self {
Self {
nonces: None,
current: start,
attempts: 0,
}
}
pub fn attempts(&self) -> u32 {
pub fn attempts(&self) -> u64 {
self.attempts
}
pub fn is_empty(&self) -> bool {
self.nonces.as_ref().is_some_and(|x| x.is_empty()) || self.current == u32::MAX
self.nonces.as_ref().is_some_and(|x| x.is_empty()) || self.current == u64::MAX
}
pub fn empty(&mut self) {
if let Some(nonces) = self.nonces.as_mut() {
nonces.clear();
}
self.current = u32::MAX;
self.current = u64::MAX;
}
}
impl Iterator for NonceIterator {
type Item = u32;
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
if let Some(nonces) = self.nonces.as_mut() {
let value = nonces.pop();
self.attempts += value.is_some() as u32;
self.attempts += value.is_some() as u64;
value
} else if self.current < u32::MAX {
} else if self.current < u64::MAX {
let value = Some(self.current);
self.attempts += 1;
self.current += 1;
@ -273,8 +273,8 @@ async fn run_once(num_workers: u32, ms_per_benchmark: u32) -> Result<()> {
None => (0..num_workers)
.into_iter()
.map(|x| {
Arc::new(Mutex::new(NonceIterator::from_u32(
u32::MAX / num_workers * x,
Arc::new(Mutex::new(NonceIterator::from_u64(
u64::MAX / num_workers as u64 * x as u64,
)))
})
.collect(),
@ -317,7 +317,7 @@ async fn run_once(num_workers: u32, ms_per_benchmark: u32) -> Result<()> {
..
} = &mut (*state().lock().await);
if time_left.as_mut().unwrap().update().finished()
|| (finished && num_solutions == num_attempts) // nonce_iter is only empty if recomputing
|| (finished && num_solutions == (num_attempts as u32)) // nonce_iter is only empty if recomputing
|| *status == Status::Stopping
{
break;

View File

@ -72,7 +72,7 @@ fn cli() -> Command {
.long("offset")
.help("(Optional) Set nonce offset for each slave")
.default_value("5000000")
.value_parser(value_parser!(u32)),
.value_parser(value_parser!(u64)),
)
}
@ -87,7 +87,7 @@ async fn main() {
let api_url = matches.get_one::<String>("api").unwrap().clone();
let api_key = matches.get_one::<String>("API_KEY").unwrap().clone();
let player_id = matches.get_one::<String>("PLAYER_ID").unwrap().clone();
let nonce_offset = matches.get_one::<u32>("offset").unwrap().clone();
let nonce_offset = matches.get_one::<u64>("offset").unwrap().clone();
if let Some(master) = matches.get_one::<String>("master") {
slave_node(master, port, num_workers).await;
} else {
@ -158,7 +158,7 @@ async fn slave_node(master: &String, port: u16, num_workers: u32) {
)
.await
{
Ok(resp) => dejsonify::<u32>(&resp).unwrap(),
Ok(resp) => dejsonify::<u64>(&resp).unwrap(),
Err(e) => {
println!("Error getting nonce offset: {:?}", e);
sleep(5000).await;
@ -171,8 +171,8 @@ async fn slave_node(master: &String, port: u16, num_workers: u32) {
nonce_iters = (0..num_workers)
.into_iter()
.map(|x| {
Arc::new(Mutex::new(NonceIterator::from_u32(
offset + u32::MAX / num_workers * x,
Arc::new(Mutex::new(NonceIterator::from_u64(
offset + u64::MAX / num_workers as u64 * x as u64,
)))
})
.collect();
@ -237,7 +237,7 @@ async fn master_node(
duration: u32,
algorithms_path: &PathBuf,
port: u16,
nonce_offset: u32,
nonce_offset: u64,
) {
benchmarker::setup(api_url, api_key, player_id).await;
benchmarker::start(num_workers, duration).await;
@ -247,9 +247,9 @@ async fn master_node(
.and(warp::get())
.and(warp::any().map(move || offsets.clone()))
.and_then(
move |slave_id: String, offsets: Arc<Mutex<HashMap<String, u32>>>| async move {
move |slave_id: String, offsets: Arc<Mutex<HashMap<String, u64>>>| async move {
let offsets = &mut (*offsets).lock().await;
let len = offsets.len() as u32;
let len = offsets.len() as u64;
let o = offsets
.entry(slave_id)
.or_insert_with(|| (len + 1) * nonce_offset);

View File

@ -47,7 +47,7 @@ impl TryFrom<Map<String, Value>> for Solution {
#[derive(Serialize, Deserialize, Debug)]
pub struct Challenge {
pub seed: u32,
pub seed: u64,
pub difficulty: Difficulty,
pub weights: Vec<u32>,
pub values: Vec<u32>,
@ -62,7 +62,7 @@ pub const KERNEL: Option<CudaKernel> = None;
impl crate::ChallengeTrait<Solution, Difficulty, 2> for Challenge {
#[cfg(feature = "cuda")]
fn cuda_generate_instance(
seed: u32,
seed: u64,
difficulty: &Difficulty,
dev: &Arc<CudaDevice>,
mut funcs: HashMap<&'static str, CudaFunction>,
@ -71,8 +71,8 @@ impl crate::ChallengeTrait<Solution, Difficulty, 2> for Challenge {
Self::generate_instance(seed, difficulty)
}
fn generate_instance(seed: u32, difficulty: &Difficulty) -> Result<Challenge> {
let mut rng: StdRng = StdRng::seed_from_u64(seed as u64);
fn generate_instance(seed: u64, difficulty: &Difficulty) -> Result<Challenge> {
let mut rng: StdRng = StdRng::seed_from_u64(seed);
let weights: Vec<u32> = (0..difficulty.num_items)
.map(|_| rng.gen_range(1..50))

View File

@ -18,30 +18,30 @@ where
T: SolutionTrait,
U: DifficultyTrait<N>,
{
fn generate_instance(seed: u32, difficulty: &U) -> Result<Self>;
fn generate_instance_from_str(seed: u32, difficulty: &str) -> Result<Self> {
fn generate_instance(seed: u64, difficulty: &U) -> Result<Self>;
fn generate_instance_from_str(seed: u64, difficulty: &str) -> Result<Self> {
Self::generate_instance(seed, &serde_json::from_str(difficulty)?)
}
fn generate_instance_from_vec(seed: u32, difficulty: &Vec<i32>) -> Result<Self> {
fn generate_instance_from_vec(seed: u64, difficulty: &Vec<i32>) -> Result<Self> {
match difficulty.as_slice().try_into() {
Ok(difficulty) => Self::generate_instance_from_arr(seed, &difficulty),
Err(_) => Err(anyhow!("Invalid difficulty length")),
}
}
fn generate_instance_from_arr(seed: u32, difficulty: &[i32; N]) -> Result<Self> {
fn generate_instance_from_arr(seed: u64, difficulty: &[i32; N]) -> Result<Self> {
Self::generate_instance(seed, &U::from_arr(difficulty))
}
#[cfg(feature = "cuda")]
fn cuda_generate_instance(
seed: u32,
seed: u64,
difficulty: &U,
dev: &Arc<CudaDevice>,
funcs: HashMap<&'static str, CudaFunction>,
) -> Result<Self>;
#[cfg(feature = "cuda")]
fn cuda_generate_instance_from_str(
seed: u32,
seed: u64,
difficulty: &str,
dev: &Arc<CudaDevice>,
funcs: HashMap<&'static str, CudaFunction>,
@ -50,7 +50,7 @@ where
}
#[cfg(feature = "cuda")]
fn cuda_generate_instance_from_vec(
seed: u32,
seed: u64,
difficulty: &Vec<i32>,
dev: &Arc<CudaDevice>,
funcs: HashMap<&'static str, CudaFunction>,
@ -62,7 +62,7 @@ where
}
#[cfg(feature = "cuda")]
fn cuda_generate_instance_from_arr(
seed: u32,
seed: u64,
difficulty: &[i32; N],
dev: &Arc<CudaDevice>,
funcs: HashMap<&'static str, CudaFunction>,

View File

@ -59,7 +59,7 @@ impl TryFrom<Map<String, Value>> for Solution {
#[derive(Serialize, Deserialize, Debug)]
pub struct Challenge {
pub seed: u32,
pub seed: u64,
pub difficulty: Difficulty,
pub clauses: Vec<Vec<i32>>,
}
@ -71,7 +71,7 @@ pub const KERNEL: Option<CudaKernel> = None;
impl crate::ChallengeTrait<Solution, Difficulty, 2> for Challenge {
#[cfg(feature = "cuda")]
fn cuda_generate_instance(
seed: u32,
seed: u64,
difficulty: &Difficulty,
dev: &Arc<CudaDevice>,
mut funcs: HashMap<&'static str, CudaFunction>,
@ -80,8 +80,8 @@ impl crate::ChallengeTrait<Solution, Difficulty, 2> for Challenge {
Self::generate_instance(seed, difficulty)
}
fn generate_instance(seed: u32, difficulty: &Difficulty) -> Result<Self> {
let mut rng = StdRng::seed_from_u64(seed as u64);
fn generate_instance(seed: u64, difficulty: &Difficulty) -> Result<Self> {
let mut rng = StdRng::seed_from_u64(seed);
let num_clauses = (difficulty.num_variables as f64
* difficulty.clauses_to_variables_percent as f64
/ 100.0)

View File

@ -51,7 +51,7 @@ impl TryFrom<Map<String, Value>> for Solution {
#[derive(Serialize, Deserialize, Debug)]
pub struct Challenge {
pub seed: u32,
pub seed: u64,
pub difficulty: Difficulty,
pub vector_database: Vec<Vec<f32>>,
pub query_vectors: Vec<Vec<f32>>,
@ -73,7 +73,7 @@ pub const KERNEL: Option<CudaKernel> = None;
impl ChallengeTrait<Solution, Difficulty, 2> for Challenge {
#[cfg(feature = "cuda")]
fn cuda_generate_instance(
seed: u32,
seed: u64,
difficulty: &Difficulty,
dev: &Arc<CudaDevice>,
mut funcs: HashMap<&'static str, CudaFunction>,
@ -82,8 +82,8 @@ impl ChallengeTrait<Solution, Difficulty, 2> for Challenge {
Self::generate_instance(seed, difficulty)
}
fn generate_instance(seed: u32, difficulty: &Difficulty) -> Result<Self> {
let mut rng = StdRng::seed_from_u64(seed as u64);
fn generate_instance(seed: u64, difficulty: &Difficulty) -> Result<Self> {
let mut rng = StdRng::seed_from_u64(seed);
let uniform = Uniform::from(0.0..1.0);
let search_vectors = (0..100000)
.map(|_| (0..250).map(|_| uniform.sample(&mut rng)).collect())

View File

@ -46,7 +46,7 @@ impl TryFrom<Map<String, Value>> for Solution {
#[derive(Serialize, Deserialize, Debug)]
pub struct Challenge {
pub seed: u32,
pub seed: u64,
pub difficulty: Difficulty,
pub demands: Vec<i32>,
pub distance_matrix: Vec<Vec<i32>>,
@ -61,7 +61,7 @@ pub const KERNEL: Option<CudaKernel> = None;
impl crate::ChallengeTrait<Solution, Difficulty, 2> for Challenge {
#[cfg(feature = "cuda")]
fn cuda_generate_instance(
seed: u32,
seed: u64,
difficulty: &Difficulty,
dev: &Arc<CudaDevice>,
mut funcs: HashMap<&'static str, CudaFunction>,
@ -70,8 +70,8 @@ impl crate::ChallengeTrait<Solution, Difficulty, 2> for Challenge {
Self::generate_instance(seed, difficulty)
}
fn generate_instance(seed: u32, difficulty: &Difficulty) -> Result<Challenge> {
let mut rng: StdRng = StdRng::seed_from_u64(seed as u64);
fn generate_instance(seed: u64, difficulty: &Difficulty) -> Result<Challenge> {
let mut rng: StdRng = StdRng::seed_from_u64(seed);
let num_nodes = difficulty.num_nodes;
let max_capacity = 100;

View File

@ -105,13 +105,13 @@ pub trait Context {
async fn verify_solution(
&self,
settings: &BenchmarkSettings,
nonce: u32,
nonce: u64,
solution: &Solution,
) -> ContextResult<anyhow::Result<()>>;
async fn compute_solution(
&self,
settings: &BenchmarkSettings,
nonce: u32,
nonce: u64,
wasm_vm_config: &WasmVMConfig,
) -> ContextResult<anyhow::Result<SolutionData>>;
async fn get_transaction(&self, tx_hash: &String) -> ContextResult<Transaction>;

View File

@ -12,7 +12,7 @@ pub enum ProtocolError {
settings: BenchmarkSettings,
},
DuplicateNonce {
nonce: u32,
nonce: u64,
},
DuplicateProof {
benchmark_id: String,
@ -35,7 +35,7 @@ pub enum ProtocolError {
benchmark_id: String,
},
InvalidBenchmarkNonce {
nonce: u32,
nonce: u64,
},
InvalidBlock {
block_id: String,
@ -48,23 +48,23 @@ pub enum ProtocolError {
difficulty_parameters: Vec<DifficultyParameter>,
},
InvalidProofNonces {
expected_nonces: Vec<u32>,
submitted_nonces: Vec<u32>,
expected_nonces: Vec<u64>,
submitted_nonces: Vec<u64>,
},
InvalidSignatureFromSolutionData {
actual_signature: u32,
nonce: u32,
nonce: u64,
expected_signature: u32,
},
InvalidSolution {
nonce: u32,
nonce: u64,
},
InvalidSolutionData {
algorithm_id: String,
nonce: u32,
nonce: u64,
},
InvalidSolutionSignature {
nonce: u32,
nonce: u64,
solution_signature: u32,
threshold: u32,
},

View File

@ -175,7 +175,7 @@ async fn verify_benchmark_settings_are_unique<T: Context>(
#[time]
fn verify_nonces_are_unique(solutions_meta_data: &Vec<SolutionMetaData>) -> ProtocolResult<()> {
let nonces: HashMap<u32, u32> =
let nonces: HashMap<u64, u32> =
solutions_meta_data
.iter()
.fold(HashMap::new(), |mut acc, s| {
@ -267,7 +267,7 @@ async fn verify_solution_is_valid<T: Context>(
solutions_meta_data: &Vec<SolutionMetaData>,
solution_data: &SolutionData,
) -> ProtocolResult<()> {
let solutions_map: HashMap<u32, u32> = solutions_meta_data
let solutions_map: HashMap<u64, u32> = solutions_meta_data
.iter()
.map(|d| (d.nonce, d.solution_signature))
.collect();

View File

@ -95,8 +95,8 @@ fn verify_sampled_nonces(
benchmark: &Benchmark,
solutions_data: &Vec<SolutionData>,
) -> ProtocolResult<()> {
let sampled_nonces: HashSet<u32> = benchmark.state().sampled_nonces().iter().cloned().collect();
let proof_nonces: HashSet<u32> = solutions_data.iter().map(|d| d.nonce).collect();
let sampled_nonces: HashSet<u64> = benchmark.state().sampled_nonces().iter().cloned().collect();
let proof_nonces: HashSet<u64> = solutions_data.iter().map(|d| d.nonce).collect();
if sampled_nonces != proof_nonces {
return Err(ProtocolError::InvalidProofNonces {
@ -113,7 +113,7 @@ async fn verify_solutions_are_valid<T: Context>(
benchmark: &Benchmark,
solutions_data: &Vec<SolutionData>,
) -> ProtocolResult<()> {
let solutions_map: HashMap<u32, u32> = benchmark
let solutions_map: HashMap<u64, u32> = benchmark
.solutions_meta_data()
.iter()
.map(|d| (d.nonce, d.solution_signature))

View File

@ -2,7 +2,7 @@ use crate::{config::ProtocolConfig, serializable_struct_with_getters};
use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
use std::collections::{HashMap, HashSet};
use tig_utils::{jsonify, u32_from_str};
use tig_utils::{jsonify, u32_from_str, u64_from_str};
pub use tig_utils::{Frontier, Point, PreciseNumber, Transaction, U256};
serializable_struct_with_getters! {
@ -109,8 +109,8 @@ serializable_struct_with_getters! {
}
}
impl BenchmarkSettings {
pub fn calc_seed(&self, nonce: u32) -> u32 {
u32_from_str(jsonify(&self).as_str()) ^ nonce
pub fn calc_seed(&self, nonce: u64) -> u64 {
u64_from_str(jsonify(&self).as_str()) ^ nonce
}
}
serializable_struct_with_getters! {
@ -122,12 +122,12 @@ serializable_struct_with_getters! {
serializable_struct_with_getters! {
BenchmarkState {
block_confirmed: Option<u32>,
sampled_nonces: Option<Vec<u32>>,
sampled_nonces: Option<Vec<u64>>,
}
}
serializable_struct_with_getters! {
SolutionMetaData {
nonce: u32,
nonce: u64,
solution_signature: u32,
}
}
@ -219,7 +219,7 @@ serializable_struct_with_getters! {
pub type Solution = Map<String, Value>;
serializable_struct_with_getters! {
SolutionData {
nonce: u32,
nonce: u64,
runtime_signature: u32,
fuel_consumed: u64,
solution: Solution,

View File

@ -18,6 +18,7 @@ rand = { version = "0.8.5", default-features = false, features = ["std_rng"] }
reqwest = { version = "0.12.2", optional = true }
serde = { version = "1.0.196", features = ["derive"] }
serde_json = { version = "1.0.113", features = ["preserve_order"] }
sha3 = "0.10.8"
uint = "0.9.5"
wasm-bindgen = { version = "0.2.91", optional = true }
wasm-bindgen-futures = { version = "0.4.41", optional = true }

View File

@ -1,4 +1,5 @@
use md5;
use sha3::{Digest, Keccak256};
pub fn md5_from_str(input: &str) -> String {
md5_from_bytes(input.as_bytes())
@ -13,3 +14,14 @@ pub fn u32_from_str(input: &str) -> u32 {
let bytes = result[12..16].try_into().expect("Should not ever panic..");
u32::from_le_bytes(bytes)
}
pub fn u64_from_str(input: &str) -> u64 {
let mut hasher = Keccak256::new();
hasher.update(input.as_bytes());
let result = hasher.finalize();
u64::from_le_bytes(
result.as_slice()[0..8]
.try_into()
.expect("Should not ever panic.."),
)
}

View File

@ -15,7 +15,7 @@ fn cli() -> Command {
arg!(<SETTINGS> "Settings json string or path to json file")
.value_parser(clap::value_parser!(String)),
)
.arg(arg!(<NONCE> "Nonce value").value_parser(clap::value_parser!(u32)))
.arg(arg!(<NONCE> "Nonce value").value_parser(clap::value_parser!(u64)))
.arg(arg!(<WASM> "Path to a wasm file").value_parser(clap::value_parser!(PathBuf)))
.arg(
arg!(--fuel [FUEL] "Optional maximum fuel parameter for WASM VM")
@ -35,7 +35,7 @@ fn cli() -> Command {
arg!(<SETTINGS> "Settings json string or path to json file")
.value_parser(clap::value_parser!(String)),
)
.arg(arg!(<NONCE> "Nonce value").value_parser(clap::value_parser!(u32)))
.arg(arg!(<NONCE> "Nonce value").value_parser(clap::value_parser!(u64)))
.arg(
arg!(<SOLUTION> "Solution json string or path to json file")
.value_parser(clap::value_parser!(String)),
@ -49,14 +49,14 @@ fn main() {
match matches.subcommand() {
Some(("compute_solution", sub_m)) => compute_solution(
sub_m.get_one::<String>("SETTINGS").unwrap().clone(),
*sub_m.get_one::<u32>("NONCE").unwrap(),
*sub_m.get_one::<u64>("NONCE").unwrap(),
sub_m.get_one::<PathBuf>("WASM").unwrap().clone(),
*sub_m.get_one::<u64>("mem").unwrap(),
*sub_m.get_one::<u64>("fuel").unwrap(),
),
Some(("verify_solution", sub_m)) => verify_solution(
sub_m.get_one::<String>("SETTINGS").unwrap().clone(),
*sub_m.get_one::<u32>("NONCE").unwrap(),
*sub_m.get_one::<u64>("NONCE").unwrap(),
sub_m.get_one::<String>("SOLUTION").unwrap().clone(),
),
_ => {}
@ -65,7 +65,7 @@ fn main() {
fn compute_solution(
mut settings: String,
nonce: u32,
nonce: u64,
wasm_path: PathBuf,
max_memory: u64,
max_fuel: u64,
@ -114,7 +114,7 @@ fn compute_solution(
}
}
fn verify_solution(mut settings: String, nonce: u32, mut solution: String) {
fn verify_solution(mut settings: String, nonce: u64, mut solution: String) {
if settings.ends_with(".json") {
settings = fs::read_to_string(&settings).unwrap_or_else(|_| {
eprintln!("Failed to read settings file: {}", settings);

View File

@ -7,7 +7,7 @@ use wasmi::{Config, Engine, Linker, Module, Store, StoreLimitsBuilder};
pub fn compute_solution(
settings: &BenchmarkSettings,
nonce: u32,
nonce: u64,
wasm: &[u8],
max_memory: u64,
max_fuel: u64,
@ -118,7 +118,7 @@ pub fn compute_solution(
pub fn verify_solution(
settings: &BenchmarkSettings,
nonce: u32,
nonce: u64,
solution: &Solution,
) -> Result<()> {
let seed = settings.calc_seed(nonce);