Skip to content
Merged
42 changes: 15 additions & 27 deletions blockprod/src/detail/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -883,21 +883,15 @@ mod produce_block {
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn cancel_received(#[case] seed: Seed) {
let override_chain_config = {
let net_upgrades = NetUpgrades::initialize(vec![
(
BlockHeight::new(0),
UpgradeVersion::ConsensusUpgrade(ConsensusUpgrade::IgnoreConsensus),
),
(
BlockHeight::new(1),
UpgradeVersion::ConsensusUpgrade(ConsensusUpgrade::PoW {
// Make difficulty impossible so the cancel from
// the mock job manager is always seen before
// solving the block
initial_difficulty: Uint256::ZERO.into(),
}),
),
])
let net_upgrades = NetUpgrades::initialize(vec![(
BlockHeight::new(0),
UpgradeVersion::ConsensusUpgrade(ConsensusUpgrade::PoW {
// Make difficulty impossible so the cancel from
// the mock job manager is always seen before
// solving the block
initial_difficulty: Uint256::ZERO.into(),
}),
)])
.expect("Net upgrade is valid");

Builder::new(ChainType::Regtest).net_upgrades(net_upgrades).build()
Expand Down Expand Up @@ -1014,18 +1008,12 @@ mod produce_block {
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn solved_pow_consensus() {
let override_chain_config = {
let net_upgrades = NetUpgrades::initialize(vec![
(
BlockHeight::new(0),
UpgradeVersion::ConsensusUpgrade(ConsensusUpgrade::IgnoreConsensus),
),
(
BlockHeight::new(1),
UpgradeVersion::ConsensusUpgrade(ConsensusUpgrade::PoW {
initial_difficulty: Uint256::MAX.into(),
}),
),
])
let net_upgrades = NetUpgrades::initialize(vec![(
BlockHeight::new(0),
UpgradeVersion::ConsensusUpgrade(ConsensusUpgrade::PoW {
initial_difficulty: Uint256::MAX.into(),
}),
)])
.expect("Net upgrade is valid");

Builder::new(ChainType::Regtest).net_upgrades(net_upgrades).build()
Expand Down
1 change: 0 additions & 1 deletion chainstate/src/detail/ban_score.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,6 @@ impl BanScore for ConsensusPoWError {
ConsensusPoWError::DecodingBitsFailed(_) => 100,
ConsensusPoWError::PreviousBitsDecodingFailed(_) => 0,
ConsensusPoWError::InvalidTargetBits(_, _) => 100,
ConsensusPoWError::GenesisCannotHaveOngoingDifficulty => 100,
ConsensusPoWError::InvalidBlockRewardMaturityDistance(_) => 0,
}
}
Expand Down
23 changes: 23 additions & 0 deletions common/src/chain/config/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use crate::{
EmissionScheduleTabular,
},
pos::get_initial_randomness,
pow::PoWChainConfigBuilder,
ConsensusUpgrade, Destination, GenBlock, Genesis, Mlt, NetUpgrades, PoWChainConfig,
UpgradeVersion,
},
Expand Down Expand Up @@ -249,6 +250,27 @@ impl Builder {
.collect::<BTreeMap<BlockHeight, Id<GenBlock>>>()
.into();

let pow_chain_config = {
let (_, genesis_upgrade_version) = net_upgrades
.version_at_height(BlockHeight::new(0))
.expect("Genesis must have an upgrade version");

let limit = match genesis_upgrade_version {
UpgradeVersion::SomeUpgrade => None,
UpgradeVersion::ConsensusUpgrade(consensus_upgrade) => match consensus_upgrade {
ConsensusUpgrade::IgnoreConsensus | ConsensusUpgrade::PoS { .. } => None,
ConsensusUpgrade::PoW { initial_difficulty } => {
let limit = (*initial_difficulty)
.try_into()
.expect("Genesis initial difficulty to be valid");
Some(limit)
}
},
};

PoWChainConfigBuilder::new(chain_type).limit(limit).build()
};

ChainConfig {
chain_type,
bip44_coin_type,
Expand All @@ -263,6 +285,7 @@ impl Builder {
max_future_block_time_offset,
max_no_signature_data_size,
max_depth_for_reorg,
pow_chain_config,
epoch_length,
sealed_epoch_distance_from_tip,
initial_randomness,
Expand Down
5 changes: 3 additions & 2 deletions common/src/chain/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ pub struct ChainConfig {
max_block_size_with_smart_contracts: usize,
max_no_signature_data_size: usize,
max_depth_for_reorg: BlockDistance,
pow_chain_config: PoWChainConfig,
epoch_length: NonZeroU64,
sealed_epoch_distance_from_tip: usize,
initial_randomness: H256,
Expand Down Expand Up @@ -456,8 +457,8 @@ impl ChainConfig {

// TODO: this should be part of net-upgrades. There should be no canonical definition of PoW for any chain config
#[must_use]
pub const fn get_proof_of_work_config(&self) -> PoWChainConfig {
PoWChainConfig::new(self.chain_type)
pub fn get_proof_of_work_config(&self) -> &PoWChainConfig {
&self.pow_chain_config
}

/// The minimum number of blocks required to be able to spend a utxo coming from a decommissioned pool
Expand Down
2 changes: 1 addition & 1 deletion common/src/chain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,5 @@ pub use pos::{
create_regtest_pos_config, create_testnet_pos_config, create_unittest_pos_config,
get_initial_randomness, initial_difficulty, DelegationId, PoSChainConfig, PoolId,
};
pub use pow::PoWChainConfig;
pub use pow::{PoWChainConfig, PoWChainConfigBuilder};
pub use upgrades::*;
55 changes: 46 additions & 9 deletions common/src/chain/pow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use std::time::Duration;
/// Chain Parameters for Proof of Work.
///
/// See in Bitcoin's [chainparams.cpp](https://github.com/bitcoin/bitcoin/blob/eca694a4e78d54ce4e29b388b3e81b06e55c2293/src/chainparams.cpp)
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct PoWChainConfig {
no_retargeting: bool,
/// Checks whether minimum difficulty can be used for the block
Expand All @@ -33,14 +33,8 @@ pub struct PoWChainConfig {
}

impl PoWChainConfig {
pub(crate) const fn new(chain_type: ChainType) -> Self {
PoWChainConfig {
no_retargeting: no_retargeting(chain_type),
allow_min_difficulty_blocks: allow_min_difficulty_blocks(chain_type),
limit: limit(chain_type),
// If block time is 2 minutes (which is my goal eventually), then 500 is equivalent to 100 in bitcoin's 10 minutes.
reward_maturity_distance: BlockDistance::new(500),
}
pub(crate) fn new(chain_type: ChainType) -> Self {
PoWChainConfigBuilder::new(chain_type).build()
}

pub const fn no_retargeting(&self) -> bool {
Expand Down Expand Up @@ -77,6 +71,49 @@ impl PoWChainConfig {
}
}

#[derive(Copy, Clone)]
pub struct PoWChainConfigBuilder {
chain_type: ChainType,
no_retargeting: Option<bool>,
allow_min_difficulty_blocks: Option<bool>,
limit: Option<Uint256>,
reward_maturity_distance: Option<BlockDistance>,
}

impl PoWChainConfigBuilder {
pub fn new(chain_type: ChainType) -> Self {
Self {
chain_type,
no_retargeting: None,
allow_min_difficulty_blocks: None,
limit: None,
reward_maturity_distance: None,
}
}

pub fn limit(mut self, value: Option<Uint256>) -> Self {
self.limit = value;
self
}

pub fn build(self) -> PoWChainConfig {
PoWChainConfig {
no_retargeting: self.no_retargeting.unwrap_or_else(|| no_retargeting(self.chain_type)),
allow_min_difficulty_blocks: self
.allow_min_difficulty_blocks
.unwrap_or_else(|| allow_min_difficulty_blocks(self.chain_type)),
limit: self.limit.unwrap_or_else(|| limit(self.chain_type)),

// If block time is 2 minutes (which is my goal
// eventually), then 500 is equivalent to 100 in bitcoin's
// 10 minutes.
reward_maturity_distance: self
.reward_maturity_distance
.unwrap_or_else(|| BlockDistance::new(500)),
}
}
}

const fn no_retargeting(chain_type: ChainType) -> bool {
match chain_type {
ChainType::Mainnet | ChainType::Testnet | ChainType::Signet => false,
Expand Down
2 changes: 0 additions & 2 deletions consensus/src/pow/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ pub enum ConsensusPoWError {
PoSInputDataProvided,
#[error("No input data was provided for PoW block generation")]
NoInputDataProvided,
#[error("Genesis block cannot have an ongoing difficulty")]
GenesisCannotHaveOngoingDifficulty,
#[error("Block reward maturity value {0} is invalid")]
InvalidBlockRewardMaturityDistance(BlockDistance),
}
2 changes: 1 addition & 1 deletion consensus/src/pow/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ struct PoW(PoWChainConfig);

impl PoW {
pub fn new(chain_config: &ChainConfig) -> Self {
PoW(chain_config.get_proof_of_work_config())
PoW(chain_config.get_proof_of_work_config().clone())
}

pub fn difficulty_limit(&self) -> Uint256 {
Expand Down
6 changes: 2 additions & 4 deletions consensus/src/pow/work.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub fn check_pow_consensus<H: BlockIndexHandle>(
let work_required = match pow_status {
PoWStatus::Threshold { initial_difficulty } => *initial_difficulty,
PoWStatus::Ongoing => match header.prev_block_id().classify(chain_config) {
GenBlockId::Genesis(_) => Err(ConsensusPoWError::GenesisCannotHaveOngoingDifficulty)?,
GenBlockId::Genesis(_) => PoW::new(chain_config).difficulty_limit().into(),
GenBlockId::Block(prev_id) => {
let prev_block_index = block_index_handle
.get_block_index(&prev_id)
Expand Down Expand Up @@ -119,9 +119,7 @@ where
match pow_status {
PoWStatus::Threshold { initial_difficulty } => Ok(*initial_difficulty),
PoWStatus::Ongoing => match prev_gen_block_index {
GenBlockIndex::Genesis(_) => {
Err(ConsensusPoWError::GenesisCannotHaveOngoingDifficulty)?
}
GenBlockIndex::Genesis(_) => Ok(PoW::new(chain_config).difficulty_limit().into()),
GenBlockIndex::Block(prev_block_index) => PoW::new(chain_config).get_work_required(
prev_block_index,
block_timestamp,
Expand Down