Skip to content

Commit

Permalink
feat: search by total zeros
Browse files Browse the repository at this point in the history
  • Loading branch information
HrikB committed Feb 1, 2024
1 parent 640986b commit 993ae28
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 71 deletions.
44 changes: 33 additions & 11 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use clap::{command, ArgGroup, Args, Parser, Subcommand};
use clap::{command, ArgAction, ArgGroup, Args, Parser, Subcommand};

#[derive(Parser)]
#[command(arg_required_else_help = true)]
Expand All @@ -9,7 +9,8 @@ pub struct Cli {
}

#[derive(Args)]
#[clap(group = ArgGroup::new("mining-pattern").required(true))]
#[clap(group = ArgGroup::new("search-criteria").multiple(true).required(true))]
#[clap(group = ArgGroup::new("zeros-threshold"))]
pub struct CliArgs {
#[arg(
id = "factory",
Expand All @@ -29,7 +30,7 @@ pub struct CliArgs {
long_help = "Set the GPU device ID.",
help_heading = "Crunching options"
)]
pub gpu_device_id: String,
pub gpu_device_id: u8,

#[arg(
id = "caller",
Expand All @@ -48,27 +49,48 @@ pub struct CliArgs {
help_heading = "Crunching options",
visible_alias = "crp"
)]
pub chain_id: Option<String>,
pub chain_id: Option<u64>,

#[arg(
id = "zeros",
long = "leading",
short = 'z',
group = "mining-pattern",
long_help = "Minimum number of leading zero bytes. Cannot be used in combination with -m.\n\nExample: -z 4.",
group = "search-criteria",
long_help = "Minimum number of leading zero bytes. Cannot be used in combination with --matching.\n\nExample: --leading 4.",
help_heading = "Crunching options"
)]
pub zeros: Option<String>,
pub zeros: Option<u8>,

#[arg(
id = "total",
long = "total",
short = 't',
group = "search-criteria",
long_help = "Total number of zero bytes. If used in conjunction with --leading, search criteria will be both thresholds. Pass --either to search for either threshold.\n\nExample: --total 32.",
help_heading = "Crunching options"
)]
pub total: Option<u8>,

#[arg(
id = "either",
long = "either",
long_help = "Search for either threshold. Must be used with --leading and --total.",
requires_all = &["zeros", "total"],
action = ArgAction::SetTrue,
help_heading = "Crunching options"
)]
pub either: bool,

#[arg(
id = "pattern",
long = "matching",
short = 'm',
group = "mining-pattern",
long_help = "Matching pattern for the contract address. Cannot be used in combination with -z.\n\nExample: -m ba5edXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXba5ed.",
help_heading = "Crunching options"
group = "search-criteria",
long_help = "Matching pattern for the contract address. Cannot be used in combination with --leading.\n\nExample: --matching ba5edXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXba5ed.",
help_heading = "Crunching options",
conflicts_with_all = &["zeros", "total"]
)]
pub pattern: Option<String>,
pub pattern: Option<Box<str>>,

#[arg(
id = "output",
Expand Down
8 changes: 8 additions & 0 deletions src/kernels/keccak256.cl
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,14 @@ static inline bool isMatching(uchar const *d)
return true;
}

#define hasTotal(d) ( \
(!(d[0])) + (!(d[1])) + (!(d[2])) + (!(d[3])) + \
(!(d[4])) + (!(d[5])) + (!(d[6])) + (!(d[7])) + \
(!(d[8])) + (!(d[9])) + (!(d[10])) + (!(d[11])) + \
(!(d[12])) + (!(d[13])) + (!(d[14])) + (!(d[15])) + \
(!(d[16])) + (!(d[17])) + (!(d[18])) + (!(d[19])) \
>= TOTAL_ZEROES)

#if LEADING_ZEROES == 8
#define hasLeading(d) (!(((uint*)d)[0]) && !(((uint*)d)[1]))
#elif LEADING_ZEROES == 7
Expand Down
135 changes: 99 additions & 36 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,23 @@ pub enum CreateXVariant {
}

pub enum RewardVariant {
LeadingZeros { leading_zeros_threshold: u8 },
Matching { pattern: String },
LeadingZeros {
zeros_threshold: u8,
},
TotalZeros {
zeros_threshold: u8,
},
LeadingAndTotalZeros {
leading_zeros_threshold: u8,
total_zeros_threshold: u8,
},
LeadingOrTotalZeros {
leading_zeros_threshold: u8,
total_zeros_threshold: u8,
},
Matching {
pattern: Box<str>,
},
}

