pub struct ConsensusParams {
pub steal_target_kyns: u64,
}
impl Default for ConsensusParams {
fn default() -> Self {
Self {
steal_target_kyns: crate::constants::STEAL_TARGET_KYNS,
}
}
}
impl ConsensusParams {
pub fn calculate_hardware_anchor(&self) -> u64 {
crate::constants::BASE_ITERATIONS
}
pub fn required_iterations(&self, name: &str) -> u64 {
let normalized_name = crate::types::names::normalize_name(name);
let apex = crate::types::names::extract_apex_name(&normalized_name);
let label = apex
.strip_suffix(crate::constants::TLD_SUFFIX)
.unwrap_or(&apex);
self.required_iterations_by_label(label)
}
pub fn required_iterations_by_label(&self, label: &str) -> u64 {
if crate::config::is_dev_mode() {
return crate::constants::DEV_MODE_ITERATIONS;
}
let len = label.len();
let base = self.calculate_hardware_anchor();
let tm = crate::constants::TARGET_MINUTES as u64;
let calc =
|multiplier: u64| -> u64 { ((base as u128 * multiplier as u128) / tm as u128) as u64 };
match len {
0 | 1 => calc(crate::constants::CONSENSUS_SQUATTER_LEN_0_TO_1), 2 => calc(crate::constants::CONSENSUS_SQUATTER_LEN_2), 3 => calc(crate::constants::CONSENSUS_SQUATTER_LEN_3), 4 => calc(crate::constants::CONSENSUS_SQUATTER_LEN_4), 5 => calc(crate::constants::CONSENSUS_SQUATTER_LEN_5), 6 => calc(crate::constants::CONSENSUS_SQUATTER_LEN_6), 7 => calc(crate::constants::CONSENSUS_SQUATTER_LEN_7), 8..=10 => calc(crate::constants::CONSENSUS_SQUATTER_LEN_8_TO_10), 11..=17 => calc(crate::constants::CONSENSUS_SQUATTER_LEN_11_TO_17), 18..=20 => calc(crate::constants::CONSENSUS_SQUATTER_LEN_18_TO_20), 21..=63 => base, _ => base, }
}
pub fn steal_difficulty(&self, base_iterations: u64, kyns_idle: u64) -> u64 {
let idle_plus = kyns_idle.saturating_add(1) as u128;
let target_kyns = self.steal_target_kyns as u128;
let multiplier = if target_kyns > idle_plus {
let target_sq = target_kyns * target_kyns;
let idle_sq = idle_plus * idle_plus;
target_sq / idle_sq
} else {
1
};
let difficulty = (base_iterations as u128) * std::cmp::max(1, multiplier);
if difficulty > (u64::MAX as u128) {
u64::MAX
} else {
difficulty as u64
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_decay_length() {
let params = ConsensusParams::default();
let _pk = [0u8; 32];
let a = params.required_iterations("a");
let ab = params.required_iterations("ab");
let abc = params.required_iterations("abc");
if crate::config::is_dev_mode() {
assert_eq!(a, crate::constants::DEV_MODE_ITERATIONS);
assert_eq!(ab, crate::constants::DEV_MODE_ITERATIONS);
assert_eq!(abc, crate::constants::DEV_MODE_ITERATIONS);
} else {
assert!(a > ab);
assert!(ab > abc);
}
}
#[test]
fn test_steal_difficulty() {
let params = ConsensusParams::default();
let target = params.steal_target_kyns;
let diff_early = params.steal_difficulty(100, target / 2);
assert!(diff_early > 100);
let diff_late = params.steal_difficulty(100, target * 2);
assert_eq!(diff_late, 100); }
}