Skip to content

Commit

Permalink
Standartize fork activation logic (kaspanet#588)
Browse files Browse the repository at this point in the history
* Use ForkActivation for all fork activations

* Avoid using negation in some ifs

* Add is_within_range_from_activation

* Move 'is always' check inside is_within_range_from_activation

* lints
  • Loading branch information
someone235 authored and biryukovmaxim committed Nov 7, 2024
1 parent d1cb457 commit 8069be5
Show file tree
Hide file tree
Showing 12 changed files with 106 additions and 75 deletions.
93 changes: 60 additions & 33 deletions consensus/core/src/config/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,33 @@ use std::{
time::{SystemTime, UNIX_EPOCH},
};

#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct ForkActivation(u64);

impl ForkActivation {
pub const fn new(daa_score: u64) -> Self {
Self(daa_score)
}

pub const fn never() -> Self {
Self(u64::MAX)
}

pub const fn always() -> Self {
Self(0)
}

pub fn is_active(self, current_daa_score: u64) -> bool {
current_daa_score >= self.0
}

/// Checks if the fork was "recently" activated, i.e., in the time frame of the provided range.
/// This function returns false for forks that were always active, since they were never activated.
pub fn is_within_range_from_activation(self, current_daa_score: u64, range: u64) -> bool {
self != Self::always() && self.is_active(current_daa_score) && current_daa_score < self.0 + range
}
}

/// Consensus parameters. Contains settings and configurations which are consensus-sensitive.
/// Changing one of these on a network node would exclude and prevent it from reaching consensus
/// with the other unmodified nodes.
Expand All @@ -41,7 +68,7 @@ pub struct Params {
pub target_time_per_block: u64,

/// DAA score from which the window sampling starts for difficulty and past median time calculation
pub sampling_activation_daa_score: u64,
pub sampling_activation: ForkActivation,

/// Defines the highest allowed proof of work difficulty value for a block as a [`Uint256`]
pub max_difficulty_target: Uint256,
Expand Down Expand Up @@ -81,7 +108,7 @@ pub struct Params {
pub storage_mass_parameter: u64,

/// DAA score from which storage mass calculation and transaction mass field are activated as a consensus rule
pub storage_mass_activation_daa_score: u64,
pub storage_mass_activation: ForkActivation,

/// DAA score from which tx engine supports kip10 opcodes: OpInputAmount, OpInputSpk, OpOutputAmount, OpOutputSpk
pub kip10_activation_daa_score: u64,
Expand Down Expand Up @@ -120,10 +147,10 @@ impl Params {
#[inline]
#[must_use]
pub fn past_median_time_window_size(&self, selected_parent_daa_score: u64) -> usize {
if selected_parent_daa_score < self.sampling_activation_daa_score {
self.legacy_past_median_time_window_size()
} else {
if self.sampling_activation.is_active(selected_parent_daa_score) {
self.sampled_past_median_time_window_size()
} else {
self.legacy_past_median_time_window_size()
}
}

Expand All @@ -132,10 +159,10 @@ impl Params {
#[inline]
#[must_use]
pub fn timestamp_deviation_tolerance(&self, selected_parent_daa_score: u64) -> u64 {
if selected_parent_daa_score < self.sampling_activation_daa_score {
self.legacy_timestamp_deviation_tolerance
} else {
if self.sampling_activation.is_active(selected_parent_daa_score) {
self.new_timestamp_deviation_tolerance
} else {
self.legacy_timestamp_deviation_tolerance
}
}

Expand All @@ -144,10 +171,10 @@ impl Params {
#[inline]
#[must_use]
pub fn past_median_time_sample_rate(&self, selected_parent_daa_score: u64) -> u64 {
if selected_parent_daa_score < self.sampling_activation_daa_score {
1
} else {
if self.sampling_activation.is_active(selected_parent_daa_score) {
self.past_median_time_sample_rate
} else {
1
}
}

Expand All @@ -156,10 +183,10 @@ impl Params {
#[inline]
#[must_use]
pub fn difficulty_window_size(&self, selected_parent_daa_score: u64) -> usize {
if selected_parent_daa_score < self.sampling_activation_daa_score {
self.legacy_difficulty_window_size
} else {
if self.sampling_activation.is_active(selected_parent_daa_score) {
self.sampled_difficulty_window_size
} else {
self.legacy_difficulty_window_size
}
}

Expand All @@ -168,10 +195,10 @@ impl Params {
#[inline]
#[must_use]
pub fn difficulty_sample_rate(&self, selected_parent_daa_score: u64) -> u64 {
if selected_parent_daa_score < self.sampling_activation_daa_score {
1
} else {
if self.sampling_activation.is_active(selected_parent_daa_score) {
self.difficulty_sample_rate
} else {
1
}
}

Expand All @@ -191,18 +218,18 @@ impl Params {
}

pub fn daa_window_duration_in_blocks(&self, selected_parent_daa_score: u64) -> u64 {
if selected_parent_daa_score < self.sampling_activation_daa_score {
self.legacy_difficulty_window_size as u64
} else {
if self.sampling_activation.is_active(selected_parent_daa_score) {
self.difficulty_sample_rate * self.sampled_difficulty_window_size as u64
} else {
self.legacy_difficulty_window_size as u64
}
}

fn expected_daa_window_duration_in_milliseconds(&self, selected_parent_daa_score: u64) -> u64 {
if selected_parent_daa_score < self.sampling_activation_daa_score {
self.target_time_per_block * self.legacy_difficulty_window_size as u64
} else {
if self.sampling_activation.is_active(selected_parent_daa_score) {
self.target_time_per_block * self.difficulty_sample_rate * self.sampled_difficulty_window_size as u64
} else {
self.target_time_per_block * self.legacy_difficulty_window_size as u64
}
}

Expand Down Expand Up @@ -325,7 +352,7 @@ pub const MAINNET_PARAMS: Params = Params {
past_median_time_sample_rate: Bps::<1>::past_median_time_sample_rate(),
past_median_time_sampled_window_size: MEDIAN_TIME_SAMPLED_WINDOW_SIZE,
target_time_per_block: 1000,
sampling_activation_daa_score: u64::MAX,
sampling_activation: ForkActivation::never(),
max_difficulty_target: MAX_DIFFICULTY_TARGET,
max_difficulty_target_f64: MAX_DIFFICULTY_TARGET_AS_F64,
difficulty_sample_rate: Bps::<1>::difficulty_adjustment_sample_rate(),
Expand Down Expand Up @@ -355,7 +382,7 @@ pub const MAINNET_PARAMS: Params = Params {
max_block_mass: 500_000,

storage_mass_parameter: STORAGE_MASS_PARAMETER,
storage_mass_activation_daa_score: u64::MAX,
storage_mass_activation: ForkActivation::never(),
kip10_activation_daa_score: u64::MAX,

// deflationary_phase_daa_score is the DAA score after which the pre-deflationary period
Expand Down Expand Up @@ -389,7 +416,7 @@ pub const TESTNET_PARAMS: Params = Params {
past_median_time_sample_rate: Bps::<1>::past_median_time_sample_rate(),
past_median_time_sampled_window_size: MEDIAN_TIME_SAMPLED_WINDOW_SIZE,
target_time_per_block: 1000,
sampling_activation_daa_score: u64::MAX,
sampling_activation: ForkActivation::never(),
max_difficulty_target: MAX_DIFFICULTY_TARGET,
max_difficulty_target_f64: MAX_DIFFICULTY_TARGET_AS_F64,
difficulty_sample_rate: Bps::<1>::difficulty_adjustment_sample_rate(),
Expand Down Expand Up @@ -419,7 +446,7 @@ pub const TESTNET_PARAMS: Params = Params {
max_block_mass: 500_000,

storage_mass_parameter: STORAGE_MASS_PARAMETER,
storage_mass_activation_daa_score: u64::MAX,
storage_mass_activation: ForkActivation::never(),
kip10_activation_daa_score: u64::MAX,
// deflationary_phase_daa_score is the DAA score after which the pre-deflationary period
// switches to the deflationary period. This number is calculated as follows:
Expand Down Expand Up @@ -451,7 +478,7 @@ pub const TESTNET11_PARAMS: Params = Params {
legacy_timestamp_deviation_tolerance: LEGACY_TIMESTAMP_DEVIATION_TOLERANCE,
new_timestamp_deviation_tolerance: NEW_TIMESTAMP_DEVIATION_TOLERANCE,
past_median_time_sampled_window_size: MEDIAN_TIME_SAMPLED_WINDOW_SIZE,
sampling_activation_daa_score: 0, // Sampling is activated from network inception
sampling_activation: ForkActivation::always(), // Sampling is activated from network inception
max_difficulty_target: MAX_DIFFICULTY_TARGET,
max_difficulty_target_f64: MAX_DIFFICULTY_TARGET_AS_F64,
sampled_difficulty_window_size: DIFFICULTY_SAMPLED_WINDOW_SIZE as usize,
Expand Down Expand Up @@ -489,7 +516,7 @@ pub const TESTNET11_PARAMS: Params = Params {
max_block_mass: 500_000,

storage_mass_parameter: STORAGE_MASS_PARAMETER,
storage_mass_activation_daa_score: 0,
storage_mass_activation: ForkActivation::always(),
kip10_activation_daa_score: u64::MAX,

skip_proof_of_work: false,
Expand All @@ -503,7 +530,7 @@ pub const SIMNET_PARAMS: Params = Params {
legacy_timestamp_deviation_tolerance: LEGACY_TIMESTAMP_DEVIATION_TOLERANCE,
new_timestamp_deviation_tolerance: NEW_TIMESTAMP_DEVIATION_TOLERANCE,
past_median_time_sampled_window_size: MEDIAN_TIME_SAMPLED_WINDOW_SIZE,
sampling_activation_daa_score: 0, // Sampling is activated from network inception
sampling_activation: ForkActivation::always(), // Sampling is activated from network inception
max_difficulty_target: MAX_DIFFICULTY_TARGET,
max_difficulty_target_f64: MAX_DIFFICULTY_TARGET_AS_F64,
sampled_difficulty_window_size: DIFFICULTY_SAMPLED_WINDOW_SIZE as usize,
Expand Down Expand Up @@ -543,7 +570,7 @@ pub const SIMNET_PARAMS: Params = Params {
max_block_mass: 500_000,

storage_mass_parameter: STORAGE_MASS_PARAMETER,
storage_mass_activation_daa_score: 0,
storage_mass_activation: ForkActivation::always(),
kip10_activation_daa_score: u64::MAX,

skip_proof_of_work: true, // For simnet only, PoW can be simulated by default
Expand All @@ -560,7 +587,7 @@ pub const DEVNET_PARAMS: Params = Params {
past_median_time_sample_rate: Bps::<1>::past_median_time_sample_rate(),
past_median_time_sampled_window_size: MEDIAN_TIME_SAMPLED_WINDOW_SIZE,
target_time_per_block: 1000,
sampling_activation_daa_score: u64::MAX,
sampling_activation: ForkActivation::never(),
max_difficulty_target: MAX_DIFFICULTY_TARGET,
max_difficulty_target_f64: MAX_DIFFICULTY_TARGET_AS_F64,
difficulty_sample_rate: Bps::<1>::difficulty_adjustment_sample_rate(),
Expand Down Expand Up @@ -590,7 +617,7 @@ pub const DEVNET_PARAMS: Params = Params {
max_block_mass: 500_000,

storage_mass_parameter: STORAGE_MASS_PARAMETER,
storage_mass_activation_daa_score: u64::MAX,
storage_mass_activation: ForkActivation::never(),
kip10_activation_daa_score: u64::MAX,

// deflationary_phase_daa_score is the DAA score after which the pre-deflationary period
Expand Down
4 changes: 2 additions & 2 deletions consensus/src/consensus/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ impl Consensus {
pruning_lock.clone(),
notification_root.clone(),
counters.clone(),
params.storage_mass_activation_daa_score,
params.storage_mass_activation,
));

let virtual_processor = Arc::new(VirtualStateProcessor::new(
Expand Down Expand Up @@ -753,7 +753,7 @@ impl ConsensusApi for Consensus {
}

fn calc_transaction_hash_merkle_root(&self, txs: &[Transaction], pov_daa_score: u64) -> Hash {
let storage_mass_activated = pov_daa_score > self.config.storage_mass_activation_daa_score;
let storage_mass_activated = self.config.storage_mass_activation.is_active(pov_daa_score);
calc_hash_merkle_root(txs.iter(), storage_mass_activated)
}

Expand Down
4 changes: 2 additions & 2 deletions consensus/src/consensus/services.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ impl ConsensusServices {
storage.block_window_cache_for_past_median_time.clone(),
params.max_difficulty_target,
params.target_time_per_block,
params.sampling_activation_daa_score,
params.sampling_activation,
params.legacy_difficulty_window_size,
params.sampled_difficulty_window_size,
params.min_difficulty_window_len,
Expand Down Expand Up @@ -146,7 +146,7 @@ impl ConsensusServices {
params.coinbase_maturity,
tx_script_cache_counters,
mass_calculator.clone(),
params.storage_mass_activation_daa_score,
params.storage_mass_activation,
params.kip10_activation_daa_score,
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use kaspa_consensus_core::{block::Block, merkle::calc_hash_merkle_root, tx::Tran

impl BlockBodyProcessor {
pub fn validate_body_in_isolation(self: &Arc<Self>, block: &Block) -> BlockProcessResult<u64> {
let storage_mass_activated = block.header.daa_score > self.storage_mass_activation_daa_score;
let storage_mass_activated = self.storage_mass_activation.is_active(block.header.daa_score);

Self::check_has_transactions(block)?;
Self::check_hash_merkle_root(block, storage_mass_activated)?;
Expand Down
8 changes: 4 additions & 4 deletions consensus/src/pipeline/body_processor/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use crossbeam_channel::{Receiver, Sender};
use kaspa_consensus_core::{
block::Block,
blockstatus::BlockStatus::{self, StatusHeaderOnly, StatusInvalid},
config::genesis::GenesisBlock,
config::{genesis::GenesisBlock, params::ForkActivation},
mass::MassCalculator,
tx::Transaction,
};
Expand Down Expand Up @@ -81,7 +81,7 @@ pub struct BlockBodyProcessor {
counters: Arc<ProcessingCounters>,

/// Storage mass hardfork DAA score
pub(crate) storage_mass_activation_daa_score: u64,
pub(crate) storage_mass_activation: ForkActivation,
}

impl BlockBodyProcessor {
Expand All @@ -108,7 +108,7 @@ impl BlockBodyProcessor {
pruning_lock: SessionLock,
notification_root: Arc<ConsensusNotificationRoot>,
counters: Arc<ProcessingCounters>,
storage_mass_activation_daa_score: u64,
storage_mass_activation: ForkActivation,
) -> Self {
Self {
receiver,
Expand All @@ -131,7 +131,7 @@ impl BlockBodyProcessor {
task_manager: BlockTaskDependencyManager::new(),
notification_root,
counters,
storage_mass_activation_daa_score,
storage_mass_activation,
}
}

Expand Down
8 changes: 4 additions & 4 deletions consensus/src/pipeline/virtual_processor/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ use kaspa_consensus_core::{
block::{BlockTemplate, MutableBlock, TemplateBuildMode, TemplateTransactionSelector},
blockstatus::BlockStatus::{StatusDisqualifiedFromChain, StatusUTXOValid},
coinbase::MinerData,
config::genesis::GenesisBlock,
config::{genesis::GenesisBlock, params::ForkActivation},
header::Header,
merkle::calc_hash_merkle_root,
pruning::PruningPointsList,
Expand Down Expand Up @@ -159,7 +159,7 @@ pub struct VirtualStateProcessor {
counters: Arc<ProcessingCounters>,

// Storage mass hardfork DAA score
pub(crate) storage_mass_activation_daa_score: u64,
pub(crate) storage_mass_activation: ForkActivation,
}

impl VirtualStateProcessor {
Expand Down Expand Up @@ -220,7 +220,7 @@ impl VirtualStateProcessor {
pruning_lock,
notification_root,
counters,
storage_mass_activation_daa_score: params.storage_mass_activation_daa_score,
storage_mass_activation: params.storage_mass_activation,
}
}

Expand Down Expand Up @@ -983,7 +983,7 @@ impl VirtualStateProcessor {
let parents_by_level = self.parents_manager.calc_block_parents(pruning_info.pruning_point, &virtual_state.parents);

// Hash according to hardfork activation
let storage_mass_activated = virtual_state.daa_score > self.storage_mass_activation_daa_score;
let storage_mass_activated = self.storage_mass_activation.is_active(virtual_state.daa_score);
let hash_merkle_root = calc_hash_merkle_root(txs.iter(), storage_mass_activated);

let accepted_id_merkle_root = kaspa_merkle::calc_merkle_root(virtual_state.accepted_tx_ids.iter().copied());
Expand Down
4 changes: 3 additions & 1 deletion consensus/src/pipeline/virtual_processor/utxo_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use kaspa_consensus_core::{
acceptance_data::{AcceptedTxEntry, MergesetBlockAcceptanceData},
api::args::TransactionValidationArgs,
coinbase::*,
config::params::ForkActivation,
hashing,
header::Header,
mass::Kip9Version,
Expand Down Expand Up @@ -328,7 +329,8 @@ impl VirtualStateProcessor {

// For non-activated nets (mainnet, TN10) we can update mempool rules to KIP9 beta asap. For
// TN11 we need to hard-fork consensus first (since the new beta rules are more permissive)
let kip9_version = if self.storage_mass_activation_daa_score == u64::MAX { Kip9Version::Beta } else { Kip9Version::Alpha };
let kip9_version =
if self.storage_mass_activation == ForkActivation::never() { Kip9Version::Beta } else { Kip9Version::Alpha };

// Calc the full contextual mass including storage mass
let contextual_mass = self
Expand Down
Loading

0 comments on commit 8069be5

Please sign in to comment.