feat: abs all options
This commit is contained in:
parent
756ddf8093
commit
262bb6bfbf
8 changed files with 291 additions and 210 deletions
59
src/avg.rs
Normal file
59
src/avg.rs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
|
use rayon::prelude::*;
|
||||||
|
use pow_sha256::ConfigBuilder;
|
||||||
|
|
||||||
|
use crate::utils::get_random;
|
||||||
|
|
||||||
|
#[derive(clap::Args, Debug, Clone)]
|
||||||
|
#[command(author, version, about, long_about = None)]
|
||||||
|
pub struct AvgGenerate {
|
||||||
|
#[arg(long)]
|
||||||
|
pub start: u32,
|
||||||
|
#[arg(long)]
|
||||||
|
pub max: u32,
|
||||||
|
#[arg(long)]
|
||||||
|
pub trials: u32,
|
||||||
|
#[arg(long)]
|
||||||
|
pub db: url::Url,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AvgGenerate {
|
||||||
|
pub fn run(&self) {
|
||||||
|
(self.start..self.max)
|
||||||
|
.into_par_iter()
|
||||||
|
.for_each(|difficulty| {
|
||||||
|
let mut summary = String::new();
|
||||||
|
let mut times: Vec<u128> = Vec::with_capacity(self.trials as usize);
|
||||||
|
|
||||||
|
for _ in 0..self.trials {
|
||||||
|
let salt = get_random(32);
|
||||||
|
let string = get_random(32);
|
||||||
|
let pow_config = ConfigBuilder::default().salt(salt.clone()).build().unwrap();
|
||||||
|
|
||||||
|
let start = Instant::now();
|
||||||
|
pow_config.prove_work(&string, difficulty).unwrap();
|
||||||
|
let finish = Instant::now();
|
||||||
|
let time_elapsed = finish.duration_since(start);
|
||||||
|
|
||||||
|
let time = time_elapsed.as_micros();
|
||||||
|
log::info!("Difficulty factor {difficulty} generated in {time}");
|
||||||
|
times.push(time);
|
||||||
|
}
|
||||||
|
let mean = (times.iter().sum::<u128>() / self.trials as u128) as u32;
|
||||||
|
let simple_variance: u32 = (times
|
||||||
|
.iter()
|
||||||
|
.map(|d| {
|
||||||
|
let x = (*d as u32 - mean) as u32;
|
||||||
|
x * x
|
||||||
|
})
|
||||||
|
.sum::<u32>())
|
||||||
|
/ (self.trials as u32 - 1);
|
||||||
|
let simple_variance: usize = (simple_variance as f32).sqrt() as usize;
|
||||||
|
let min = times.iter().min().unwrap();
|
||||||
|
let max = times.iter().max().unwrap();
|
||||||
|
summary = format!("{summary}\ndifficulty: {difficulty} min: {min} max: {max} mean: {mean} variance {simple_variance}");
|
||||||
|
println!("{summary}");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
45
src/cli.rs
Normal file
45
src/cli.rs
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
use clap::Parser;
|
||||||
|
|
||||||
|
use crate::avg::AvgGenerate;
|
||||||
|
use crate::diff::ForDiff;
|
||||||
|
use crate::gen::GenerateDeriveArgs;
|
||||||
|
use crate::migrate_pg::SledToPostgres;
|
||||||
|
use crate::print::PrintRes;
|
||||||
|
|
||||||
|
#[derive(Parser)] // requires `derive` feature
|
||||||
|
#[command(name = "cargo")]
|
||||||
|
#[command(bin_name = "cargo")]
|
||||||
|
pub enum PoWdCli {
|
||||||
|
Generate(GenerateDeriveArgs),
|
||||||
|
PrintDB(PrintRes),
|
||||||
|
SledToPostgres(SledToPostgres),
|
||||||
|
ForDiff(ForDiff),
|
||||||
|
AvgGenerate(AvgGenerate),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PoWdCli {
|
||||||
|
pub async fn run() {
|
||||||
|
match PoWdCli::parse() {
|
||||||
|
PoWdCli::Generate(args) => {
|
||||||
|
println!("{:?}", args);
|
||||||
|
args.run();
|
||||||
|
}
|
||||||
|
PoWdCli::PrintDB(args) => {
|
||||||
|
println!("{:?}", args);
|
||||||
|
args.run()
|
||||||
|
}
|
||||||
|
|
||||||
|
PoWdCli::SledToPostgres(args) => {
|
||||||
|
args.run().await;
|
||||||
|
}
|
||||||
|
PoWdCli::ForDiff(args) => {
|
||||||
|
println!("{:?}", args);
|
||||||
|
args.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
PoWdCli::AvgGenerate(args) => {
|
||||||
|
args.run().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
58
src/diff.rs
Normal file
58
src/diff.rs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
|
use pow_sha256::ConfigBuilder;
|
||||||
|
|
||||||
|
use crate::utils::get_random;
|
||||||
|
|
||||||
|
#[derive(clap::Args, Debug, Clone)]
|
||||||
|
#[command(author, version, about, long_about = None)]
|
||||||
|
pub struct ForDiff {
|
||||||
|
#[arg(long)]
|
||||||
|
pub factors: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ForDiff {
|
||||||
|
pub fn run(&self) {
|
||||||
|
let factors: Vec<u32> = self
|
||||||
|
.factors
|
||||||
|
.split(',')
|
||||||
|
.map(|d| d.parse::<u32>().unwrap())
|
||||||
|
.collect();
|
||||||
|
let mut summary = String::new();
|
||||||
|
for difficulty in factors.iter() {
|
||||||
|
let trials = 100;
|
||||||
|
let mut times: Vec<u128> = Vec::with_capacity(trials);
|
||||||
|
|
||||||
|
for _ in 0..trials {
|
||||||
|
let salt = get_random(32);
|
||||||
|
let string = get_random(32);
|
||||||
|
let pow_config = ConfigBuilder::default().salt(salt.clone()).build().unwrap();
|
||||||
|
|
||||||
|
let start = Instant::now();
|
||||||
|
pow_config.prove_work(&string, *difficulty).unwrap();
|
||||||
|
let finish = Instant::now();
|
||||||
|
let time_elapsed = finish.duration_since(start);
|
||||||
|
|
||||||
|
let time = time_elapsed.as_micros();
|
||||||
|
log::info!("Difficulty factor {difficulty} generated in {time}");
|
||||||
|
times.push(time);
|
||||||
|
}
|
||||||
|
let mean = (times.iter().sum::<u128>() / trials as u128) as u32;
|
||||||
|
let simple_variance: u32 = (times
|
||||||
|
.iter()
|
||||||
|
.map(|d| {
|
||||||
|
let x = (*d as u32 - mean) as u32;
|
||||||
|
x * x
|
||||||
|
})
|
||||||
|
.sum::<u32>())
|
||||||
|
/ (trials as u32 - 1);
|
||||||
|
let simple_variance: usize = (simple_variance as f32).sqrt() as usize;
|
||||||
|
let min = times.iter().min().unwrap();
|
||||||
|
let max = times.iter().max().unwrap();
|
||||||
|
summary = format!("{summary}\ndifficulty: {difficulty} min: {min} max: {max} mean: {mean} variance {simple_variance}");
|
||||||
|
}
|
||||||
|
println!("{summary}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
61
src/gen.rs
Normal file
61
src/gen.rs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
|
use pow_sha256::ConfigBuilder;
|
||||||
|
use rayon::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::utils::get_random;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(clap::Args, Debug, Clone)]
|
||||||
|
#[command(author, version, about, long_about = None)]
|
||||||
|
pub struct GenerateDeriveArgs {
|
||||||
|
#[arg(long)]
|
||||||
|
pub start: u32,
|
||||||
|
#[arg(long)]
|
||||||
|
pub max: u32,
|
||||||
|
#[arg(long)]
|
||||||
|
pub db: std::path::PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Log {
|
||||||
|
pub string: String,
|
||||||
|
pub salt: String,
|
||||||
|
pub time: u128,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GenerateDeriveArgs {
|
||||||
|
pub fn run(&self) {
|
||||||
|
let db = sled::open(&self.db).unwrap();
|
||||||
|
let salt = get_random(32);
|
||||||
|
let string = get_random(32);
|
||||||
|
let pow_config = ConfigBuilder::default().salt(salt.clone()).build().unwrap();
|
||||||
|
|
||||||
|
(self.start..self.max)
|
||||||
|
.into_par_iter()
|
||||||
|
.for_each(|difficulty| {
|
||||||
|
let start = Instant::now();
|
||||||
|
pow_config.prove_work(&string, difficulty).unwrap();
|
||||||
|
let finish = Instant::now();
|
||||||
|
let time_elapsed = finish.duration_since(start);
|
||||||
|
|
||||||
|
let time = time_elapsed.as_micros();
|
||||||
|
if difficulty % 10000 == 0 {
|
||||||
|
log::info!("Difficulty factor {difficulty} generated in {time}");
|
||||||
|
}
|
||||||
|
|
||||||
|
let log = Log {
|
||||||
|
salt: salt.clone(),
|
||||||
|
time,
|
||||||
|
string: string.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
db.insert(
|
||||||
|
bincode::serialize(&difficulty).unwrap(),
|
||||||
|
bincode::serialize(&log).unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
220
src/main.rs
220
src/main.rs
|
@ -2,221 +2,21 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
use clap::Parser;
|
mod avg;
|
||||||
use pow_sha256::ConfigBuilder;
|
mod cli;
|
||||||
use rayon::prelude::*;
|
mod db;
|
||||||
use serde::{Deserialize, Serialize};
|
mod diff;
|
||||||
use sqlx::postgres::PgPoolOptions;
|
mod print;
|
||||||
use std::time::Duration;
|
mod gen;
|
||||||
use std::time::Instant;
|
mod migrate_pg;
|
||||||
|
mod utils;
|
||||||
|
|
||||||
#[derive(Parser)] // requires `derive` feature
|
pub(crate) use gen::Log;
|
||||||
#[command(name = "cargo")]
|
|
||||||
#[command(bin_name = "cargo")]
|
|
||||||
enum PoWdCli {
|
|
||||||
Generate(GenerateDeriveArgs),
|
|
||||||
PrintDB(PrintRes),
|
|
||||||
Sqlite(Sqlite),
|
|
||||||
ForDiff(ForDiff),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(clap::Args, Debug, Clone)]
|
|
||||||
#[command(author, version, about, long_about = None)]
|
|
||||||
struct ForDiff {
|
|
||||||
#[arg(long)]
|
|
||||||
factors: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ForDiff {
|
|
||||||
fn run(&self) {
|
|
||||||
let factors: Vec<u32> = self
|
|
||||||
.factors
|
|
||||||
.split(',')
|
|
||||||
.map(|d| d.parse::<u32>().unwrap())
|
|
||||||
.collect();
|
|
||||||
let mut summary = String::new();
|
|
||||||
for difficulty in factors.iter() {
|
|
||||||
let trials = 100;
|
|
||||||
let mut times: Vec<u128> = Vec::with_capacity(trials);
|
|
||||||
|
|
||||||
for _ in 0..trials {
|
|
||||||
let salt = get_random(32);
|
|
||||||
let string = get_random(32);
|
|
||||||
let pow_config = ConfigBuilder::default().salt(salt.clone()).build().unwrap();
|
|
||||||
|
|
||||||
let start = Instant::now();
|
|
||||||
pow_config.prove_work(&string, *difficulty).unwrap();
|
|
||||||
let finish = Instant::now();
|
|
||||||
let time_elapsed = finish.duration_since(start);
|
|
||||||
|
|
||||||
let time = time_elapsed.as_micros();
|
|
||||||
log::info!("Difficulty factor {difficulty} generated in {time}");
|
|
||||||
times.push(time);
|
|
||||||
}
|
|
||||||
let mean = (times.iter().sum::<u128>() / trials as u128) as u32;
|
|
||||||
let simple_variance: u32 = (times
|
|
||||||
.iter()
|
|
||||||
.map(|d| {
|
|
||||||
let x = (*d as u32 - mean) as u32;
|
|
||||||
x * x
|
|
||||||
})
|
|
||||||
.sum::<u32>())
|
|
||||||
/ (trials as u32 - 1);
|
|
||||||
let simple_variance: usize = ((simple_variance as f32).sqrt() as usize);
|
|
||||||
let min = times.iter().min().unwrap();
|
|
||||||
let max = times.iter().max().unwrap();
|
|
||||||
summary = format!("{summary}\ndifficulty: {difficulty} min: {min} max: {max} mean: {mean} variance {simple_variance}");
|
|
||||||
}
|
|
||||||
println!("{summary}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(clap::Args, Debug, Clone)]
|
|
||||||
#[command(author, version, about, long_about = None)]
|
|
||||||
struct GenerateDeriveArgs {
|
|
||||||
#[arg(long)]
|
|
||||||
start: u32,
|
|
||||||
#[arg(long)]
|
|
||||||
max: u32,
|
|
||||||
#[arg(long)]
|
|
||||||
db: std::path::PathBuf,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
struct Log {
|
|
||||||
string: String,
|
|
||||||
salt: String,
|
|
||||||
time: u128,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GenerateDeriveArgs {
|
|
||||||
fn run(&self) {
|
|
||||||
let db = sled::open(&self.db).unwrap();
|
|
||||||
let salt = get_random(32);
|
|
||||||
let string = get_random(32);
|
|
||||||
let pow_config = ConfigBuilder::default().salt(salt.clone()).build().unwrap();
|
|
||||||
|
|
||||||
(self.start..self.max)
|
|
||||||
.into_par_iter()
|
|
||||||
.for_each(|difficulty| {
|
|
||||||
let start = Instant::now();
|
|
||||||
pow_config.prove_work(&string, difficulty).unwrap();
|
|
||||||
let finish = Instant::now();
|
|
||||||
let time_elapsed = finish.duration_since(start);
|
|
||||||
|
|
||||||
let time = time_elapsed.as_micros();
|
|
||||||
if difficulty % 10000 == 0 {
|
|
||||||
log::info!("Difficulty factor {difficulty} generated in {time}");
|
|
||||||
}
|
|
||||||
|
|
||||||
let log = Log {
|
|
||||||
salt: salt.clone(),
|
|
||||||
time,
|
|
||||||
string: string.clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
db.insert(
|
|
||||||
bincode::serialize(&difficulty).unwrap(),
|
|
||||||
bincode::serialize(&log).unwrap(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(clap::Args, Debug, Clone)]
|
|
||||||
#[command(author, version, about, long_about = None)]
|
|
||||||
struct PrintRes {
|
|
||||||
#[arg(long)]
|
|
||||||
db: std::path::PathBuf,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(clap::Args, Debug, Clone)]
|
|
||||||
#[command(author, version, about, long_about = None)]
|
|
||||||
struct Sqlite {
|
|
||||||
#[arg(long)]
|
|
||||||
sled: std::path::PathBuf,
|
|
||||||
#[arg(long)]
|
|
||||||
sqlite: url::Url,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(clap::Args, Debug, Clone)]
|
|
||||||
#[command(author, version, about, long_about = None)]
|
|
||||||
struct Plot {
|
|
||||||
#[arg(long)]
|
|
||||||
graph: std::path::PathBuf,
|
|
||||||
#[arg(long)]
|
|
||||||
sqlite: url::Url,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_rt::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
std::env::set_var("RUST_LOG", "INFO");
|
std::env::set_var("RUST_LOG", "INFO");
|
||||||
pretty_env_logger::init();
|
pretty_env_logger::init();
|
||||||
match PoWdCli::parse() {
|
cli::PoWdCli::run().await;
|
||||||
PoWdCli::Generate(args) => {
|
|
||||||
println!("{:?}", args);
|
|
||||||
args.run();
|
|
||||||
}
|
|
||||||
PoWdCli::PrintDB(args) => {
|
|
||||||
println!("{:?}", args);
|
|
||||||
let db = sled::open(args.db).unwrap();
|
|
||||||
for entry in db.iter() {
|
|
||||||
let (difficulty, entry) = entry.unwrap();
|
|
||||||
let log: Log = bincode::deserialize::<Log>(&entry[..]).unwrap();
|
|
||||||
let difficulty: u32 = bincode::deserialize::<u32>(&difficulty).unwrap();
|
|
||||||
println!("{difficulty}: {}", log.time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PoWdCli::Sqlite(args) => {
|
|
||||||
let sqlite_db = PgPoolOptions::new()
|
|
||||||
.max_connections(1)
|
|
||||||
.acquire_timeout(Duration::new(1000, 0))
|
|
||||||
.idle_timeout(Duration::new(1000, 0))
|
|
||||||
.connect(&args.sqlite.to_string())
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
sqlx::migrate!("./migrations/")
|
|
||||||
.run(&sqlite_db)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
println!("{:?}", args);
|
|
||||||
let sled_db = sled::open(args.sled).unwrap();
|
|
||||||
for entry in sled_db.iter() {
|
|
||||||
let (difficulty, entry) = entry.unwrap();
|
|
||||||
let log: Log = bincode::deserialize::<Log>(&entry[..]).unwrap();
|
|
||||||
let difficulty: u32 = bincode::deserialize::<u32>(&difficulty).unwrap();
|
|
||||||
|
|
||||||
let time = log.time as i32;
|
|
||||||
sqlx::query!(
|
|
||||||
"INSERT INTO logs (string, salt, time, difficulty) VALUES ($1, $2, $3, $4) ON CONFLICT(difficulty) DO NOTHING;",
|
|
||||||
log.string,
|
|
||||||
log.salt,
|
|
||||||
time,
|
|
||||||
difficulty as i32,
|
|
||||||
).execute(&sqlite_db).await.unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PoWdCli::ForDiff(args) => {
|
|
||||||
println!("{:?}", args);
|
|
||||||
args.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_random(len: usize) -> String {
|
|
||||||
use std::iter;
|
|
||||||
|
|
||||||
use rand::{distributions::Alphanumeric, rngs::ThreadRng, thread_rng, Rng};
|
|
||||||
|
|
||||||
let mut rng: ThreadRng = thread_rng();
|
|
||||||
|
|
||||||
iter::repeat(())
|
|
||||||
.map(|()| rng.sample(Alphanumeric))
|
|
||||||
.map(char::from)
|
|
||||||
.take(len)
|
|
||||||
.collect::<String>()
|
|
||||||
}
|
}
|
||||||
|
|
25
src/migrate_pg.rs
Normal file
25
src/migrate_pg.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
use crate::db;
|
||||||
|
use crate::Log;
|
||||||
|
|
||||||
|
#[derive(clap::Args, Debug, Clone)]
|
||||||
|
#[command(author, version, about, long_about = None)]
|
||||||
|
pub struct SledToPostgres {
|
||||||
|
#[arg(long)]
|
||||||
|
pub sled: std::path::PathBuf,
|
||||||
|
#[arg(long)]
|
||||||
|
pub pg: url::Url,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SledToPostgres {
|
||||||
|
pub async fn run(&self) {
|
||||||
|
let pool = db::DB::new(&self.pg, 1).await;
|
||||||
|
let sled_db = sled::open(&self.sled).unwrap();
|
||||||
|
for entry in sled_db.iter() {
|
||||||
|
let (difficulty, entry) = entry.unwrap();
|
||||||
|
let log: Log = bincode::deserialize::<Log>(&entry[..]).unwrap();
|
||||||
|
let difficulty: u32 = bincode::deserialize::<u32>(&difficulty).unwrap();
|
||||||
|
|
||||||
|
pool.write_log(&log, difficulty).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
src/print.rs
Normal file
20
src/print.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
use crate::Log;
|
||||||
|
|
||||||
|
#[derive(clap::Args, Debug, Clone)]
|
||||||
|
#[command(author, version, about, long_about = None)]
|
||||||
|
pub struct PrintRes {
|
||||||
|
#[arg(long)]
|
||||||
|
pub db: std::path::PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrintRes {
|
||||||
|
pub fn run(&self) {
|
||||||
|
let db = sled::open(&self.db).unwrap();
|
||||||
|
for entry in db.iter() {
|
||||||
|
let (difficulty, entry) = entry.unwrap();
|
||||||
|
let log: Log = bincode::deserialize::<Log>(&entry[..]).unwrap();
|
||||||
|
let difficulty: u32 = bincode::deserialize::<u32>(&difficulty).unwrap();
|
||||||
|
println!("{difficulty}: {}", log.time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
src/utils.rs
Normal file
13
src/utils.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
pub fn get_random(len: usize) -> String {
|
||||||
|
use std::iter;
|
||||||
|
|
||||||
|
use rand::{distributions::Alphanumeric, rngs::ThreadRng, thread_rng, Rng};
|
||||||
|
|
||||||
|
let mut rng: ThreadRng = thread_rng();
|
||||||
|
|
||||||
|
iter::repeat(())
|
||||||
|
.map(|()| rng.sample(Alphanumeric))
|
||||||
|
.map(char::from)
|
||||||
|
.take(len)
|
||||||
|
.collect::<String>()
|
||||||
|
}
|
Reference in a new issue