From f526ad534c80ff90cf0ab9cedc6a5f247901f8d0 Mon Sep 17 00:00:00 2001 From: SW van Heerden Date: Mon, 3 Feb 2025 15:53:01 +0200 Subject: [PATCH] feat!: add squad to block name to not allow cross pollination (#248) Description --- add squad to block name to not allow cross pollination --- src/cli/commands/util.rs | 11 ++++++++++- src/server/mod.rs | 2 +- src/server/p2p/mod.rs | 2 +- src/server/p2p/network.rs | 12 +++--------- src/server/server.rs | 8 +++++++- src/sharechain/in_memory.rs | 21 +++++++++++++++++++-- src/sharechain/mod.rs | 1 - src/sharechain/p2block.rs | 8 ++++++++ src/sharechain/p2chain.rs | 5 +++++ 9 files changed, 54 insertions(+), 16 deletions(-) diff --git a/src/cli/commands/util.rs b/src/cli/commands/util.rs index 011195b..7783688 100644 --- a/src/cli/commands/util.rs +++ b/src/cli/commands/util.rs @@ -24,6 +24,8 @@ use crate::{ sharechain::{in_memory::InMemoryShareChain, BlockValidationParams}, }; +const LOG_TARGET: &str = "tari::p2pool::server::p2p"; + #[allow(clippy::too_many_lines)] pub async fn server( cli: Arc, @@ -137,12 +139,17 @@ genesis_block_hash.to_hex()); let stats_broadcast_client = StatsBroadcastClient::new(stats_tx); let stats_collector = StatsCollector::new(shutdown_signal.clone(), stats_rx); + let swarm = crate::server::p2p::setup::new_swarm(&config).await?; + let squad_id = (*swarm.local_peer_id().to_bytes().last().unwrap_or(&0) as usize) % config.p2p_service.num_squads; + let squad = format!("{}_{}", config.p2p_service.squad_prefix.clone(), squad_id); + info!(target: LOG_TARGET, "Swarm created. Our id: {}, our squad:{}", swarm.local_peer_id(), squad); let share_chain_sha3x = InMemoryShareChain::new( config.clone(), PowAlgorithm::Sha3x, None, coinbase_extras_sha3x.clone(), stats_broadcast_client.clone(), + squad.clone(), )?; let coinbase_extras_random_x = Arc::new(RwLock::new(HashMap::>::new())); let share_chain_random_x = InMemoryShareChain::new( @@ -151,8 +158,8 @@ genesis_block_hash.to_hex()); Some(block_validation_params.clone()), coinbase_extras_random_x.clone(), stats_broadcast_client.clone(), + squad.clone(), )?; - Server::new( config, share_chain_sha3x, @@ -160,6 +167,8 @@ genesis_block_hash.to_hex()); stats_collector, stats_broadcast_client, shutdown_signal, + swarm, + squad, ) .await } diff --git a/src/server/mod.rs b/src/server/mod.rs index 1f0ec17..a6b30e5 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -12,4 +12,4 @@ pub mod grpc; pub mod http; pub mod p2p; -pub const PROTOCOL_VERSION: u64 = 31; +pub const PROTOCOL_VERSION: u64 = 32; diff --git a/src/server/p2p/mod.rs b/src/server/p2p/mod.rs index fd97f1a..b4f4012 100644 --- a/src/server/p2p/mod.rs +++ b/src/server/p2p/mod.rs @@ -11,5 +11,5 @@ pub mod messages; mod network; pub mod peer_store; mod relay_store; -mod setup; +pub mod setup; pub mod util; diff --git a/src/server/p2p/network.rs b/src/server/p2p/network.rs index 21249e2..7198864 100644 --- a/src/server/p2p/network.rs +++ b/src/server/p2p/network.rs @@ -58,10 +58,7 @@ use tokio::{ time::MissedTickBehavior, }; -use super::{ - messages::{CatchUpSyncRequest, CatchUpSyncResponse, MetaDataRequest, MetaDataResponse, NotifyNewTipBlock}, - setup, -}; +use super::messages::{CatchUpSyncRequest, CatchUpSyncResponse, MetaDataRequest, MetaDataResponse, NotifyNewTipBlock}; use crate::{ server::{ config, @@ -318,12 +315,9 @@ where S: ShareChain are_we_synced_with_sha3x_p2pool: Arc, stats_broadcast_client: StatsBroadcastClient, share_window: u64, + swarm: Swarm, + squad: String, ) -> Result { - let swarm = setup::new_swarm(config).await?; - let squad_id = - (*swarm.local_peer_id().to_bytes().last().unwrap_or(&0) as usize) % config.p2p_service.num_squads; - let squad = format!("{}_{}", config.p2p_service.squad_prefix.clone(), squad_id); - info!(target: LOG_TARGET, "Swarm created. Our id: {}, our squad:{}", swarm.local_peer_id(), squad); let _res = stats_broadcast_client.send_info_changed(squad.clone(), *swarm.local_peer_id()); let network_peer_store = PeerStore::new(stats_broadcast_client.clone(), squad.clone()); diff --git a/src/server/server.rs b/src/server/server.rs index acefec9..866718e 100644 --- a/src/server/server.rs +++ b/src/server/server.rs @@ -8,6 +8,7 @@ use std::{ }; use anyhow::Error; +use libp2p::Swarm; use log::{error, info}; use minotari_app_grpc::tari_rpc::{base_node_server::BaseNodeServer, sha_p2_pool_server::ShaP2PoolServer}; use tari_common::configuration::Network; @@ -21,6 +22,7 @@ use crate::{ grpc::{base_node::TariBaseNodeGrpc, p2pool::ShaP2PoolGrpc}, http::server::HttpServer, p2p, + p2p::ServerNetworkBehaviour, }, sharechain::ShareChain, }; @@ -52,6 +54,8 @@ where S: ShareChain stats_collector: StatsCollector, stats_broadcast_client: StatsBroadcastClient, shutdown_signal: ShutdownSignal, + swarm: Swarm, + squad: String, ) -> Result { let share_chain_sha3x = Arc::new(share_chain_sha3x); let share_chain_random_x = Arc::new(share_chain_random_x); @@ -67,6 +71,8 @@ where S: ShareChain are_we_synced_with_sha3x_p2pool.clone(), stats_broadcast_client.clone(), config.share_window, + swarm, + squad.clone(), ) .await?; let local_peer_id = p2p_service.local_peer_id(); @@ -93,7 +99,7 @@ where S: ShareChain stats_broadcast_client.clone(), are_we_synced_with_randomx_p2pool.clone(), are_we_synced_with_sha3x_p2pool.clone(), - p2p_service.squad.clone(), + squad, ) .await?; p2pool_server = Some(ShaP2PoolServer::new(p2pool_grpc_service)); diff --git a/src/sharechain/in_memory.rs b/src/sharechain/in_memory.rs index 1a74a33..3eb078e 100644 --- a/src/sharechain/in_memory.rs +++ b/src/sharechain/in_memory.rs @@ -55,6 +55,7 @@ pub(crate) struct InMemoryShareChain { coinbase_extras: Arc>>>, stat_client: StatsBroadcastClient, config: Config, + squad: String, } #[allow(dead_code)] @@ -65,6 +66,7 @@ impl InMemoryShareChain { block_validation_params: Option>, coinbase_extras: Arc>>>, stat_client: StatsBroadcastClient, + squad: String, ) -> Result { if pow_algo == PowAlgorithm::RandomX && block_validation_params.is_none() { return Err(ShareChainError::MissingBlockValidationParams); @@ -99,6 +101,7 @@ impl InMemoryShareChain { config.block_time, old, new, + &squad, ) { Ok(p) => { let _unused = @@ -125,7 +128,6 @@ impl InMemoryShareChain { } let p2chain = p2chain.unwrap(); - Ok(Self { p2_chain: Arc::new(RwLock::new(p2chain)), pow_algo, @@ -133,6 +135,7 @@ impl InMemoryShareChain { coinbase_extras, stat_client, config, + squad, }) } @@ -427,7 +430,14 @@ impl InMemoryShareChain { impl ShareChain for InMemoryShareChain { async fn submit_block(&self, block: Arc) -> Result { if block.version != PROTOCOL_VERSION { - return Err(ShareChainError::BlockValidation("Block version is too low".to_string())); + return Err(ShareChainError::BlockValidation( + "Block version not supported".to_string(), + )); + } + if block.squad != self.squad { + return Err(ShareChainError::BlockValidation( + "Block squad not supported".to_string(), + )); } let mut p2_chain_write_lock = self.p2_chain.write().await; let height = block.height; @@ -472,6 +482,11 @@ impl ShareChain for InMemoryShareChain { if block.version != PROTOCOL_VERSION { return Err(ShareChainError::BlockValidation("Block version is too low".to_string())); } + if block.squad != self.squad { + return Err(ShareChainError::BlockValidation( + "Block squad not supported".to_string(), + )); + } let height = block.height; // info!(target: LOG_TARGET, "[{:?}] ✅ adding Block from sync: {:?}", self.pow_algo, height); match self @@ -722,6 +737,7 @@ impl ShareChain for InMemoryShareChain { .with_uncles(&uncles)? .with_miner_wallet_address(miner_address.clone()) .with_miner_coinbase_extra(coinbase_extra) + .with_squad(self.squad.clone()) .build()?) } @@ -904,6 +920,7 @@ pub mod test { coinbase_extras, stat_client, config, + squad: "NoSquad".to_string(), } } diff --git a/src/sharechain/mod.rs b/src/sharechain/mod.rs index dae0822..5d17a80 100644 --- a/src/sharechain/mod.rs +++ b/src/sharechain/mod.rs @@ -118,7 +118,6 @@ pub(crate) trait ShareChain: Send + Sync + 'static { /// Returns the requested blocks from this chain async fn get_blocks(&self, requested_blocks: &[(u64, FixedHash)]) -> Vec>; - async fn request_sync( &self, their_blocks: &[(u64, FixedHash)], diff --git a/src/sharechain/p2block.rs b/src/sharechain/p2block.rs index 5138c8a..76782c4 100644 --- a/src/sharechain/p2block.rs +++ b/src/sharechain/p2block.rs @@ -40,6 +40,7 @@ lazy_static! { pub(crate) struct P2Block { #[serde(default)] pub version: u64, + pub squad: String, pub hash: BlockHash, pub timestamp: EpochTime, pub prev_hash: BlockHash, @@ -63,6 +64,7 @@ impl Default for P2Block { Self { version: PROTOCOL_VERSION, hash: Default::default(), + squad: "NoSquad".to_string(), timestamp: EpochTime::now(), prev_hash: Default::default(), height: 0, @@ -85,6 +87,7 @@ impl P2Block { pub fn generate_hash(&self) -> BlockHash { DomainSeparatedConsensusHasher::>::new("block") .chain(&self.prev_hash) + .chain(&self.squad.as_bytes()) .chain(&self.version.to_le_bytes()) .chain(&self.timestamp) .chain(&self.height) @@ -188,6 +191,11 @@ impl P2BlockBuilder { } } + pub fn with_squad(mut self, squad: String) -> Self { + self.block.squad = squad; + self + } + pub fn with_timestamp(mut self, timestamp: EpochTime) -> Self { self.block.timestamp = timestamp; self diff --git a/src/sharechain/p2chain.rs b/src/sharechain/p2chain.rs index 3d3a84d..57d2b5d 100644 --- a/src/sharechain/p2chain.rs +++ b/src/sharechain/p2chain.rs @@ -169,6 +169,7 @@ impl P2Chain { block_time: u64, from_block_cache: T, new_block_cache: T, + squad: &str, ) -> Result { let mut new_chain = Self::new_empty(algo, total_size, share_window, block_time, new_block_cache); for block in from_block_cache.all_blocks()? { @@ -176,6 +177,10 @@ impl P2Chain { warn!(target: LOG_TARGET, "Block version mismatch, skipping block"); continue; } + if block.squad != squad { + warn!(target: LOG_TARGET, "Block squad mismatch, skipping block"); + continue; + } info!(target: LOG_TARGET, "Loading block {}({:x}{:x}{:x}{:x}) into chain", block.height, block.hash[0], block.hash[1], block.hash[2], block.hash[3]); let _unused = new_chain.add_block_to_chain(block).inspect_err(|e| { error!(target: LOG_TARGET, "Failed to load block into chain: {}", e);