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

Return initial difficulty for when the previous block is Genesis #1136

Merged
merged 11 commits into from
Aug 8, 2023
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
alfiedotwtf marked this conversation as resolved.
Show resolved Hide resolved
#[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
Loading