Skip to content

Commit

Permalink
Add custom noise prologue
Browse files Browse the repository at this point in the history
Added a custom noise prologue to the noise protocol to be hashed in to the handshake hash value.
This enables an application to specify a unique identifier like the genesis block hash as the
noise prologue, effectively stopping any communication handshake to succeed with nodes that is
not on the same genesis block.
  • Loading branch information
hansieodendaal committed Sep 5, 2024
1 parent e734269 commit 008ab88
Show file tree
Hide file tree
Showing 25 changed files with 372 additions and 77 deletions.
24 changes: 24 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion applications/minotari_node/src/bootstrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ use std::{cmp, str::FromStr, sync::Arc};
use log::*;
use minotari_app_utilities::{consts, identity_management, identity_management::load_from_json};
use tari_common::{
configuration::bootstrap::ApplicationType,
configuration::{bootstrap::ApplicationType, Network},
exit_codes::{ExitCode, ExitError},
get_static_genesis_block_hash,
};
use tari_common_types::types::FixedHash;
use tari_comms::{
multiaddr::{Error as MultiaddrError, Multiaddr},
peer_manager::Peer,
Expand Down Expand Up @@ -65,6 +67,7 @@ use tari_p2p::{
};
use tari_service_framework::{ServiceHandles, StackBuilder};
use tari_shutdown::ShutdownSignal;
use tari_utilities::{hex::Hex, ByteArray};

use crate::ApplicationConfig;

Expand Down Expand Up @@ -125,6 +128,11 @@ where B: BlockchainBackend + 'static
base_node_config.network,
self.node_identity.clone(),
publisher,
FixedHash::from_hex(get_static_genesis_block_hash(
Network::get_current_or_user_setting_or_default(),
))
.map_err(|e| ExitError::new(ExitCode::ConfigError, e))?
.to_vec(),
))
.add_initializer(SoftwareUpdaterService::new(
ApplicationType::BaseNode,
Expand Down
1 change: 1 addition & 0 deletions base_layer/contacts/src/chat_client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ tari_p2p = { path = "../../../p2p" }
tari_service_framework= { path = "../../../service_framework" }
tari_shutdown = { path = "../../../../infrastructure/shutdown" }
tari_storage = { path = "../../../../infrastructure/storage" }
tari_utilities = { version = "0.7" }

anyhow = "1.0.41"
async-trait = "0.1.52"
Expand Down
9 changes: 9 additions & 0 deletions base_layer/contacts/src/chat_client/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use tari_comms::peer_manager::PeerManagerError;
use tari_contacts::contacts_service::error::ContactsServiceError;
use tari_p2p::initialization::CommsInitializationError;
use tari_storage::lmdb_store::LMDBError;
use tari_utilities::hex::HexError;

#[derive(Debug, thiserror::Error)]
pub enum Error {
Expand Down Expand Up @@ -73,4 +74,12 @@ pub enum NetworkingError {
ServiceInitializerError(#[from] anyhow::Error),
#[error("Comms failed to spawn")]
CommsSpawnError,
#[error("Hex error: `{0}`")]
HexError(String),
}

impl From<HexError> for NetworkingError {
fn from(err: HexError) -> Self {
NetworkingError::HexError(err.to_string())
}
}
7 changes: 7 additions & 0 deletions base_layer/contacts/src/chat_client/src/networking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ use std::{str::FromStr, sync::Arc, time::Duration};

use log::{error, trace};
use minotari_app_utilities::{identity_management, identity_management::load_from_json};
use tari_common::{configuration::Network, get_static_genesis_block_hash};
use tari_common_types::types::FixedHash;
// Re-exports
pub use tari_comms::{
multiaddr::{Error as MultiaddrError, Multiaddr},
Expand All @@ -40,6 +42,7 @@ use tari_p2p::{
};
use tari_service_framework::StackBuilder;
use tari_shutdown::ShutdownSignal;
use tari_utilities::hex::Hex;

use crate::{
config::ApplicationConfig,
Expand Down Expand Up @@ -75,6 +78,10 @@ pub async fn start(
config.chat_client.network,
node_identity,
publisher,
FixedHash::from_hex(get_static_genesis_block_hash(
Network::get_current_or_user_setting_or_default(),
))?
.to_vec(),
))
.add_initializer(LivenessInitializer::new(
LivenessConfig {
Expand Down
1 change: 1 addition & 0 deletions base_layer/contacts/tests/contacts_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ pub fn setup_contacts_service<T: ContactsBackend + 'static>(
Network::LocalNet,
node_identity.clone(),
publisher,
b"tari.contacts_service.testing.prologue".to_vec(),
))
.add_initializer(LivenessInitializer::new(
LivenessConfig {
Expand Down
1 change: 1 addition & 0 deletions base_layer/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
158 changes: 140 additions & 18 deletions base_layer/core/src/blocks/genesis_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -469,10 +469,13 @@ fn get_raw_block(genesis_timestamp: &DateTime<FixedOffset>, 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};

use super::*;
Expand All @@ -489,61 +492,97 @@ mod test {
};

#[test]
#[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]
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]
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]
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]
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]
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) {
Expand Down Expand Up @@ -624,4 +663,87 @@ mod test {
.validate(&*lock, 0, &utxo_sum, &kernel_sum, &Commitment::default())
.unwrap();
}

// 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,
Network::NextNet,
Network::Igor,
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),
Network::NextNet => assert_genesis_block_hash(network),
Network::Igor => assert_genesis_block_hash(network),
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!(
expected_hash.to_hex(),
get_static_genesis_block_hash(network),
"network: {}, expected hash: {} (update `tari_common::get_static_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(<NETWORK>)` 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
}
}
}
Loading

0 comments on commit 008ab88

Please sign in to comment.