Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Standartize fork activation logic #588

Merged
merged 5 commits into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 58 additions & 33 deletions consensus/core/src/config/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,31 @@ 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
}

pub fn is_within_range_from_activation(self, current_daa_score: u64, range: u64) -> bool {
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 +66,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 +106,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 after which the pre-deflationary period switches to the deflationary period
pub deflationary_phase_daa_score: u64,
Expand Down Expand Up @@ -117,10 +142,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 @@ -129,10 +154,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 @@ -141,10 +166,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 @@ -153,10 +178,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 @@ -165,10 +190,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 @@ -188,18 +213,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 @@ -322,7 +347,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 @@ -352,7 +377,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(),

// 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 @@ -385,7 +410,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 @@ -415,7 +440,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(),

// 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 @@ -447,7 +472,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 @@ -485,7 +510,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(),

skip_proof_of_work: false,
max_block_level: 250,
Expand All @@ -498,7 +523,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 @@ -538,7 +563,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(),

skip_proof_of_work: true, // For simnet only, PoW can be simulated by default
max_block_level: 250,
Expand All @@ -554,7 +579,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 @@ -584,7 +609,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(),

// 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
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,
);

let pruning_point_manager = PruningPointManager::new(
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