Use all 512 bits of keccak512 in seed & challenge generation

This commit is contained in:
FiveMovesAhead 2024-08-15 13:50:30 +08:00
parent ec71c8e719
commit 53460404ba
10 changed files with 120 additions and 91 deletions

View File

@ -84,7 +84,7 @@ pub async fn execute(
yield_now().await;
last_yield = now;
}
let seed = job.settings.calc_seed(nonce);
let seeds = job.settings.calc_seeds(nonce);
let skip = match job.settings.challenge_id.as_str() {
"c001" => {
type CudaSolveChallengeFn =
@ -3121,7 +3121,7 @@ pub async fn execute(
.clone();
let challenge =
tig_challenges::c001::Challenge::cuda_generate_instance_from_vec(
seed,
seeds,
&job.settings.difficulty,
&dev,
challenge_cuda_funcs,
@ -6176,7 +6176,7 @@ pub async fn execute(
.clone();
let challenge =
tig_challenges::c002::Challenge::cuda_generate_instance_from_vec(
seed,
seeds,
&job.settings.difficulty,
&dev,
challenge_cuda_funcs,
@ -9231,7 +9231,7 @@ pub async fn execute(
.clone();
let challenge =
tig_challenges::c003::Challenge::cuda_generate_instance_from_vec(
seed,
seeds,
&job.settings.difficulty,
&dev,
challenge_cuda_funcs,
@ -12286,7 +12286,7 @@ pub async fn execute(
.clone();
let challenge =
tig_challenges::c004::Challenge::cuda_generate_instance_from_vec(
seed,
seeds,
&job.settings.difficulty,
&dev,
challenge_cuda_funcs,

View File

@ -32,7 +32,7 @@ pub async fn execute(
yield_now().await;
last_yield = now;
}
let seed = job.settings.calc_seed(nonce);
let seeds = job.settings.calc_seeds(nonce);
let skip = match job.settings.challenge_id.as_str() {
"c001" => {
type SolveChallengeFn =
@ -3042,7 +3042,7 @@ pub async fn execute(
Some(solve_challenge) => {
let challenge =
tig_challenges::c001::Challenge::generate_instance_from_vec(
seed,
seeds,
&job.settings.difficulty,
)
.unwrap();
@ -6064,7 +6064,7 @@ pub async fn execute(
Some(solve_challenge) => {
let challenge =
tig_challenges::c002::Challenge::generate_instance_from_vec(
seed,
seeds,
&job.settings.difficulty,
)
.unwrap();
@ -9086,7 +9086,7 @@ pub async fn execute(
Some(solve_challenge) => {
let challenge =
tig_challenges::c003::Challenge::generate_instance_from_vec(
seed,
seeds,
&job.settings.difficulty,
)
.unwrap();
@ -9103,7 +9103,7 @@ pub async fn execute(
"c004" => {
let challenge =
tig_challenges::c004::Challenge::generate_instance_from_vec(
seed,
seeds,
&job.settings.difficulty,
)
.unwrap();
@ -12114,7 +12114,7 @@ pub async fn execute(
Some(solve_challenge) => {
let challenge =
tig_challenges::c004::Challenge::generate_instance_from_vec(
seed,
seeds,
&job.settings.difficulty,
)
.unwrap();

View File

@ -1,5 +1,6 @@
use crate::RngArray;
use anyhow::{anyhow, Result};
use rand::{rngs::StdRng, Rng, SeedableRng};
use rand::Rng;
use serde::{Deserialize, Serialize};
use serde_json::{from_value, Map, Value};
use std::collections::HashSet;
@ -47,7 +48,7 @@ impl TryFrom<Map<String, Value>> for Solution {
#[derive(Serialize, Deserialize, Debug)]
pub struct Challenge {
pub seed: u64,
pub seeds: [u64; 8],
pub difficulty: Difficulty,
pub weights: Vec<u32>,
pub values: Vec<u32>,
@ -62,23 +63,23 @@ pub const KERNEL: Option<CudaKernel> = None;
impl crate::ChallengeTrait<Solution, Difficulty, 2> for Challenge {
#[cfg(feature = "cuda")]
fn cuda_generate_instance(
seed: u64,
seeds: [u64; 8],
difficulty: &Difficulty,
dev: &Arc<CudaDevice>,
mut funcs: HashMap<&'static str, CudaFunction>,
) -> Result<Self> {
// TIG dev bounty available for a GPU optimisation for instance generation!
Self::generate_instance(seed, difficulty)
Self::generate_instance(seeds, difficulty)
}
fn generate_instance(seed: u64, difficulty: &Difficulty) -> Result<Challenge> {
let mut rng: StdRng = StdRng::seed_from_u64(seed);
fn generate_instance(seeds: [u64; 8], difficulty: &Difficulty) -> Result<Challenge> {
let mut rngs = RngArray::new(seeds);
let weights: Vec<u32> = (0..difficulty.num_items)
.map(|_| rng.gen_range(1..50))
.map(|_| rngs.get_mut().gen_range(1..50))
.collect();
let values: Vec<u32> = (0..difficulty.num_items)
.map(|_| rng.gen_range(1..50))
.map(|_| rngs.get_mut().gen_range(1..50))
.collect();
let max_weight: u32 = weights.iter().sum::<u32>() / 2;
@ -103,7 +104,7 @@ impl crate::ChallengeTrait<Solution, Difficulty, 2> for Challenge {
.round() as u32;
Ok(Challenge {
seed,
seeds,
difficulty: difficulty.clone(),
weights,
values,

View File

@ -1,4 +1,5 @@
use anyhow::{anyhow, Result};
use rand::{rngs::StdRng, Rng, SeedableRng};
use serde::de::DeserializeOwned;
use serde::Serialize;
@ -18,56 +19,56 @@ where
T: SolutionTrait,
U: DifficultyTrait<N>,
{
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(seeds: [u64; 8], difficulty: &U) -> Result<Self>;
fn generate_instance_from_str(seeds: [u64; 8], difficulty: &str) -> Result<Self> {
Self::generate_instance(seeds, &serde_json::from_str(difficulty)?)
}
fn generate_instance_from_vec(seed: u64, difficulty: &Vec<i32>) -> Result<Self> {
fn generate_instance_from_vec(seeds: [u64; 8], difficulty: &Vec<i32>) -> Result<Self> {
match difficulty.as_slice().try_into() {
Ok(difficulty) => Self::generate_instance_from_arr(seed, &difficulty),
Ok(difficulty) => Self::generate_instance_from_arr(seeds, &difficulty),
Err(_) => Err(anyhow!("Invalid difficulty length")),
}
}
fn generate_instance_from_arr(seed: u64, difficulty: &[i32; N]) -> Result<Self> {
Self::generate_instance(seed, &U::from_arr(difficulty))
fn generate_instance_from_arr(seeds: [u64; 8], difficulty: &[i32; N]) -> Result<Self> {
Self::generate_instance(seeds, &U::from_arr(difficulty))
}
#[cfg(feature = "cuda")]
fn cuda_generate_instance(
seed: u64,
seeds: [u64; 8],
difficulty: &U,
dev: &Arc<CudaDevice>,
funcs: HashMap<&'static str, CudaFunction>,
) -> Result<Self>;
#[cfg(feature = "cuda")]
fn cuda_generate_instance_from_str(
seed: u64,
seeds: [u64; 8],
difficulty: &str,
dev: &Arc<CudaDevice>,
funcs: HashMap<&'static str, CudaFunction>,
) -> Result<Self> {
Self::cuda_generate_instance(seed, &serde_json::from_str(difficulty)?, dev, funcs)
Self::cuda_generate_instance(seeds, &serde_json::from_str(difficulty)?, dev, funcs)
}
#[cfg(feature = "cuda")]
fn cuda_generate_instance_from_vec(
seed: u64,
seeds: [u64; 8],
difficulty: &Vec<i32>,
dev: &Arc<CudaDevice>,
funcs: HashMap<&'static str, CudaFunction>,
) -> Result<Self> {
match difficulty.as_slice().try_into() {
Ok(difficulty) => Self::cuda_generate_instance_from_arr(seed, &difficulty, dev, funcs),
Ok(difficulty) => Self::cuda_generate_instance_from_arr(seeds, &difficulty, dev, funcs),
Err(_) => Err(anyhow!("Invalid difficulty length")),
}
}
#[cfg(feature = "cuda")]
fn cuda_generate_instance_from_arr(
seed: u64,
seeds: [u64; 8],
difficulty: &[i32; N],
dev: &Arc<CudaDevice>,
funcs: HashMap<&'static str, CudaFunction>,
) -> Result<Self> {
Self::cuda_generate_instance(seed, &U::from_arr(difficulty), dev, funcs)
Self::cuda_generate_instance(seeds, &U::from_arr(difficulty), dev, funcs)
}
fn verify_solution(&self, solution: &T) -> Result<()>;
@ -92,3 +93,20 @@ pub struct CudaKernel {
pub src: &'static str,
pub funcs: &'static [&'static str],
}
pub struct RngArray {
rngs: [StdRng; 8],
index: u32,
}
impl RngArray {
pub fn new(seeds: [u64; 8]) -> Self {
let rngs = seeds.map(StdRng::seed_from_u64);
RngArray { rngs, index: 0 }
}
pub fn get_mut(&mut self) -> &mut StdRng {
self.index = (&mut self.rngs[self.index as usize]).gen_range(0..8);
&mut self.rngs[self.index as usize]
}
}

View File

@ -1,10 +1,6 @@
use anyhow::{anyhow, Result};
use ndarray::{Array2, Axis};
use rand::{
distributions::{Distribution, Uniform},
rngs::StdRng,
SeedableRng,
};
use rand::distributions::{Distribution, Uniform};
use serde::{
de::{self, SeqAccess, Visitor},
ser::SerializeSeq,
@ -14,6 +10,7 @@ use serde_json::{from_value, Map, Value};
#[cfg(feature = "cuda")]
use crate::CudaKernel;
use crate::RngArray;
#[cfg(feature = "cuda")]
use cudarc::driver::*;
#[cfg(feature = "cuda")]
@ -59,7 +56,7 @@ impl TryFrom<Map<String, Value>> for Solution {
#[derive(Serialize, Deserialize, Debug)]
pub struct Challenge {
pub seed: u64,
pub seeds: [u64; 8],
pub difficulty: Difficulty,
pub clauses: Vec<Vec<i32>>,
}
@ -71,17 +68,17 @@ pub const KERNEL: Option<CudaKernel> = None;
impl crate::ChallengeTrait<Solution, Difficulty, 2> for Challenge {
#[cfg(feature = "cuda")]
fn cuda_generate_instance(
seed: u64,
seeds: [u64; 8],
difficulty: &Difficulty,
dev: &Arc<CudaDevice>,
mut funcs: HashMap<&'static str, CudaFunction>,
) -> Result<Self> {
// TIG dev bounty available for a GPU optimisation for instance generation!
Self::generate_instance(seed, difficulty)
Self::generate_instance(seeds, difficulty)
}
fn generate_instance(seed: u64, difficulty: &Difficulty) -> Result<Self> {
let mut rng = StdRng::seed_from_u64(seed);
fn generate_instance(seeds: [u64; 8], difficulty: &Difficulty) -> Result<Self> {
let mut rngs = RngArray::new(seeds);
let num_clauses = (difficulty.num_variables as f64
* difficulty.clauses_to_variables_percent as f64
/ 100.0)
@ -92,11 +89,12 @@ impl crate::ChallengeTrait<Solution, Difficulty, 2> for Challenge {
let neg_distr = Uniform::new(0, 2);
// Generate the clauses array.
let clauses_array = Array2::from_shape_fn((num_clauses, 3), |_| var_distr.sample(&mut rng));
let clauses_array =
Array2::from_shape_fn((num_clauses, 3), |_| var_distr.sample(rngs.get_mut()));
// Generate the negations array.
let negations = Array2::from_shape_fn((num_clauses, 3), |_| {
if neg_distr.sample(&mut rng) == 0 {
if neg_distr.sample(rngs.get_mut()) == 0 {
-1
} else {
1
@ -113,7 +111,7 @@ impl crate::ChallengeTrait<Solution, Difficulty, 2> for Challenge {
.collect();
Ok(Self {
seed,
seeds,
difficulty: difficulty.clone(),
clauses,
})

View File

@ -1,10 +1,6 @@
use crate::{ChallengeTrait, DifficultyTrait, SolutionTrait};
use crate::{ChallengeTrait, DifficultyTrait, RngArray, SolutionTrait};
use anyhow::{anyhow, Ok, Result};
use rand::{
distributions::{Distribution, Uniform},
rngs::StdRng,
SeedableRng,
};
use rand::distributions::{Distribution, Uniform};
use serde::{Deserialize, Serialize};
use serde_json::{from_value, Map, Value};
@ -51,7 +47,7 @@ impl TryFrom<Map<String, Value>> for Solution {
#[derive(Serialize, Deserialize, Debug)]
pub struct Challenge {
pub seed: u64,
pub seeds: [u64; 8],
pub difficulty: Difficulty,
pub vector_database: Vec<Vec<f32>>,
pub query_vectors: Vec<Vec<f32>>,
@ -73,28 +69,28 @@ pub const KERNEL: Option<CudaKernel> = None;
impl ChallengeTrait<Solution, Difficulty, 2> for Challenge {
#[cfg(feature = "cuda")]
fn cuda_generate_instance(
seed: u64,
seeds: [u64; 8],
difficulty: &Difficulty,
dev: &Arc<CudaDevice>,
mut funcs: HashMap<&'static str, CudaFunction>,
) -> Result<Self> {
// TIG dev bounty available for a GPU optimisation for instance generation!
Self::generate_instance(seed, difficulty)
Self::generate_instance(seeds, difficulty)
}
fn generate_instance(seed: u64, difficulty: &Difficulty) -> Result<Self> {
let mut rng = StdRng::seed_from_u64(seed);
fn generate_instance(seeds: [u64; 8], difficulty: &Difficulty) -> Result<Self> {
let mut rngs = RngArray::new(seeds);
let uniform = Uniform::from(0.0..1.0);
let search_vectors = (0..100000)
.map(|_| (0..250).map(|_| uniform.sample(&mut rng)).collect())
.map(|_| (0..250).map(|_| uniform.sample(rngs.get_mut())).collect())
.collect();
let query_vectors = (0..difficulty.num_queries)
.map(|_| (0..250).map(|_| uniform.sample(&mut rng)).collect())
.map(|_| (0..250).map(|_| uniform.sample(rngs.get_mut())).collect())
.collect();
let max_distance = 6.0 - (difficulty.better_than_baseline as f32) / 1000.0;
Ok(Self {
seed,
seeds,
difficulty: difficulty.clone(),
vector_database: search_vectors,
query_vectors,

View File

@ -1,10 +1,11 @@
use anyhow::{anyhow, Result};
use rand::{rngs::StdRng, Rng, SeedableRng};
use rand::Rng;
use serde::{Deserialize, Serialize};
use serde_json::{from_value, Map, Value};
#[cfg(feature = "cuda")]
use crate::CudaKernel;
use crate::RngArray;
#[cfg(feature = "cuda")]
use cudarc::driver::*;
#[cfg(feature = "cuda")]
@ -46,7 +47,7 @@ impl TryFrom<Map<String, Value>> for Solution {
#[derive(Serialize, Deserialize, Debug)]
pub struct Challenge {
pub seed: u64,
pub seeds: [u64; 8],
pub difficulty: Difficulty,
pub demands: Vec<i32>,
pub distance_matrix: Vec<Vec<i32>>,
@ -61,27 +62,34 @@ pub const KERNEL: Option<CudaKernel> = None;
impl crate::ChallengeTrait<Solution, Difficulty, 2> for Challenge {
#[cfg(feature = "cuda")]
fn cuda_generate_instance(
seed: u64,
seeds: [u64; 8],
difficulty: &Difficulty,
dev: &Arc<CudaDevice>,
mut funcs: HashMap<&'static str, CudaFunction>,
) -> Result<Self> {
// TIG dev bounty available for a GPU optimisation for instance generation!
Self::generate_instance(seed, difficulty)
Self::generate_instance(seeds, difficulty)
}
fn generate_instance(seed: u64, difficulty: &Difficulty) -> Result<Challenge> {
let mut rng: StdRng = StdRng::seed_from_u64(seed);
fn generate_instance(seeds: [u64; 8], difficulty: &Difficulty) -> Result<Challenge> {
let mut rngs = RngArray::new(seeds);
let num_nodes = difficulty.num_nodes;
let max_capacity = 100;
let mut node_positions: Vec<(f64, f64)> = (0..num_nodes)
.map(|_| (rng.gen::<f64>() * 500.0, rng.gen::<f64>() * 500.0))
.map(|_| {
(
rngs.get_mut().gen::<f64>() * 500.0,
rngs.get_mut().gen::<f64>() * 500.0,
)
})
.collect();
node_positions[0] = (250.0, 250.0); // Depot is node 0, and in the center
let mut demands: Vec<i32> = (0..num_nodes).map(|_| rng.gen_range(15..30)).collect();
let mut demands: Vec<i32> = (0..num_nodes)
.map(|_| rngs.get_mut().gen_range(15..30))
.collect();
demands[0] = 0; // Depot demand is 0
let distance_matrix: Vec<Vec<i32>> = node_positions
@ -112,7 +120,7 @@ impl crate::ChallengeTrait<Solution, Difficulty, 2> for Challenge {
/ 1000) as i32;
Ok(Challenge {
seed,
seeds,
difficulty: difficulty.clone(),
demands,
distance_matrix,

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, u64_from_str};
use tig_utils::{jsonify, u32_from_str, u64s_from_str};
pub use tig_utils::{Frontier, Point, PreciseNumber, Transaction, U256};
serializable_struct_with_getters! {
@ -109,8 +109,12 @@ serializable_struct_with_getters! {
}
}
impl BenchmarkSettings {
pub fn calc_seed(&self, nonce: u64) -> u64 {
u64_from_str(jsonify(&self).as_str()) ^ nonce
pub fn calc_seeds(&self, nonce: u64) -> [u64; 8] {
let mut seeds = u64s_from_str(jsonify(&self).as_str());
for seed in seeds.iter_mut() {
*seed ^= nonce;
}
seeds
}
}
serializable_struct_with_getters! {

View File

@ -1,5 +1,5 @@
use md5;
use sha3::{Digest, Keccak256};
use sha3::{Digest, Keccak512};
pub fn md5_from_str(input: &str) -> String {
md5_from_bytes(input.as_bytes())
@ -15,13 +15,17 @@ pub fn u32_from_str(input: &str) -> u32 {
u32::from_le_bytes(bytes)
}
pub fn u64_from_str(input: &str) -> u64 {
let mut hasher = Keccak256::new();
pub fn u64s_from_str(input: &str) -> [u64; 8] {
let mut hasher = Keccak512::new();
hasher.update(input.as_bytes());
let result = hasher.finalize();
u64::from_le_bytes(
result.as_slice()[0..8]
let mut output = [0u64; 8];
for i in 0..8 {
let bytes = result[i * 8..(i + 1) * 8]
.try_into()
.expect("Should not ever panic.."),
)
.expect("Should not ever panic..");
output[i] = u64::from_le_bytes(bytes);
}
output
}

View File

@ -12,29 +12,29 @@ pub fn compute_solution(
max_memory: u64,
max_fuel: u64,
) -> Result<Option<SolutionData>> {
let seed = settings.calc_seed(nonce);
let seeds = settings.calc_seeds(nonce);
let serialized_challenge = match settings.challenge_id.as_str() {
"c001" => {
let challenge =
satisfiability::Challenge::generate_instance_from_vec(seed, &settings.difficulty)
satisfiability::Challenge::generate_instance_from_vec(seeds, &settings.difficulty)
.unwrap();
bincode::serialize(&challenge).unwrap()
}
"c002" => {
let challenge =
vehicle_routing::Challenge::generate_instance_from_vec(seed, &settings.difficulty)
vehicle_routing::Challenge::generate_instance_from_vec(seeds, &settings.difficulty)
.unwrap();
bincode::serialize(&challenge).unwrap()
}
"c003" => {
let challenge =
knapsack::Challenge::generate_instance_from_vec(seed, &settings.difficulty)
knapsack::Challenge::generate_instance_from_vec(seeds, &settings.difficulty)
.unwrap();
bincode::serialize(&challenge).unwrap()
}
"c004" => {
let challenge =
vector_search::Challenge::generate_instance_from_vec(seed, &settings.difficulty)
vector_search::Challenge::generate_instance_from_vec(seeds, &settings.difficulty)
.unwrap();
bincode::serialize(&challenge).unwrap()
}
@ -88,7 +88,7 @@ pub fn compute_solution(
// Get runtime signature
let runtime_signature_u64 = store.get_runtime_signature();
let runtime_signature = (runtime_signature_u64 as u32) ^ ((runtime_signature_u64 >> 32) as u32);
let fuel_consumed = store.get_fuel().unwrap();
let fuel_consumed = max_fuel - store.get_fuel().unwrap();
// Read solution from memory
let mut solution_len_bytes = [0u8; 4];
memory
@ -121,11 +121,11 @@ pub fn verify_solution(
nonce: u64,
solution: &Solution,
) -> Result<()> {
let seed = settings.calc_seed(nonce);
let seeds = settings.calc_seeds(nonce);
match settings.challenge_id.as_str() {
"c001" => {
let challenge =
satisfiability::Challenge::generate_instance_from_vec(seed, &settings.difficulty)
satisfiability::Challenge::generate_instance_from_vec(seeds, &settings.difficulty)
.expect("Failed to generate satisfiability instance");
match satisfiability::Solution::try_from(solution.clone()) {
Ok(solution) => challenge.verify_solution(&solution),
@ -136,7 +136,7 @@ pub fn verify_solution(
}
"c002" => {
let challenge =
vehicle_routing::Challenge::generate_instance_from_vec(seed, &settings.difficulty)
vehicle_routing::Challenge::generate_instance_from_vec(seeds, &settings.difficulty)
.expect("Failed to generate vehicle_routing instance");
match vehicle_routing::Solution::try_from(solution.clone()) {
Ok(solution) => challenge.verify_solution(&solution),
@ -147,7 +147,7 @@ pub fn verify_solution(
}
"c003" => {
let challenge =
knapsack::Challenge::generate_instance_from_vec(seed, &settings.difficulty)
knapsack::Challenge::generate_instance_from_vec(seeds, &settings.difficulty)
.expect("Failed to generate knapsack instance");
match knapsack::Solution::try_from(solution.clone()) {
Ok(solution) => challenge.verify_solution(&solution),
@ -158,7 +158,7 @@ pub fn verify_solution(
}
"c004" => {
let challenge =
vector_search::Challenge::generate_instance_from_vec(seed, &settings.difficulty)
vector_search::Challenge::generate_instance_from_vec(seeds, &settings.difficulty)
.expect("Failed to generate vector_search instance");
match vector_search::Solution::try_from(solution.clone()) {
Ok(solution) => challenge.verify_solution(&solution),