Skip to content

Commit b7178ad

Browse files
Merge pull request #1252 from mintlayer/fix/ensure_always_consensus
Add function to ensure that consensus will never be IgnoreConsensus in production
2 parents fb69030 + 0252c01 commit b7178ad

File tree

3 files changed

+100
-0
lines changed

3 files changed

+100
-0
lines changed

common/src/chain/config/mod.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,57 @@ pub fn create_unit_test_config() -> ChainConfig {
637637
.build()
638638
}
639639

640+
/// This function ensure that IgnoreConsensus will never be used in anything other than regtest
641+
pub fn assert_no_ignore_consensus_in_chain_config(chain_config: &ChainConfig) {
642+
match chain_config.chain_type() {
643+
ChainType::Regtest => {
644+
return;
645+
}
646+
ChainType::Mainnet | ChainType::Testnet | ChainType::Signet => {}
647+
}
648+
649+
let upgrades = chain_config.net_upgrade();
650+
651+
let all_upgrades = upgrades.all_upgrades();
652+
653+
assert!(
654+
!all_upgrades.is_empty(),
655+
"Invalid chain config. There are no net-upgrades defined, not even for genesis."
656+
);
657+
658+
assert!(all_upgrades.len() >= 2, "Invalid chain config. There must be at least 2 net-upgrades defined, one for genesis and one for the first block after genesis.");
659+
660+
assert!(
661+
all_upgrades[0].0 == 0.into(),
662+
"Invalid chain config. The first net-upgrade must be at height 0"
663+
);
664+
665+
assert!(
666+
upgrades.consensus_status(0.into()) == RequiredConsensus::IgnoreConsensus,
667+
"Invalid chain config. The genesis net-upgrade must be IgnoreConsensus"
668+
);
669+
670+
assert!(
671+
upgrades.consensus_status(1.into()) != RequiredConsensus::IgnoreConsensus,
672+
"Invalid chain config. The net-upgrade at height 1 must not be IgnoreConsensus"
673+
);
674+
675+
for upgrade in all_upgrades.iter().skip(1) {
676+
let upgrade_height = &upgrade.0;
677+
let upgrade_data = &upgrade.1;
678+
679+
let consensus = upgrades.consensus_status(*upgrade_height);
680+
assert_ne!(
681+
RequiredConsensus::IgnoreConsensus,
682+
consensus,
683+
"Upgrade {:?} at height {} is ignoring consensus in net type {}. This is only allowed in regtest",
684+
upgrade_data,
685+
upgrade_height,
686+
chain_config.chain_type().name()
687+
)
688+
}
689+
}
690+
640691
#[cfg(test)]
641692
mod tests {
642693
use super::*;
@@ -816,4 +867,32 @@ mod tests {
816867
.build();
817868
assert_eq!(expected_epoch, config.sealed_epoch_index(&block_height));
818869
}
870+
871+
#[test]
872+
fn test_ignore_consensus_in_mainnet() {
873+
let config = create_mainnet();
874+
875+
assert_no_ignore_consensus_in_chain_config(&config);
876+
}
877+
878+
#[test]
879+
#[should_panic(
880+
expected = "Invalid chain config. There must be at least 2 net-upgrades defined, one for genesis and one for the first block after genesis."
881+
)]
882+
fn test_ignore_consensus_outside_regtest_in_no_upgrades() {
883+
let config =
884+
Builder::new(ChainType::Mainnet).net_upgrades(NetUpgrades::unit_tests()).build();
885+
886+
assert_no_ignore_consensus_in_chain_config(&config);
887+
}
888+
889+
#[test]
890+
#[should_panic(expected = "The net-upgrade at height 1 must not be IgnoreConsensus")]
891+
fn test_ignore_consensus_outside_regtest_with_deliberate_bad_upgrades() {
892+
let config = Builder::new(ChainType::Mainnet)
893+
.net_upgrades(NetUpgrades::deliberate_ignore_consensus_twice())
894+
.build();
895+
896+
assert_no_ignore_consensus_in_chain_config(&config);
897+
}
819898
}

common/src/chain/upgrades/netupgrade.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,20 @@ impl NetUpgrades<UpgradeVersion> {
4242
)])
4343
}
4444

45+
#[cfg(test)]
46+
pub fn deliberate_ignore_consensus_twice() -> Self {
47+
Self(vec![
48+
(
49+
BlockHeight::zero(),
50+
UpgradeVersion::ConsensusUpgrade(ConsensusUpgrade::IgnoreConsensus),
51+
),
52+
(
53+
BlockHeight::new(1),
54+
UpgradeVersion::ConsensusUpgrade(ConsensusUpgrade::IgnoreConsensus),
55+
),
56+
])
57+
}
58+
4559
pub fn regtest_with_pos() -> Self {
4660
Self(vec![
4761
(
@@ -57,6 +71,10 @@ impl NetUpgrades<UpgradeVersion> {
5771
),
5872
])
5973
}
74+
75+
pub fn all_upgrades(&self) -> &[(BlockHeight, UpgradeVersion)] {
76+
&self.0
77+
}
6078
}
6179

6280
pub trait Activate {

node-lib/src/runner.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use chainstate::{rpc::ChainstateRpcServer, ChainstateError, InitializationError}
3232
use common::{
3333
chain::{
3434
config::{
35+
assert_no_ignore_consensus_in_chain_config,
3536
regtest::{create_regtest_pos_genesis, create_regtest_pow_genesis},
3637
Builder as ChainConfigBuilder, ChainConfig, ChainType, EmissionScheduleTabular,
3738
},
@@ -86,6 +87,8 @@ async fn initialize(
8687
) -> Result<(subsystem::Manager, NodeController)> {
8788
let chain_config = Arc::new(chain_config);
8889

90+
assert_no_ignore_consensus_in_chain_config(&chain_config);
91+
8992
// INITIALIZE SUBSYSTEMS
9093

9194
let mut manager = subsystem::Manager::new("mintlayer");

0 commit comments

Comments
 (0)