pub enum SaltVariant {
Expand All @@ -52,32 +67,25 @@ pub enum SaltVariant {
Random,
}

pub struct Config {
pub struct Config<'a> {
gpu_device: u8,
factory_address: [u8; 20],
salt_variant: SaltVariant,
variant: CreateXVariant,
reward: RewardVariant,
output: String,
output: &'a str,
}

impl Config {
impl<'a> Config<'a> {
pub fn new(
gpu_device: &str,
factory_address: &String,
calling_address: Option<&String>,
chain_id: Option<&String>,
init_code_hash: Option<&String>,
gpu_device: u8,
factory_address: &str,
calling_address: Option<&str>,
chain_id: Option<u64>,
init_code_hash: Option<&str>,
reward: RewardVariant,
output: &String,
output: &'a str,
) -> Result<Self, &'static str> {
let chain_id = chain_id.map(|chain_id| {
chain_id
// Chain ids are technically 32 bytes, but 8 bytes should be enough
.parse::<u64>()
.expect("could not parse chain id argument as u64")
});

// convert main arguments from hex string to vector of bytes
let factory_address_vec =
hex::decode(factory_address).expect("could not decode factory address argument");
Expand Down Expand Up @@ -110,21 +118,21 @@ impl Config {
None => CreateXVariant::Create3 {},
};

// convert gpu argument to u8
let Ok(gpu_device) = gpu_device.parse::<u8>() else {
return Err("invalid gpu device value");
};

match &reward {
RewardVariant::LeadingZeros {
RewardVariant::LeadingZeros { zeros_threshold }
| RewardVariant::TotalZeros { zeros_threshold } => {
validate_zeros_threshold(zeros_threshold)?;
}
RewardVariant::LeadingOrTotalZeros {
leading_zeros_threshold,
total_zeros_threshold,
}
| RewardVariant::LeadingAndTotalZeros {
leading_zeros_threshold,
total_zeros_threshold,
} => {
if leading_zeros_threshold == &0 {
return Err("leading zeros threshold must be greater than 0");
}
if leading_zeros_threshold > &20 {
return Err("leading zeros threshold must be less than 20");
}
validate_zeros_threshold(leading_zeros_threshold)?;
validate_zeros_threshold(total_zeros_threshold)?;
}
RewardVariant::Matching { pattern } => {
if pattern.len() != 40 {
Expand All @@ -136,6 +144,17 @@ impl Config {
}
}

fn validate_zeros_threshold(threhsold: &u8) -> Result<(), &'static str> {
if threhsold == &0u8 {
return Err("threshold must be greater than 0");
}
if threhsold > &20u8 {
return Err("threshold must be less than 20");
}

Ok(())
}

let salt_variant = match (chain_id, calling_address) {
(Some(chain_id), Some(calling_address)) if calling_address != [0u8; 20] => {
SaltVariant::CrosschainSender {
Expand All @@ -156,7 +175,7 @@ impl Config {
salt_variant,
variant: create_variant,
reward,
output: output.to_string(),
output,
})
}
}
Expand Down Expand Up @@ -327,9 +346,26 @@ pub fn gpu(config: Config) -> ocl::Result<()> {
))?;

let threshold_string = match config.reward {
RewardVariant::LeadingZeros {
RewardVariant::LeadingZeros { zeros_threshold } => {
format!("with {} leading zero byte(s)", zeros_threshold)
}
RewardVariant::TotalZeros { zeros_threshold } => {
format!("with {} total zero byte(s)", zeros_threshold)
}
RewardVariant::LeadingAndTotalZeros {
leading_zeros_threshold,
} => format!("with {} leading zero byte(s)", leading_zeros_threshold),
total_zeros_threshold,
} => format!(
"with {} leading and {} total zero byte(s)",
leading_zeros_threshold, total_zeros_threshold
),
RewardVariant::LeadingOrTotalZeros {
leading_zeros_threshold,
total_zeros_threshold,
} => format!(
"with {} leading or {} total zero byte(s)",
leading_zeros_threshold, total_zeros_threshold
),
RewardVariant::Matching { ref pattern } => {
format!("matching pattern {}", pattern)
}
Expand Down Expand Up @@ -456,7 +492,7 @@ fn output_file(config: &Config) -> File {
.append(true)
.create(true)
.read(true)
.open(config.output.clone())
.open(config.output)
.unwrap_or_else(|_| panic!("Could not create or open {} file.", config.output))
}

Expand Down Expand Up @@ -488,11 +524,38 @@ fn mk_kernel_src(config: &Config) -> String {
};

match &config.reward {
RewardVariant::LeadingZeros {
RewardVariant::LeadingZeros { zeros_threshold } => {
writeln!(src, "#define LEADING_ZEROES {zeros_threshold}").unwrap();
writeln!(src, "#define SUCCESS_CONDITION() hasLeading(digest)").unwrap();
}
RewardVariant::TotalZeros { zeros_threshold } => {
writeln!(src, "#define LEADING_ZEROES 0").unwrap();
writeln!(src, "#define TOTAL_ZEROES {zeros_threshold}").unwrap();
writeln!(src, "#define SUCCESS_CONDITION() hasTotal(digest)").unwrap();
}
RewardVariant::LeadingAndTotalZeros {
leading_zeros_threshold,
total_zeros_threshold,
} => {
writeln!(src, "#define LEADING_ZEROES {leading_zeros_threshold}").unwrap();
writeln!(src, "#define SUCCESS_CONDITION() hasLeading(digest)").unwrap();
writeln!(src, "#define TOTAL_ZEROES {total_zeros_threshold}").unwrap();
writeln!(
src,
"#define SUCCESS_CONDITION() hasLeading(digest) && hasTotal(digest)"
)
.unwrap();
}
RewardVariant::LeadingOrTotalZeros {
leading_zeros_threshold,
total_zeros_threshold,
} => {
writeln!(src, "#define LEADING_ZEROES {leading_zeros_threshold}").unwrap();
writeln!(src, "#define TOTAL_ZEROES {total_zeros_threshold}").unwrap();
writeln!(
src,
"#define SUCCESS_CONDITION() hasLeading(digest) || hasTotal(digest)"
)
.unwrap();
}
RewardVariant::Matching { pattern } => {
writeln!(src, "#define LEADING_ZEROES 0").unwrap();
Expand Down
Loading

0 comments on commit 993ae28

Please sign in to comment.