From 66a05715d7f0409203c796fae01f5f4a5e55cd17 Mon Sep 17 00:00:00 2001 From: Hansie Odendaal Date: Fri, 23 Aug 2024 16:59:02 +0200 Subject: [PATCH] fix use of network domain separated hashes in genesis block tests --- Cargo.lock | 23 +++ base_layer/core/Cargo.toml | 1 + base_layer/core/src/blocks/genesis_block.rs | 144 ++++++++++++++---- .../consensus/consensus_encoding/hashing.rs | 85 ++++++----- common/src/lib.rs | 10 +- 5 files changed, 196 insertions(+), 67 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 68779ae287..f74500aaca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5450,6 +5450,28 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "serial_test" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0bccbcf40c8938196944a3da0e133e031a33f4d6b72db3bda3cc556e361905d" +dependencies = [ + "lazy_static", + "parking_lot 0.11.2", + "serial_test_derive", +] + +[[package]] +name = "serial_test_derive" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2acd6defeddb41eb60bb468f8825d0cfd0c2a76bc03bfd235b6a1dc4f6a1ad5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "servo_arc" version = "0.3.0" @@ -6223,6 +6245,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", + "serial_test", "sha2 0.10.8", "sha3", "strum", diff --git a/base_layer/core/Cargo.toml b/base_layer/core/Cargo.toml index e516dbcc9a..62397a4d48 100644 --- a/base_layer/core/Cargo.toml +++ b/base_layer/core/Cargo.toml @@ -106,6 +106,7 @@ env_logger = "0.7.0" tempfile = "3.1.0" toml = { version = "0.5" } quickcheck = "1.0" +serial_test = "0.5" [build-dependencies] tari_common = { path = "../../common", features = ["build"], version = "1.3.0-pre.0" } diff --git a/base_layer/core/src/blocks/genesis_block.rs b/base_layer/core/src/blocks/genesis_block.rs index 6a73204677..09a614cab9 100644 --- a/base_layer/core/src/blocks/genesis_block.rs +++ b/base_layer/core/src/blocks/genesis_block.rs @@ -49,11 +49,6 @@ pub fn get_genesis_block(network: Network) -> ChainBlock { } } -/// Returns the genesis block hash for the selected network. -pub fn get_genesis_block_hash(network: Network) -> FixedHash { - *get_genesis_block(network).hash() -} - fn add_pre_mine_utxos_to_genesis_block(file: &str, block: &mut Block) { let mut utxos = Vec::new(); let mut counter = 1; @@ -474,10 +469,12 @@ fn get_raw_block(genesis_timestamp: &DateTime, not_before_proof: &P } } +// Note: Tests in this module are serialized to prevent domain separated network hash conflicts #[cfg(test)] mod test { use std::convert::TryFrom; + use serial_test::serial; use tari_common::get_static_genesis_block_hash; use tari_common_types::{epoch::VnEpoch, types::Commitment}; @@ -495,61 +492,103 @@ mod test { }; #[test] - #[cfg(tari_target_network_testnet)] + // #[cfg(tari_target_network_testnet)] + #[serial] fn esmeralda_genesis_sanity_check() { - let _ = Network::set_current(Network::Esmeralda); + let network = Network::Esmeralda; + set_network_by_env_var_or_force_set(network); + if !network_matches(network) { + panic!("Network could not be set ('esmeralda_genesis_sanity_check()')"); + } // Note: Generate new data for `pub fn get_esmeralda_genesis_block()` and `fn get_esmeralda_genesis_block_raw()` // if consensus values change, e.g. new pre_mine or other let block = get_esmeralda_genesis_block(); - check_block(Network::Esmeralda, &block, 164, 1); + check_block(network, &block, 164, 1); + assert_genesis_block_hash(network); + remove_network_env_var() } #[test] - #[cfg(tari_target_network_nextnet)] + #[serial] + // #[cfg(tari_target_network_nextnet)] fn nextnet_genesis_sanity_check() { - let _ = Network::set_current(Network::NextNet); + let network = Network::NextNet; + set_network_by_env_var_or_force_set(network); + if !network_matches(network) { + panic!("Network could not be set ('nextnet_genesis_sanity_check()')"); + } // Note: Generate new data for `pub fn get_nextnet_genesis_block()` and `fn get_stagenet_genesis_block_raw()` // if consensus values change, e.g. new pre_mine or other let block = get_nextnet_genesis_block(); - check_block(Network::NextNet, &block, 0, 0); + check_block(network, &block, 0, 0); + assert_genesis_block_hash(network); + remove_network_env_var() } #[test] - #[cfg(tari_target_network_mainnet)] + #[serial] + // #[cfg(tari_target_network_mainnet)] fn mainnet_genesis_sanity_check() { - let _ = Network::set_current(Network::MainNet); + let network = Network::MainNet; + set_network_by_env_var_or_force_set(network); + if !network_matches(network) { + panic!("Network could not be set ('mainnet_genesis_sanity_check()')"); + } // Note: Generate new data for `pub fn get_nextnet_genesis_block()` and `fn get_stagenet_genesis_block_raw()` // if consensus values change, e.g. new pre_mine or other let block = get_mainnet_genesis_block(); - check_block(Network::MainNet, &block, 164, 1); + check_block(network, &block, 164, 1); + assert_genesis_block_hash(network); + remove_network_env_var() } #[test] - #[cfg(tari_target_network_mainnet)] + #[serial] + // #[cfg(tari_target_network_mainnet)] fn stagenet_genesis_sanity_check() { - let _ = Network::set_current(Network::StageNet); + let network = Network::StageNet; + set_network_by_env_var_or_force_set(network); + if !network_matches(network) { + panic!("Network could not be set ('stagenet_genesis_sanity_check()')"); + } // Note: Generate new data for `pub fn get_stagenet_genesis_block()` and `fn get_stagenet_genesis_block_raw()` // if consensus values change, e.g. new pre_mine or other let block = get_stagenet_genesis_block(); - check_block(Network::StageNet, &block, 0, 0); + check_block(network, &block, 0, 0); + assert_genesis_block_hash(network); + remove_network_env_var() } #[test] - #[cfg(tari_target_network_testnet)] + #[serial] + // #[cfg(tari_target_network_testnet)] fn igor_genesis_sanity_check() { - let _ = Network::set_current(Network::Igor); + let network = Network::Igor; + set_network_by_env_var_or_force_set(network); + if !network_matches(network) { + panic!("Network could not be set ('igor_genesis_sanity_check()')"); + } // Note: If outputs and kernels are added, this test will fail unless you explicitly check that network == Igor let block = get_igor_genesis_block(); - check_block(Network::Igor, &block, 0, 0); + check_block(network, &block, 0, 0); + assert_genesis_block_hash(network); + remove_network_env_var() } #[test] - #[cfg(tari_target_network_testnet)] + #[serial] + // #[cfg(tari_target_network_testnet)] fn localnet_genesis_sanity_check() { - let _ = Network::set_current(Network::LocalNet); + let network = Network::LocalNet; + set_network_by_env_var_or_force_set(network); + if !network_matches(network) { + panic!("Network could not be set ('localnet_genesis_sanity_check()')"); + } // Note: If outputs and kernels are added, this test will fail unless you explicitly check that network == Igor let block = get_localnet_genesis_block(); - check_block(Network::LocalNet, &block, 0, 0); + check_block(network, &block, 0, 0); + assert_genesis_block_hash(network); + remove_network_env_var() } fn check_block(network: Network, block: &ChainBlock, expected_outputs: usize, expected_kernels: usize) { @@ -631,9 +670,21 @@ mod test { .unwrap(); } - // Update `tari_common::get_static_genesis_block_hash` with the correct values if the genesis block change + // This is a convenience test to check all networks are covered and to be able to test all networks at once + // without the need to re-compile or be dependent on the global static network setting. Update + // `tari_common::get_static_genesis_block_hash` with the correct values if the genesis block change. #[test] + #[serial] fn test_get_static_genesis_block_hash() { + if Network::is_set() { + println!("\nNote!! Static network constant is set, cannot run `test_get_static_genesis_block_hash`\n"); + return; + } + if std::env::var("TARI_NETWORK").is_ok() { + println!("\nNote!! env_var 'TARI_NETWORK' in use, cannot run `test_get_static_genesis_block_hash`\n"); + return; + } + for network in [ Network::MainNet, Network::StageNet, @@ -642,6 +693,10 @@ mod test { Network::Esmeralda, Network::LocalNet, ] { + set_network_by_env_var(network); + if !network_matches(network) { + panic!("Network could not be set ('test_get_static_genesis_block_hash()')"); + } match network { Network::MainNet => assert_genesis_block_hash(network), Network::StageNet => assert_genesis_block_hash(network), @@ -650,16 +705,51 @@ mod test { Network::Esmeralda => assert_genesis_block_hash(network), Network::LocalNet => assert_genesis_block_hash(network), } + remove_network_env_var(); } } fn assert_genesis_block_hash(network: Network) { + let expected_hash = *get_genesis_block(network).hash(); assert_eq!( - get_genesis_block_hash(network), - FixedHash::from_hex(get_static_genesis_block_hash(network)).unwrap(), + expected_hash.to_hex(), + get_static_genesis_block_hash(network), "network: {}, expected hash: {} (update `tari_common::get_static_genesis_block_hash`)", network, - get_genesis_block_hash(network) + expected_hash ); } + + fn set_network_by_env_var_or_force_set(network: Network) { + set_network_by_env_var(network); + if Network::get_current_or_user_setting_or_default() != network { + let _ = Network::set_current(network); + } + } + + // Targeted network compilations will override inferred network hashes; this has effect only if + // `Network::set_current()` has not been called. + fn set_network_by_env_var(network: Network) { + // Do not override the env_var if network is already set; another test may fail + if std::env::var("TARI_NETWORK").is_err() { + std::env::set_var("TARI_NETWORK", network.as_key_str()); + } + } + + fn remove_network_env_var() { + std::env::remove_var("TARI_NETWORK"); + } + + fn network_matches(network: Network) -> bool { + let current_network = Network::get_current_or_user_setting_or_default(); + if current_network == network { + true + } else { + println!( + "\nNetwork mismatch!! Required: {:?}, current: {:?}.\n", + network, current_network + ); + false + } + } } diff --git a/base_layer/core/src/consensus/consensus_encoding/hashing.rs b/base_layer/core/src/consensus/consensus_encoding/hashing.rs index 93abebc848..4c611380ca 100644 --- a/base_layer/core/src/consensus/consensus_encoding/hashing.rs +++ b/base_layer/core/src/consensus/consensus_encoding/hashing.rs @@ -145,44 +145,59 @@ mod tests { #[test] fn it_uses_the_network_environment_variable_if_set() { - // This test will not pass if `Network::set_current()` is called before the test - if !Network::is_set() { - let label = "test"; - let input = [1u8; 32]; - - for network in [ - Network::MainNet, - Network::StageNet, - Network::NextNet, - Network::LocalNet, - Network::Igor, - Network::Esmeralda, - ] { - println!("Testing network: {:?}", network); - // Generate a specific network hash - let hash_specify_network = - DomainSeparatedConsensusHasher::>::new_with_network(label, network) - .chain(&input) - .finalize(); - - // Generate an inferred network hash - std::env::set_var("TARI_NETWORK", network.as_key_str()); - println!( - "TARI_NETWORK: {:?}", - std::env::var("TARI_NETWORK").unwrap_or_default() - ); - println!( - "Network: {:?}\n", - Network::get_current_or_user_setting_or_default() - ); - let inferred_network_hash = DomainSeparatedConsensusHasher::>::new(label) + // Targeted network compilations will override inferred network hashes; this only has effect if + // `Network::set_current()` has not been called. The test may also not run if + // `std::env::var("TARI_NETWORK")` has been set by some other test. + if Network::is_set() { + println!( + "\nNote!! Static network constant is set, cannot run \ + `it_uses_the_network_environment_variable_if_set`\n" + ); + return; + } + if std::env::var("TARI_NETWORK").is_ok() { + println!( + "\nNote!! env_var 'TARI_NETWORK' in use, cannot run \ + `it_uses_the_network_environment_variable_if_set`\n" + ); + return; + } + + let label = "test"; + let input = [1u8; 32]; + + for network in [ + Network::MainNet, + Network::StageNet, + Network::NextNet, + Network::LocalNet, + Network::Igor, + Network::Esmeralda, + ] { + println!("Testing network: {:?}", network); + // Generate a specific network hash + let hash_specify_network = + DomainSeparatedConsensusHasher::>::new_with_network(label, network) .chain(&input) .finalize(); - std::env::remove_var("TARI_NETWORK"); - // They should be equal - assert_eq!(hash_specify_network, inferred_network_hash); - } + // Generate an inferred network hash + std::env::set_var("TARI_NETWORK", network.as_key_str()); + println!( + "TARI_NETWORK: {:?}", + std::env::var("TARI_NETWORK").unwrap_or_default() + ); + println!( + "Network: {:?}\n", + Network::get_current_or_user_setting_or_default() + ); + let inferred_network_hash = DomainSeparatedConsensusHasher::>::new(label) + .chain(&input) + .finalize(); + std::env::remove_var("TARI_NETWORK"); + + // They should be equal + assert_eq!(hash_specify_network, inferred_network_hash); } } } diff --git a/common/src/lib.rs b/common/src/lib.rs index 7b31cebc81..860582a922 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -86,11 +86,11 @@ pub(crate) const LOG_TARGET: &str = "common::config"; /// are wrong. pub fn get_static_genesis_block_hash<'a>(network: Network) -> &'a str { match network { - Network::MainNet => "54537be28b5d91b58d27fc52b7dc0cc8cea1977f199eb509d8b4978b0d6630c9", - Network::StageNet => "40afb45c7f10a2dd7bcdd3802273518aba20ac468a75cdfd0c85342a82096557", - Network::NextNet => "fed55ccea50122f9bc7ca913e4bbc0fcbd6913c10cb77bf08f98486ec88d5f02", - Network::Igor => "6cf2950380c69c991612f4ba0afb80281a41bb016239adc642c78817c2e1dbd4", + Network::MainNet => "ba4379a1319a6315d5262f61761d3f609f5b8eb9fa30a05f0d18a80c25d6bae9", + Network::StageNet => "cd073787a0bd8803a2546919523c687ccd88c8f0b39d652783530502e101f351", + Network::NextNet => "5ae9384d705f8df49d7e5b5988297440a53bc8be48b8792f8bc0a2c3d17c3479", + Network::Igor => "50ed5847a5b4b88dfd86fd48597801b72565a0e1ba14701fddbeaca356e8b4c3", Network::Esmeralda => "6598d13c5dcb398f5cad294473421bc2fed69071b56fada4387a6ad03a44df08", - Network::LocalNet => "7a32e20ebaf29f7cd67f59a7894050488c350f9d97fcea0765b7a4723e2d0bf7", + Network::LocalNet => "b693c14804ceaafaee77c2d01310a221960383128de6b0f36c581fb706332bb3", } }