From e61b5e2d172f782e953f351a81723713b150c57d Mon Sep 17 00:00:00 2001 From: Hansie Odendaal <39146854+hansieodendaal@users.noreply.github.com> Date: Fri, 1 Nov 2024 09:22:36 +0200 Subject: [PATCH 01/19] feat: verify active base node peer connections and disconnect if stale (#6655) Description --- Added check connections to the p2p services (`MonitorPeersService`). All active connections are pinged on a set (slowish) interval (10 times slower than the _auto ping metadata interval_). The nodes that do not respond timeously on three consecutive iterations with a corresponding pong are disconnected. This will help keep the list of active connections (lazily) up to date. **Edit:** Fixed an error in the liveness service where misbehaving ping peers were never disconnected. The liveness service and monitor peers service work hand in hand. Liveness selects 8 randomly connected peers to obtain metadata from and will disconnect any of those that misbehave after 1 minute (2x ping intervals). The monitor peers service assesses all connected peers at a much slower pace and disconnects non-responsive peers after 15 minutes (10 x 3 ping intervals). Motivation and Context --- See #6516 How Has This Been Tested? --- Performed system-level testing. From the log below we can see that 5 of 41 active peer connections did not respond with a ping. Peer `e19e1454a1e0519866297960ad ` was disconnected because it did not respond three times in a row, ``` 2024-10-29 15:12:07.664466900 [minotari::base_node::monitor_peers] TRACE Found 5 of 41 outbound base node peer connections that did not respond to pings 2024-10-29 15:12:07.664619800 [minotari::base_node::monitor_peers] TRACE Peer e2fa82050c2f7579febafb7e08 stats - (iteration, connected, responsive) [(3, true, true), (4, true, true), (5, true, false)] 2024-10-29 15:12:07.664683300 [minotari::base_node::monitor_peers] DEBUG Disconnecting e19e1454a1e0519866297960ad as the peer is no longer responsive - (iteration, connected, responsive) [(2, true, true), (3, true, false), (4, true, false), (5, true, false)] 2024-10-29 15:12:07.665853300 [minotari::base_node::monitor_peers] TRACE Peer 6ea597117476676d5ddcb18153 stats - (iteration, connected, responsive) [(1, true, true), (2, true, true), (3, true, true), (4, true, true), (5, true, false)] 2024-10-29 15:12:07.665965500 [minotari::base_node::monitor_peers] TRACE Peer a671f812efe5ab14cbb3c1f9f4 stats - (iteration, connected, responsive) [(2, true, true), (3, true, true), (4, true, true), (5, true, false)] 2024-10-29 15:12:07.665997800 [minotari::base_node::monitor_peers] TRACE Peer e336b264e02f611cf4fbf51f22 stats - (iteration, connected, responsive) [(2, true, true), (3, true, true), (4, true, true), (5, true, false)] ``` What process can a PR reviewer use to test or verify this change? --- - Code review - System-level testing Breaking Changes --- - [x] None - [ ] Requires data directory on base node to be deleted - [ ] Requires hard fork - [ ] Other - Please specify --------- Co-authored-by: SW van Heerden --- applications/minotari_node/src/bootstrap.rs | 8 +- .../src/commands/command/ping_peer.rs | 49 +-- applications/minotari_node/src/lib.rs | 3 +- .../chain_metadata_service/service.rs | 12 +- .../p2p/src/services/liveness/handle.rs | 27 +- base_layer/p2p/src/services/liveness/mock.rs | 12 +- base_layer/p2p/src/services/liveness/mod.rs | 3 +- .../p2p/src/services/liveness/service.rs | 78 +++-- base_layer/p2p/src/services/liveness/state.rs | 26 +- base_layer/p2p/src/services/mod.rs | 1 + .../p2p/src/services/monitor_peers/mod.rs | 90 +++++ .../p2p/src/services/monitor_peers/service.rs | 324 ++++++++++++++++++ 12 files changed, 554 insertions(+), 79 deletions(-) create mode 100644 base_layer/p2p/src/services/monitor_peers/mod.rs create mode 100644 base_layer/p2p/src/services/monitor_peers/service.rs diff --git a/applications/minotari_node/src/bootstrap.rs b/applications/minotari_node/src/bootstrap.rs index fc41b77cfd..6620e7bd07 100644 --- a/applications/minotari_node/src/bootstrap.rs +++ b/applications/minotari_node/src/bootstrap.rs @@ -59,7 +59,10 @@ use tari_p2p::{ initialization, initialization::P2pInitializer, peer_seeds::SeedPeer, - services::liveness::{config::LivenessConfig, LivenessInitializer}, + services::{ + liveness::{config::LivenessConfig, LivenessInitializer}, + monitor_peers::MonitorPeersInitializer, + }, P2pConfig, TransportType, }; @@ -155,6 +158,9 @@ where B: BlockchainBackend + 'static }, peer_message_subscriptions, )) + .add_initializer(MonitorPeersInitializer::new( + base_node_config.metadata_auto_ping_interval, + )) .add_initializer(ChainMetadataServiceInitializer) .add_initializer(BaseNodeStateMachineInitializer::new( self.db.clone().into(), diff --git a/applications/minotari_node/src/commands/command/ping_peer.rs b/applications/minotari_node/src/commands/command/ping_peer.rs index ea37a8fdcc..55553756b6 100644 --- a/applications/minotari_node/src/commands/command/ping_peer.rs +++ b/applications/minotari_node/src/commands/command/ping_peer.rs @@ -45,34 +45,39 @@ impl HandleCommand for CommandContext { } impl CommandContext { - /// Function to process the dial-peer command + /// Function to process the ping-peer command pub async fn ping_peer(&mut self, dest_node_id: NodeId) -> Result<(), Error> { - println!("πŸ“ Pinging peer..."); let mut liveness_events = self.liveness.get_event_stream(); let mut liveness = self.liveness.clone(); task::spawn(async move { - if let Err(e) = liveness.send_ping(dest_node_id.clone()).await { - println!("πŸ“ Ping failed to send to {}: {}", dest_node_id, e); - return; - } - loop { - match liveness_events.recv().await { - Ok(event) => { - if let LivenessEvent::ReceivedPong(pong) = &*event { - if pong.node_id == dest_node_id { - println!( - "πŸ“οΈ Pong received, round-trip-time is {:.2?}!", - pong.latency.unwrap_or_default() - ); + match liveness.send_ping(dest_node_id.clone()).await { + Ok(nonce) => { + println!("πŸ“ Pinging peer {} with nonce {} ...", dest_node_id, nonce); + loop { + match liveness_events.recv().await { + Ok(event) => { + if let LivenessEvent::ReceivedPong(pong) = &*event { + if pong.node_id == dest_node_id && pong.nonce == nonce { + println!( + "πŸ“οΈ Pong: peer {} responded with nonce {}, round-trip-time is {:.2?}!", + pong.node_id, + pong.nonce, + pong.latency.unwrap_or_default() + ); + break; + } + } + }, + Err(RecvError::Closed) => { break; - } + }, + Err(RecvError::Lagged(_)) => {}, } - }, - Err(RecvError::Closed) => { - break; - }, - Err(RecvError::Lagged(_)) => {}, - } + } + }, + Err(e) => { + println!("πŸ“ Ping failed to send to {}: {}", dest_node_id, e); + }, } }); Ok(()) diff --git a/applications/minotari_node/src/lib.rs b/applications/minotari_node/src/lib.rs index 99ebebf22b..2c40ac2101 100644 --- a/applications/minotari_node/src/lib.rs +++ b/applications/minotari_node/src/lib.rs @@ -37,6 +37,7 @@ mod grpc_method; mod metrics; mod recovery; mod utils; + use std::{process, sync::Arc}; use commands::{cli_loop::CliLoop, command::CommandContext}; @@ -151,7 +152,7 @@ pub async fn run_base_node_with_cli( } // Run, node, run! - let context = CommandContext::new(&ctx, shutdown); + let context = CommandContext::new(&ctx, shutdown.clone()); let main_loop = CliLoop::new(context, cli.watch, cli.non_interactive_mode); if cli.non_interactive_mode { println!("Node started in non-interactive mode (pid = {})", process::id()); diff --git a/base_layer/core/src/base_node/chain_metadata_service/service.rs b/base_layer/core/src/base_node/chain_metadata_service/service.rs index 58d8768ac2..ebe656e571 100644 --- a/base_layer/core/src/base_node/chain_metadata_service/service.rs +++ b/base_layer/core/src/base_node/chain_metadata_service/service.rs @@ -141,10 +141,6 @@ impl ChainMetadataService { match event { // Received a ping, check if it contains ChainMetadata LivenessEvent::ReceivedPing(event) => { - debug!( - target: LOG_TARGET, - "Received ping from neighbouring node '{}'.", event.node_id - ); self.number_of_rounds_no_pings = 0; if event.metadata.has(MetadataKey::ChainMetadata) { self.send_chain_metadata_to_event_publisher(event).await?; @@ -152,11 +148,6 @@ impl ChainMetadataService { }, // Received a pong, check if our neighbour sent it and it contains ChainMetadata LivenessEvent::ReceivedPong(event) => { - trace!( - target: LOG_TARGET, - "Received pong from neighbouring node '{}'.", - event.node_id - ); self.number_of_rounds_no_pings = 0; if event.metadata.has(MetadataKey::ChainMetadata) { self.send_chain_metadata_to_event_publisher(event).await?; @@ -325,6 +316,7 @@ mod test { metadata, node_id: node_id.clone(), latency: None, + nonce: 0, }; let sample_event = LivenessEvent::ReceivedPong(Box::new(pong_event)); @@ -347,6 +339,7 @@ mod test { metadata, node_id, latency: None, + nonce: 0, }; let sample_event = LivenessEvent::ReceivedPong(Box::new(pong_event)); @@ -365,6 +358,7 @@ mod test { metadata, node_id, latency: None, + nonce: 0, }; let sample_event = LivenessEvent::ReceivedPong(Box::new(pong_event)); diff --git a/base_layer/p2p/src/services/liveness/handle.rs b/base_layer/p2p/src/services/liveness/handle.rs index 2eabd07c9d..96696c528f 100644 --- a/base_layer/p2p/src/services/liveness/handle.rs +++ b/base_layer/p2p/src/services/liveness/handle.rs @@ -35,6 +35,8 @@ use crate::proto::liveness::MetadataKey; pub enum LivenessRequest { /// Send a ping to the given node ID SendPing(NodeId), + /// Ping a list of peers + SendPings(Vec), /// Retrieve the total number of pings received GetPingCount, /// Retrieve the total number of pongs received @@ -55,7 +57,7 @@ pub enum LivenessRequest { #[derive(Debug)] pub enum LivenessResponse { /// Indicates that the request succeeded - Ok, + Ok(Option>), /// Used to return a counter value from `GetPingCount` and `GetPongCount` Count(usize), /// Response for GetAvgLatency and GetNetworkAvgLatency @@ -84,14 +86,17 @@ pub struct PingPongEvent { pub latency: Option, /// Metadata of the corresponding node pub metadata: Metadata, + /// The nonce of the ping/pong message, for clients that want to match pings with pongs + pub nonce: u64, } impl PingPongEvent { - pub fn new(node_id: NodeId, latency: Option, metadata: Metadata) -> Self { + pub fn new(node_id: NodeId, latency: Option, metadata: Metadata, nonce: u64) -> Self { Self { node_id, latency, metadata, + nonce, } } } @@ -122,9 +127,17 @@ impl LivenessHandle { } /// Send a ping to a given node ID - pub async fn send_ping(&mut self, node_id: NodeId) -> Result<(), LivenessError> { + pub async fn send_ping(&mut self, node_id: NodeId) -> Result { match self.handle.call(LivenessRequest::SendPing(node_id)).await?? { - LivenessResponse::Ok => Ok(()), + LivenessResponse::Ok(Some(nonces)) => Ok(nonces[0]), + _ => Err(LivenessError::UnexpectedApiResponse), + } + } + + /// Send pings to a list of peers + pub async fn send_pings(&mut self, node_ids: Vec) -> Result, LivenessError> { + match self.handle.call(LivenessRequest::SendPings(node_ids)).await?? { + LivenessResponse::Ok(Some(nonces)) => Ok(nonces), _ => Err(LivenessError::UnexpectedApiResponse), } } @@ -152,7 +165,7 @@ impl LivenessHandle { .call(LivenessRequest::SetMetadataEntry(key, value)) .await?? { - LivenessResponse::Ok => Ok(()), + LivenessResponse::Ok(_) => Ok(()), _ => Err(LivenessError::UnexpectedApiResponse), } } @@ -160,7 +173,7 @@ impl LivenessHandle { /// Add a monitored peer to the basic config if not present pub async fn check_add_monitored_peer(&mut self, node_id: NodeId) -> Result<(), LivenessError> { match self.handle.call(LivenessRequest::AddMonitoredPeer(node_id)).await?? { - LivenessResponse::Ok => Ok(()), + LivenessResponse::Ok(_) => Ok(()), _ => Err(LivenessError::UnexpectedApiResponse), } } @@ -172,7 +185,7 @@ impl LivenessHandle { .call(LivenessRequest::RemoveMonitoredPeer(node_id)) .await?? { - LivenessResponse::Ok => Ok(()), + LivenessResponse::Ok(_) => Ok(()), _ => Err(LivenessError::UnexpectedApiResponse), } } diff --git a/base_layer/p2p/src/services/liveness/mock.rs b/base_layer/p2p/src/services/liveness/mock.rs index 652531a17f..9b765fe5d3 100644 --- a/base_layer/p2p/src/services/liveness/mock.rs +++ b/base_layer/p2p/src/services/liveness/mock.rs @@ -125,7 +125,11 @@ impl LivenessMock { self.mock_state.add_request_call(req.clone()); match req { SendPing(_) => { - reply.send(Ok(LivenessResponse::Ok)).unwrap(); + reply.send(Ok(LivenessResponse::Ok(Some(vec![0])))).unwrap(); + }, + SendPings(node_ids) => { + let nonces: Vec = (0..node_ids.len() as u64).collect(); + reply.send(Ok(LivenessResponse::Ok(Some(nonces)))).unwrap(); }, GetPingCount => { reply.send(Ok(LivenessResponse::Count(1))).unwrap(); @@ -140,13 +144,13 @@ impl LivenessMock { reply.send(Ok(LivenessResponse::AvgLatency(None))).unwrap(); }, SetMetadataEntry(_, _) => { - reply.send(Ok(LivenessResponse::Ok)).unwrap(); + reply.send(Ok(LivenessResponse::Ok(None))).unwrap(); }, AddMonitoredPeer(_) => { - reply.send(Ok(LivenessResponse::Ok)).unwrap(); + reply.send(Ok(LivenessResponse::Ok(None))).unwrap(); }, RemoveMonitoredPeer(_) => { - reply.send(Ok(LivenessResponse::Ok)).unwrap(); + reply.send(Ok(LivenessResponse::Ok(None))).unwrap(); }, } } diff --git a/base_layer/p2p/src/services/liveness/mod.rs b/base_layer/p2p/src/services/liveness/mod.rs index 53031bbe7a..e7842002db 100644 --- a/base_layer/p2p/src/services/liveness/mod.rs +++ b/base_layer/p2p/src/services/liveness/mod.rs @@ -52,6 +52,7 @@ pub use handle::{ mod message; mod service; +pub use service::MAX_INFLIGHT_TTL; mod state; pub use state::Metadata; @@ -87,7 +88,7 @@ const LOG_TARGET: &str = "p2p::services::liveness"; /// Initializer for the Liveness service handle and service future. pub struct LivenessInitializer { - config: Option, + pub(crate) config: Option, inbound_message_subscription_factory: Arc>>, } diff --git a/base_layer/p2p/src/services/liveness/service.rs b/base_layer/p2p/src/services/liveness/service.rs index e7407b4190..1be0bb0015 100644 --- a/base_layer/p2p/src/services/liveness/service.rs +++ b/base_layer/p2p/src/services/liveness/service.rs @@ -20,7 +20,11 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use std::{iter, sync::Arc, time::Instant}; +use std::{ + iter, + sync::Arc, + time::{Duration, Instant}, +}; use futures::{future::Either, pin_mut, stream::StreamExt, Stream}; use log::*; @@ -55,6 +59,8 @@ use crate::{ tari_message::TariMessageType, }; +pub const MAX_INFLIGHT_TTL: Duration = Duration::from_secs(30); + /// Service responsible for testing Liveness of Peers. pub struct LivenessService { config: LivenessConfig, @@ -131,9 +137,7 @@ where warn!(target: LOG_TARGET, "Error when pinging peers: {}", err); } if self.config.max_allowed_ping_failures > 0 { - if let Err(err) = self.disconnect_failed_peers().await { - error!(target: LOG_TARGET, "Error occurred while disconnecting failed peers: {}", err); - } + self.disconnect_failed_peers().await; } }, @@ -184,7 +188,7 @@ where self.send_pong(ping_pong_msg.nonce, public_key).await?; self.state.inc_pongs_sent(); - debug!( + trace!( target: LOG_TARGET, "Received ping from peer '{}' with useragent '{}' (Trace: {})", node_id.short_str(), @@ -192,7 +196,7 @@ where message_tag, ); - let ping_event = PingPongEvent::new(node_id, None, ping_pong_msg.metadata.into()); + let ping_event = PingPongEvent::new(node_id, None, ping_pong_msg.metadata.into(), ping_pong_msg.nonce); self.publish_event(LivenessEvent::ReceivedPing(Box::new(ping_event))); }, PingPong::Pong => { @@ -208,7 +212,7 @@ where } let maybe_latency = self.state.record_pong(ping_pong_msg.nonce, &node_id); - debug!( + trace!( target: LOG_TARGET, "Received pong from peer '{}' with useragent '{}'. {} (Trace: {})", node_id.short_str(), @@ -219,7 +223,12 @@ where message_tag, ); - let pong_event = PingPongEvent::new(node_id.clone(), maybe_latency, ping_pong_msg.metadata.into()); + let pong_event = PingPongEvent::new( + node_id.clone(), + maybe_latency, + ping_pong_msg.metadata.into(), + ping_pong_msg.nonce, + ); self.publish_event(LivenessEvent::ReceivedPong(Box::new(pong_event))); if let Some(address) = source_peer.last_address_used() { @@ -232,9 +241,14 @@ where Ok(()) } - async fn send_ping(&mut self, node_id: NodeId) -> Result<(), LivenessError> { + async fn send_ping(&mut self, node_id: NodeId) -> Result { let msg = PingPongMessage::ping_with_metadata(self.state.metadata().clone()); - self.state.add_inflight_ping(msg.nonce, node_id.clone()); + let nonce = msg.nonce; + self.state.add_inflight_ping( + nonce, + node_id.clone(), + self.config.auto_ping_interval.unwrap_or(MAX_INFLIGHT_TTL), + ); debug!(target: LOG_TARGET, "Sending ping to peer '{}'", node_id.short_str(),); self.outbound_messaging @@ -246,7 +260,7 @@ where .await .map_err(Into::::into)?; - Ok(()) + Ok(nonce) } async fn send_pong(&mut self, nonce: u64, dest: CommsPublicKey) -> Result<(), LivenessError> { @@ -267,9 +281,17 @@ where use LivenessRequest::*; match request { SendPing(node_id) => { - self.send_ping(node_id).await?; + let nonce = self.send_ping(node_id).await?; self.state.inc_pings_sent(); - Ok(LivenessResponse::Ok) + Ok(LivenessResponse::Ok(Some(vec![nonce]))) + }, + SendPings(node_ids) => { + let mut nonces = Vec::with_capacity(node_ids.len()); + for node_id in node_ids { + nonces.push(self.send_ping(node_id).await?); + self.state.inc_pings_sent(); + } + Ok(LivenessResponse::Ok(Some(nonces))) }, GetPingCount => { let ping_count = self.get_ping_count(); @@ -289,21 +311,21 @@ where }, SetMetadataEntry(key, value) => { self.state.set_metadata_entry(key, value); - Ok(LivenessResponse::Ok) + Ok(LivenessResponse::Ok(None)) }, AddMonitoredPeer(node_id) => { let node_id_exists = { self.monitored_peers.read().await.iter().any(|val| val == &node_id) }; if !node_id_exists { self.monitored_peers.write().await.push(node_id.clone()); } - Ok(LivenessResponse::Ok) + Ok(LivenessResponse::Ok(None)) }, RemoveMonitoredPeer(node_id) => { let node_id_exists = { self.monitored_peers.read().await.iter().position(|val| *val == node_id) }; if let Some(pos) = node_id_exists { self.monitored_peers.write().await.swap_remove(pos); } - Ok(LivenessResponse::Ok) + Ok(LivenessResponse::Ok(None)) }, } } @@ -333,7 +355,11 @@ where for peer in selected_peers { let msg = PingPongMessage::ping_with_metadata(self.state.metadata().clone()); - self.state.add_inflight_ping(msg.nonce, peer.clone()); + self.state.add_inflight_ping( + msg.nonce, + peer.clone(), + self.config.auto_ping_interval.unwrap_or(MAX_INFLIGHT_TTL), + ); self.outbound_messaging .send_direct_node_id( peer, @@ -348,24 +374,31 @@ where Ok(()) } - async fn disconnect_failed_peers(&mut self) -> Result<(), LivenessError> { + async fn disconnect_failed_peers(&mut self) { let max_allowed_ping_failures = self.config.max_allowed_ping_failures; + let mut node_ids = Vec::new(); for node_id in self .state .failed_pings_iter() .filter(|(_, n)| **n > max_allowed_ping_failures) .map(|(node_id, _)| node_id) { - if let Some(mut conn) = self.connectivity.get_connection(node_id.clone()).await? { + if let Ok(Some(mut conn)) = self.connectivity.get_connection(node_id.clone()).await { debug!( target: LOG_TARGET, "Disconnecting peer {} that failed {} rounds of pings", node_id, max_allowed_ping_failures ); - conn.disconnect(Minimized::No).await?; + match conn.disconnect(Minimized::No).await { + Ok(_) => { + node_ids.push(node_id.clone()); + }, + Err(err) => { + warn!(target: LOG_TARGET, "Failed to disconnect peer {} ({})", node_id, err); + }, + } } } - self.state.clear_failed_pings(); - Ok(()) + self.state.clear_failed_pings(&node_ids); } fn publish_event(&mut self, event: LivenessEvent) { @@ -613,6 +646,7 @@ mod test { state.add_inflight_ping( msg.inner.as_ref().map(|i| i.nonce).unwrap(), msg.source_peer.node_id.clone(), + MAX_INFLIGHT_TTL, ); // A stream which emits an inflight pong message and an unexpected one diff --git a/base_layer/p2p/src/services/liveness/state.rs b/base_layer/p2p/src/services/liveness/state.rs index 0c29d20d31..849f2a328c 100644 --- a/base_layer/p2p/src/services/liveness/state.rs +++ b/base_layer/p2p/src/services/liveness/state.rs @@ -33,7 +33,6 @@ use super::LOG_TARGET; use crate::proto::liveness::MetadataKey; const LATENCY_SAMPLE_WINDOW_SIZE: usize = 25; -const MAX_INFLIGHT_TTL: Duration = Duration::from_secs(40); /// Represents metadata in a ping/pong message. #[derive(Clone, Debug, Default, PartialEq, Eq)] @@ -136,17 +135,17 @@ impl LivenessState { } /// Adds a ping to the inflight ping list, while noting the current time that a ping was sent. - pub fn add_inflight_ping(&mut self, nonce: u64, node_id: NodeId) { + pub fn add_inflight_ping(&mut self, nonce: u64, node_id: NodeId, max_inflight_ttl: Duration) { self.inflight_pings.insert(nonce, (node_id, Instant::now())); - self.clear_stale_inflight_pings(); + self.clear_stale_inflight_pings(max_inflight_ttl); } /// Clears inflight ping requests which have not responded and adds them to failed_ping counter - fn clear_stale_inflight_pings(&mut self) { + fn clear_stale_inflight_pings(&mut self, max_inflight_ttl: Duration) { let (inflight, expired) = self .inflight_pings .drain() - .partition(|(_, (_, time))| time.elapsed() <= MAX_INFLIGHT_TTL); + .partition(|(_, (_, time))| time.elapsed() <= max_inflight_ttl); self.inflight_pings = inflight; @@ -221,8 +220,10 @@ impl LivenessState { self.failed_pings.iter() } - pub fn clear_failed_pings(&mut self) { - self.failed_pings.clear(); + pub fn clear_failed_pings(&mut self, node_ids: &[NodeId]) { + for node_id in node_ids { + self.failed_pings.remove(node_id); + } } } @@ -265,6 +266,7 @@ impl AverageLatency { #[cfg(test)] mod test { use super::*; + use crate::services::liveness::service::MAX_INFLIGHT_TTL; #[test] fn new() { @@ -322,7 +324,7 @@ mod test { let mut state = LivenessState::new(); let node_id = NodeId::default(); - state.add_inflight_ping(123, node_id.clone()); + state.add_inflight_ping(123, node_id.clone(), MAX_INFLIGHT_TTL); let latency = state.record_pong(123, &node_id).unwrap(); assert!(latency < Duration::from_millis(50)); @@ -340,10 +342,10 @@ mod test { let mut state = LivenessState::new(); let peer1 = NodeId::default(); - state.add_inflight_ping(1, peer1.clone()); + state.add_inflight_ping(1, peer1.clone(), MAX_INFLIGHT_TTL); let peer2 = NodeId::from_public_key(&Default::default()); - state.add_inflight_ping(2, peer2.clone()); - state.add_inflight_ping(3, peer2.clone()); + state.add_inflight_ping(2, peer2.clone(), MAX_INFLIGHT_TTL); + state.add_inflight_ping(3, peer2.clone(), MAX_INFLIGHT_TTL); assert!(!state.failed_pings.contains_key(&peer1)); assert!(!state.failed_pings.contains_key(&peer2)); @@ -354,7 +356,7 @@ mod test { *time = Instant::now() - (MAX_INFLIGHT_TTL + Duration::from_secs(1)); } - state.clear_stale_inflight_pings(); + state.clear_stale_inflight_pings(MAX_INFLIGHT_TTL); let n = state.failed_pings.get(&peer1).unwrap(); assert_eq!(*n, 1); let n = state.failed_pings.get(&peer2).unwrap(); diff --git a/base_layer/p2p/src/services/mod.rs b/base_layer/p2p/src/services/mod.rs index 95da571d62..2514d17730 100644 --- a/base_layer/p2p/src/services/mod.rs +++ b/base_layer/p2p/src/services/mod.rs @@ -21,4 +21,5 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. pub mod liveness; +pub mod monitor_peers; pub mod utils; diff --git a/base_layer/p2p/src/services/monitor_peers/mod.rs b/base_layer/p2p/src/services/monitor_peers/mod.rs new file mode 100644 index 0000000000..d09dd925ca --- /dev/null +++ b/base_layer/p2p/src/services/monitor_peers/mod.rs @@ -0,0 +1,90 @@ +// Copyright 2022, The Tari Project +// +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +// following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +// disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +// following disclaimer in the documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +// products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +mod service; + +use std::{cmp::max, time::Duration}; + +use log::debug; +use tari_comms::{async_trait, connectivity::ConnectivityRequester}; +use tari_service_framework::{ServiceInitializationError, ServiceInitializer, ServiceInitializerContext}; + +use crate::services::{ + liveness::{LivenessHandle, MAX_INFLIGHT_TTL}, + monitor_peers::service::MonitorPeersService, +}; + +const LOG_TARGET: &str = "p2p::services::monitor_peers"; + +/// Initializer for the MonitorPeers service handle and service future. +pub struct MonitorPeersInitializer { + auto_ping_interval: Option, +} + +impl MonitorPeersInitializer { + /// Create a new MonitorPeersInitializer from the inbound message subscriber + pub fn new(auto_ping_interval: Duration) -> Self { + Self { + auto_ping_interval: Some(auto_ping_interval), + } + } +} + +impl Default for MonitorPeersInitializer { + fn default() -> Self { + Self { + auto_ping_interval: Some(MAX_INFLIGHT_TTL), + } + } +} + +#[async_trait] +impl ServiceInitializer for MonitorPeersInitializer { + async fn initialize(&mut self, context: ServiceInitializerContext) -> Result<(), ServiceInitializationError> { + debug!(target: LOG_TARGET, "Initializing Peer Monitoring Service"); + + let auto_ping_interval = max( + self.auto_ping_interval + .take() + .expect("Monitor peers service initialized more than once."), + MAX_INFLIGHT_TTL, + ); + + // Spawn the MonitorPeers service on the executor + context.spawn_when_ready(move |handles| async move { + let liveness = handles.expect_handle::(); + let connectivity = handles.expect_handle::(); + + let service = MonitorPeersService::new( + connectivity, + liveness, + handles.get_shutdown_signal(), + auto_ping_interval, + ); + service.run().await; + debug!(target: LOG_TARGET, "Monitor peers service has shut down"); + }); + + debug!(target: LOG_TARGET, "Monitor peers service initialized"); + Ok(()) + } +} diff --git a/base_layer/p2p/src/services/monitor_peers/service.rs b/base_layer/p2p/src/services/monitor_peers/service.rs new file mode 100644 index 0000000000..fceb157458 --- /dev/null +++ b/base_layer/p2p/src/services/monitor_peers/service.rs @@ -0,0 +1,324 @@ +// Copyright 2022, The Tari Project +// +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +// following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +// disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +// following disclaimer in the documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +// products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use std::collections::{HashMap, VecDeque}; + +use futures::pin_mut; +use log::*; +use tari_comms::{ + connection_manager::ConnectionDirection, + connectivity::ConnectivityRequester, + peer_manager::NodeId, + Minimized, + PeerConnection, +}; +use tari_shutdown::ShutdownSignal; +use tokio::{ + sync::broadcast::error::RecvError, + time::{self, Duration}, +}; + +use crate::services::{ + liveness::{LivenessEvent, LivenessHandle}, + monitor_peers::LOG_TARGET, +}; + +struct PeerLiveness { + vec: VecDeque, +} + +impl PeerLiveness { + pub fn new() -> Self { + Self { + vec: VecDeque::with_capacity(MAX_SIZE), + } + } + + pub fn push_pop(&mut self, item: T) { + if self.vec.len() == MAX_SIZE { + self.vec.pop_front(); + } + self.vec.push_back(item); + } + + pub fn iter(&self) -> std::collections::vec_deque::Iter { + self.vec.iter() + } +} + +struct Stats { + connected: bool, + responsive: bool, + loop_count: u64, +} + +struct PeerPingPong { + expected_nonce: u64, + received_nonce: Option, + node_id: NodeId, +} + +pub struct MonitorPeersService { + comms: ConnectivityRequester, + liveness_handle: LivenessHandle, + shutdown_signal: ShutdownSignal, + auto_ping_interval: Duration, +} + +impl MonitorPeersService { + pub fn new( + comms: ConnectivityRequester, + liveness_handle: LivenessHandle, + shutdown_signal: ShutdownSignal, + auto_ping_interval: Duration, + ) -> Self { + Self { + comms, + liveness_handle, + shutdown_signal, + auto_ping_interval, + } + } + + /// Monitor the liveness of outbound peer connections and disconnect those that do not respond to pings + /// consecutively. The intent of the interval timer is to be significantly longer than the rate at which + /// metadata is requested from peers. + #[allow(clippy::too_many_lines)] + pub async fn run(mut self) { + let mut interval_timer = time::interval(self.auto_ping_interval * 10); + let liveness_events = self.liveness_handle.get_event_stream(); + pin_mut!(liveness_events); + + let mut peer_liveness_stats: HashMap> = HashMap::new(); + + let mut loop_count = 0u64; + loop { + loop_count += 1; + tokio::select! { + biased; + _ = self.shutdown_signal.wait() => { + break; + } + + _ = interval_timer.tick() => { + trace!(target: LOG_TARGET, "Starting monitor peers round (iter {})", loop_count); + let active_connections = match self.comms.get_active_connections().await { + Ok(val) => val, + Err(e) => { + warn!(target: LOG_TARGET, "Failed to get active connections ({})", e); + continue; + }, + }; + let mut active_peer_connections = active_connections + .iter() + .filter(|p|p.peer_features().is_node() && p.direction() == ConnectionDirection::Outbound) + .cloned() + .collect::>(); + if active_peer_connections.is_empty() { + trace!(target: LOG_TARGET, "No active connections found"); + continue; + } + let active_peer_node_ids = active_peer_connections + .iter() + .map(|p|p.peer_node_id().clone()) + .collect::>(); + + let known_peer_connections = peer_liveness_stats.keys().cloned().collect::>(); + for peer_id in &known_peer_connections { + if !active_peer_node_ids.contains(peer_id) { + // Prior connections not connected now are considered inactive and unresponsive + peer_liveness_stats + .entry(peer_id.clone()) + .and_modify(|item| item.push_pop( + Stats {connected: false, responsive: false, loop_count} + )); + } + } + for peer_id in &active_peer_node_ids { + if !known_peer_connections.contains(peer_id) { + // New connections are considered active and responsive + peer_liveness_stats.insert( peer_id.clone(), PeerLiveness::new()); + } + } + + let mut peer_ping_pongs = match self.liveness_handle + .send_pings(active_peer_node_ids.clone()) + .await + { + Ok(nonces) => active_peer_node_ids + .iter() + .zip(nonces.iter()) + .map(|(node_id, &nonce)| PeerPingPong { + expected_nonce: nonce, + received_nonce: None, + node_id: node_id.clone(), + }) + .collect::>(), + Err(e) => { + warn!(target: LOG_TARGET, "Failed to send pings to peers ({})", e); + continue; + }, + }; + + // Only listen for the expected pongs from the peers (ignore any other pongs) + let timeout_timer = time::sleep(self.auto_ping_interval); + tokio::pin!(timeout_timer); + loop { + tokio::select! { + biased; + _ = self.shutdown_signal.wait() => { + break; + } + + event = liveness_events.recv() => { + let event_str = format!("{:?}", event); + match event { + Ok(arc_event) => { + if let LivenessEvent::ReceivedPong(pong) = &*arc_event { + if let Some(ping_pong) = peer_ping_pongs.iter_mut().find(|p| p.expected_nonce == pong.nonce) { + ping_pong.received_nonce = Some(pong.nonce); + } + if peer_ping_pongs.iter().all(|p| p.received_nonce.is_some()) { + break; + } + } + }, + Err(RecvError::Closed) => { + return; + }, + Err(ref e) => { + debug!( + target: LOG_TARGET, + "Liveness event error: {:?} ({})", + event_str, e.to_string() + ); + }, + } + }, + + _ = &mut timeout_timer => { + trace!( + target: LOG_TARGET, + "Timed out waiting for pongs, received {} of {} (iter {})", + peer_ping_pongs.iter().filter(|p| p.received_nonce.is_some()).count(), + peer_ping_pongs.len(), + loop_count + ); + break; + }, + } + } + + // Compare nonces and close connections for peers that did not respond multiple times + update_stats_and_cull_unresponsive_connections( + &peer_ping_pongs, + &mut active_peer_connections, + &mut peer_liveness_stats, + loop_count + ).await; + }, + } + } + } +} + +async fn update_stats_and_cull_unresponsive_connections( + peer_ping_pongs: &[PeerPingPong], + active_peer_connections: &mut [PeerConnection], + peer_liveness_stats: &mut HashMap>, + loop_count: u64, +) { + let received_nonces_count = peer_ping_pongs.iter().filter(|p| p.received_nonce.is_some()).count(); + if received_nonces_count != peer_ping_pongs.len() { + trace!( + target: LOG_TARGET, + "Found {} of {} outbound base node peer connections that did not respond to pings", + peer_ping_pongs.len().saturating_sub(received_nonces_count), active_peer_connections.len() + ); + } + + let mut disconnect_peers = Vec::new(); + for &mut ref peer in active_peer_connections.iter_mut() { + if let Some(ping_pong) = peer_ping_pongs.iter().find(|p| &p.node_id == peer.peer_node_id()) { + if ping_pong.received_nonce.is_some() { + peer_liveness_stats + .entry(peer.peer_node_id().clone()) + .and_modify(|item| { + item.push_pop(Stats { + connected: true, + responsive: true, + loop_count, + }) + }); + } else { + peer_liveness_stats + .entry(peer.peer_node_id().clone()) + .and_modify(|item| { + item.push_pop(Stats { + connected: true, + responsive: false, + loop_count, + }) + }); + if let Some(stats) = peer_liveness_stats.get(peer.peer_node_id()) { + // Evaluate the last 3 entries in the stats + if stats + .iter() + .rev() + .take(3) + .filter(|s| s.connected && !s.responsive) + .count() >= + 3 + { + disconnect_peers.push(peer.clone()); + } else { + trace!( + target: LOG_TARGET, + "Peer {} stats - (iter, conn, resp) {:?}", + peer.peer_node_id(), + stats.iter().map(|s|(s.loop_count, s.connected, s.responsive)).collect::>(), + ); + } + } + } + } + } + + for peer in disconnect_peers { + if let Some(stats) = peer_liveness_stats.get(peer.peer_node_id()) { + debug!( + target: LOG_TARGET, + "Disconnecting {} as the peer is no longer responsive - (iter, conn, resp) {:?}", + peer.peer_node_id(), + stats.iter().map(|s|(s.loop_count, s.connected, s.responsive)).collect::>(), + ); + if let Err(e) = peer.clone().disconnect(Minimized::No).await { + warn!( + target: LOG_TARGET, + "Error while attempting to disconnect peer {}: {}", peer.peer_node_id(), e + ); + } + peer_liveness_stats.remove(peer.peer_node_id()); + trace!(target: LOG_TARGET, "Disconnected {} (iter, {})", peer.peer_node_id(), loop_count); + } + } +} From 06f7a6830661ffdc88cd0b90cf4e139123786225 Mon Sep 17 00:00:00 2001 From: Hansie Odendaal <39146854+hansieodendaal@users.noreply.github.com> Date: Thu, 7 Nov 2024 07:40:23 +0200 Subject: [PATCH 02/19] feat: update ledger instructions (#6673) Description --- Updated the ledger wallet build instructions to ensure it is still current. Motivation and Context --- See above. How Has This Been Tested? --- - nanosplus ``` docker run --rm -it -v ".:/app" -w /app/applications/minotari_ledger_wallet/wallet ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder cargo ledger build stax Finished release [optimized] target(s) in 37.50s text data bss dec hex filename 129488 0 11936 141424 22870 /app/applications/minotari_ledger_wallet/wallet/target/nanosplus/release/minotari_ledger_wallet Dumping APDU installation file to /app/applications/minotari_ledger_wallet/wallet/target/nanosplus/release/minotari_ledger_wallet.apdu ``` - stax ``` docker run --rm -it -v ".:/app" -w /app/applications/minotari_ledger_wallet/wallet ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder cargo ledger build stax Finished release [optimized] target(s) in 15.47s text data bss dec hex filename 177552 0 21012 198564 307a4 /app/applications/minotari_ledger_wallet/wallet/target/stax/release/minotari_ledger_wallet Dumping APDU installation file to /app/applications/minotari_ledger_wallet/wallet/target/stax/release/minotari_ledger_wallet.apdu ``` What process can a PR reviewer use to test or verify this change? --- Breaking Changes --- - [x] None - [ ] Requires data directory on base node to be deleted - [ ] Requires hard fork - [ ] Other - Please specify --- applications/minotari_ledger_wallet/wallet/README.md | 7 ++++++- applications/minotari_ledger_wallet/wallet/src/main.rs | 5 +++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/applications/minotari_ledger_wallet/wallet/README.md b/applications/minotari_ledger_wallet/wallet/README.md index aa28371822..8df303142a 100644 --- a/applications/minotari_ledger_wallet/wallet/README.md +++ b/applications/minotari_ledger_wallet/wallet/README.md @@ -72,13 +72,18 @@ For more information see [LedgerCTL](https://github.com/LedgerHQ/ledgerctl). It is recommended to build the Ledger application via the official `ledger-app-builder` Docker image, as the Docker image is properly setup, supported and always kept up to date. +**Note:** Before proceeding, manually delete any ledger docker images from Docker Desktop as those will not be updated +automatically: +- Select he _Images_ tab/menu item +- Select the checkbox next to _ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder_ and then press _Delete_. + ### Option 1: Using Docker Ensure Docker Desktop is installed and running on your machine. The following command has to be run from the root of the Tari repository. -Replace ```{TARGET}``` with the appropriate value (e.g., `nanosplus`, `nanos`, etc.). +Replace ```{TARGET}``` with the appropriate value (e.g., `nanosplus`, `stax`, etc.). Compiled resources will be found in `applications/minotari_ledger_wallet/wallet/target/{TARGET}/release` diff --git a/applications/minotari_ledger_wallet/wallet/src/main.rs b/applications/minotari_ledger_wallet/wallet/src/main.rs index fece1eccd1..d58d130126 100644 --- a/applications/minotari_ledger_wallet/wallet/src/main.rs +++ b/applications/minotari_ledger_wallet/wallet/src/main.rs @@ -229,7 +229,7 @@ extern "C" fn sample_main() { continue; }; - let status = match handle_apdu(&mut comm, ins, &mut offset_ctx) { + let _status = match handle_apdu(&mut comm, ins, &mut offset_ctx) { Ok(()) => { comm.reply_ok(); AppSW::Ok @@ -239,8 +239,9 @@ extern "C" fn sample_main() { sw }, }; + #[cfg(any(target_os = "stax", target_os = "flex"))] - show_status_and_home_if_needed(&ins, &status, &mut offset_ctx, &mut home); + show_status_and_home_if_needed(&ins, &_status, &mut offset_ctx, &mut home); } } From a2aa20e46760384982f7631c200c9196cf1bbb31 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Nov 2024 08:37:49 +0200 Subject: [PATCH 03/19] chore(deps): bump mikepenz/action-junit-report from 4 to 5 (#6672) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 4 to 5.
Release notes

Sourced from mikepenz/action-junit-report's releases.

v5

  • no changes

v5.0.0-rc01

πŸš€ Features

  • Improve parsing logic for nested suites
  • Configuration to enable grouping by TestSuite in the Detail Summary

πŸ’¬ Other

  • Slight code cleanup

Contributors:

v5.0.0-b01

πŸš€ Features

  • Upgrade dependencies to latest major version
  • Add new API to skip annotations all-to-gether
  • Introduce flag to fail_on_parse_error

Contributors:

v5.0.0-a03

πŸš€ Features

  • Improve transformer performance
  • Provide optimised class detection skipping globber if not required

πŸ› Fixes

  • Require pull_request trigger to attach comment

πŸ“¦ Dependencies

... (truncated)

Commits
  • ec3a351 Merge pull request #1225 from mikepenz/feature/grouped_summary
  • b317015 - html formatting
  • 58833a9 - look to further modify formatting
  • 11d2c3e - update tests
  • bc02967 - further improve table format, remove obsolete first column
  • d9c3594 - adjust table structure
  • cfb2e06 - add grouping and comment for nested report
  • 9cc197e - fix group header (no merged cells possible)
  • 0d45d52 - update test
  • dda3b1e - introduce ability to group the test detailed summary
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=mikepenz/action-junit-report&package-manager=github_actions&previous-version=4&new-version=5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish_test_results_ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish_test_results_ci.yml b/.github/workflows/publish_test_results_ci.yml index 0ab37a69d5..9eb60d8cef 100644 --- a/.github/workflows/publish_test_results_ci.yml +++ b/.github/workflows/publish_test_results_ci.yml @@ -48,7 +48,7 @@ jobs: files: "artifacts/**/*.xml" - name: Publish Test Report 2 - uses: mikepenz/action-junit-report@v4 + uses: mikepenz/action-junit-report@v5 if: always() with: report_paths: "artifacts/**/*.xml" From 69a5872e52d8332e0b46e50614b2105bed0d22c9 Mon Sep 17 00:00:00 2001 From: SW van Heerden Date: Thu, 14 Nov 2024 10:14:44 +0200 Subject: [PATCH 04/19] feat!: add new header field (#6686) Description --- Add new header field, block output mmr which only tracks outputs in current block Motivation and Context --- This is needed in order to validate that all outputs included in the block is correctly captured in the pow of the header. The current strategy is to only use the output smt, which commits to all outputs on the blockchain. This is required for horizon sync and prune mode to verify the blockchain as we sync. But someone else wants to verify the block outputs, they have to have the entire outputs set aka entire blockchain in order to verify that the outputs are indeed locked behind pow. This addition allows any person to take only the block and know that the outputs contained in that block, is correctly locked behind the pow of the header. The output field is constructed as two merkle mountain ranges. the primary one used in the header field is constructed as [coinbase_1, coinbase_2, .., coinbase_x, non_coinbase_ouputs_merkle_root] with the non_coinbase_ouputs_merkle_root constructed as [output_1, output_2, .., output_x] This double mountain range approach allows you to prove the output are in the block header, as well as create a proof for a specific output. But separating them allows p2pool to only need to store a single hash + list of all outputs in order to verify all coin bases are correctly included in the header. Rather than all outputs or before this pr, the entire block. Breaking change --- Need to resync database --- .../minotari_app_grpc/proto/block.proto | 5 +- .../src/conversions/block_header.rs | 2 + .../base_node/sync/header_sync/validator.rs | 14 ++++-- base_layer/core/src/blocks/block_header.rs | 19 +++++--- base_layer/core/src/blocks/genesis_block.rs | 47 +++++++++++++++++-- .../src/chain_storage/blockchain_database.rs | 20 ++++++++ .../core/src/consensus/consensus_constants.rs | 31 +++++++----- base_layer/core/src/lib.rs | 6 +++ .../src/proof_of_work/monero_rx/helpers.rs | 9 ++++ .../core/src/proof_of_work/sha3x_pow.rs | 2 +- base_layer/core/src/proto/block.proto | 5 +- base_layer/core/src/proto/block_header.rs | 2 + base_layer/core/src/test_helpers/mod.rs | 1 + .../core/src/validation/block_body/test.rs | 4 ++ base_layer/core/src/validation/helpers.rs | 18 ++++++- .../core/tests/helpers/block_builders.rs | 4 ++ .../core/tests/tests/block_validation.rs | 2 +- 17 files changed, 159 insertions(+), 32 deletions(-) diff --git a/applications/minotari_app_grpc/proto/block.proto b/applications/minotari_app_grpc/proto/block.proto index f5ed70c3ee..afb6d7c855 100644 --- a/applications/minotari_app_grpc/proto/block.proto +++ b/applications/minotari_app_grpc/proto/block.proto @@ -38,9 +38,10 @@ message BlockHeader { bytes prev_hash = 4; // Timestamp at which the block was built. uint64 timestamp = 5; - // This is the UTXO merkle root of the outputs - // This is calculated as Hash (txo MMR root || roaring bitmap hash of UTXO indices) + // This is the UTXO merkle root of the outputs in the blockchain bytes output_mr = 6; + // This is the merkle root of all outputs in this block + bytes block_output_mr = 7; // This is the MMR root of the kernels bytes kernel_mr = 8; // This is the Merkle root of the inputs in this block diff --git a/applications/minotari_app_grpc/src/conversions/block_header.rs b/applications/minotari_app_grpc/src/conversions/block_header.rs index a0eb9e05cc..dccee203e5 100644 --- a/applications/minotari_app_grpc/src/conversions/block_header.rs +++ b/applications/minotari_app_grpc/src/conversions/block_header.rs @@ -39,6 +39,7 @@ impl From for grpc::BlockHeader { timestamp: h.timestamp.as_u64(), input_mr: h.input_mr.to_vec(), output_mr: h.output_mr.to_vec(), + block_output_mr: h.block_output_mr.to_vec(), output_mmr_size: h.output_smt_size, kernel_mr: h.kernel_mr.to_vec(), kernel_mmr_size: h.kernel_mmr_size, @@ -76,6 +77,7 @@ impl TryFrom for BlockHeader { timestamp: EpochTime::from(header.timestamp), input_mr: FixedHash::try_from(header.input_mr).map_err(|err| err.to_string())?, output_mr: FixedHash::try_from(header.output_mr).map_err(|err| err.to_string())?, + block_output_mr: FixedHash::try_from(header.block_output_mr).unwrap_or_default(), output_smt_size: header.output_mmr_size, kernel_mr: FixedHash::try_from(header.kernel_mr).map_err(|err| err.to_string())?, kernel_mmr_size: header.kernel_mmr_size, diff --git a/base_layer/core/src/base_node/sync/header_sync/validator.rs b/base_layer/core/src/base_node/sync/header_sync/validator.rs index 6a60cc81b7..bcf8d6cc05 100644 --- a/base_layer/core/src/base_node/sync/header_sync/validator.rs +++ b/base_layer/core/src/base_node/sync/header_sync/validator.rs @@ -245,13 +245,18 @@ mod test { test_helpers::blockchain::{create_new_blockchain, TempDatabase}, }; - fn setup() -> (BlockHeaderSyncValidator, AsyncBlockchainDb) { + fn setup() -> ( + BlockHeaderSyncValidator, + AsyncBlockchainDb, + ConsensusManager, + ) { let rules = ConsensusManager::builder(Network::LocalNet).build().unwrap(); let randomx_factory = RandomXFactory::default(); let db = create_new_blockchain(); ( - BlockHeaderSyncValidator::new(db.clone().into(), rules, randomx_factory), + BlockHeaderSyncValidator::new(db.clone().into(), rules.clone(), randomx_factory), db.into(), + rules, ) } @@ -262,10 +267,11 @@ mod test { AsyncBlockchainDb, ChainHeader, ) { - let (validator, db) = setup(); + let (validator, db, cm) = setup(); let mut tip = db.fetch_tip_header().await.unwrap(); for _ in 0..n { let mut header = BlockHeader::from_previous(tip.header()); + header.version = cm.consensus_constants(header.height).blockchain_version(); // Needed to have unique keys for the blockchain db mmr count indexes (MDB_KEY_EXIST error) header.kernel_mmr_size += 1; header.output_smt_size += 1; @@ -301,7 +307,7 @@ mod test { #[tokio::test] async fn it_errors_if_hash_does_not_exist() { - let (mut validator, _) = setup(); + let (mut validator, _, _cm) = setup(); let start_hash = vec![0; 32]; let err = validator .initialize_state(&start_hash.clone().try_into().unwrap()) diff --git a/base_layer/core/src/blocks/block_header.rs b/base_layer/core/src/blocks/block_header.rs index 5b5704348c..4988a38e9e 100644 --- a/base_layer/core/src/blocks/block_header.rs +++ b/base_layer/core/src/blocks/block_header.rs @@ -98,9 +98,10 @@ pub struct BlockHeader { pub timestamp: EpochTime, /// This is the Merkle root of the inputs in this block pub input_mr: FixedHash, - /// This is the UTXO merkle root of the outputs - /// This is calculated as Hash (txo MMR root || roaring bitmap hash of UTXO indices) + /// This is the UTXO merkle root of the outputs on the blockchain pub output_mr: FixedHash, + /// This is the block_output_mr + pub block_output_mr: FixedHash, /// The size (number of leaves) of the output and range proof MMRs at the time of this header pub output_smt_size: u64, /// This is the MMR root of the kernels @@ -130,6 +131,7 @@ impl BlockHeader { prev_hash: FixedHash::zero(), timestamp: EpochTime::now(), output_mr: FixedHash::zero(), + block_output_mr: FixedHash::zero(), output_smt_size: 0, kernel_mr: FixedHash::zero(), kernel_mmr_size: 0, @@ -164,6 +166,7 @@ impl BlockHeader { timestamp: EpochTime::now(), output_mr: FixedHash::zero(), output_smt_size: prev.output_smt_size, + block_output_mr: FixedHash::zero(), kernel_mr: FixedHash::zero(), kernel_mmr_size: prev.kernel_mmr_size, input_mr: FixedHash::zero(), @@ -222,7 +225,7 @@ impl BlockHeader { /// Provides a mining hash of the header, used for the mining. /// This differs from the normal hash by not hashing the nonce and kernel pow. pub fn mining_hash(&self) -> FixedHash { - DomainSeparatedConsensusHasher::>::new("block_header") + let incomplete = DomainSeparatedConsensusHasher::>::new("block_header") .chain(&self.version) .chain(&self.height) .chain(&self.prev_hash) @@ -235,9 +238,12 @@ impl BlockHeader { .chain(&self.total_kernel_offset) .chain(&self.total_script_offset) .chain(&self.validator_node_mr) - .chain(&self.validator_node_size) - .finalize() - .into() + .chain(&self.validator_node_size); + + match self.version { + 0 => incomplete.finalize().into(), + _ => incomplete.chain(&self.block_output_mr).finalize().into(), + } } pub fn merge_mining_hash(&self) -> FixedHash { @@ -273,6 +279,7 @@ impl From for BlockHeader { prev_hash: header_template.prev_hash, timestamp: EpochTime::now(), output_mr: FixedHash::zero(), + block_output_mr: FixedHash::zero(), output_smt_size: 0, kernel_mr: FixedHash::zero(), kernel_mmr_size: 0, diff --git a/base_layer/core/src/blocks/genesis_block.rs b/base_layer/core/src/blocks/genesis_block.rs index 5ca7cdf802..8818206ca2 100644 --- a/base_layer/core/src/blocks/genesis_block.rs +++ b/base_layer/core/src/blocks/genesis_block.rs @@ -191,6 +191,8 @@ pub fn get_nextnet_genesis_block() -> ChainBlock { // TODO: Fix this hack with the next nextnet reset!! block.header.input_mr = FixedHash::from_hex("0000000000000000000000000000000000000000000000000000000000000000").unwrap(); + block.header.block_output_mr = + FixedHash::from_hex("0000000000000000000000000000000000000000000000000000000000000000").unwrap(); // Add pre-mine utxos - enable/disable as required let add_pre_mine_utxos = false; @@ -270,6 +272,8 @@ pub fn get_mainnet_genesis_block() -> ChainBlock { FixedHash::from_hex("b7b38b76f5832b5b63691a8334dfa67d8c762b77b2b4aa4f648c4eb1dfb25c1e").unwrap(); block.header.output_mr = FixedHash::from_hex("a77ecf05b20c426d3d400a63397be6c622843c66d5751ecbe3390c8a4885158e").unwrap(); + block.header.block_output_mr = + FixedHash::from_hex("91e997520b0eee770914334692080f92d18db434d373561f8842c56d70c11b97").unwrap(); block.header.validator_node_mr = FixedHash::from_hex("277da65c40b2cf99db86baedb903a3f0a38540f3a94d40c826eecac7e27d5dfc").unwrap(); } @@ -371,6 +375,10 @@ pub fn get_esmeralda_genesis_block() -> ChainBlock { // lets get the block let mut block = get_esmeralda_genesis_block_raw(); + // TODO: Fix this hack with the next esme reset!! + block.header.block_output_mr = + FixedHash::from_hex("0000000000000000000000000000000000000000000000000000000000000000").unwrap(); + // Add pre-mine utxos - enable/disable as required let add_pre_mine_utxos = true; if add_pre_mine_utxos { @@ -482,7 +490,9 @@ fn get_raw_block(genesis_timestamp: &DateTime, not_before_proof: &P height: 0, prev_hash: FixedHash::zero(), timestamp: timestamp.into(), - output_mr: FixedHash::from_hex("0000000000000000000000000000000000000000000000000000000000000000").unwrap(), + output_mr: FixedHash::zero(), + block_output_mr: FixedHash::from_hex("622720a6571c33d6bf6138d9e737d3468c77f1193640698ad459953d24ec0812") + .unwrap(), output_smt_size: 0, kernel_mr: FixedHash::from_hex("c14803066909d6d22abf0d2d2782e8936afc3f713f2af3a4ef5c42e8400c1303").unwrap(), kernel_mmr_size: 0, @@ -518,6 +528,7 @@ mod test { use super::*; use crate::{ + block_output_mr_hash_from_pruned_mmr, chain_storage::calculate_validator_node_mr, consensus::ConsensusManager, test_helpers::blockchain::create_new_blockchain_with_network, @@ -527,8 +538,8 @@ mod test { }, validation::{ChainBalanceValidator, FinalHorizonStateValidation}, KernelMmr, + PrunedOutputMmr, }; - #[test] #[serial] fn esmeralda_genesis_sanity_check() { @@ -661,9 +672,15 @@ mod test { kernel_mmr.push(k.hash().to_vec()).unwrap(); } let mut output_smt = OutputSmt::new(); - + let mut block_output_mmr = PrunedOutputMmr::new(PrunedHashSet::default()); + let mut normal_output_mmr = PrunedOutputMmr::new(PrunedHashSet::default()); let mut vn_nodes = Vec::new(); for o in block.block().body.outputs() { + if o.features.is_coinbase() { + block_output_mmr.push(o.hash().to_vec()).unwrap(); + } else { + normal_output_mmr.push(o.hash().to_vec()).unwrap(); + } let smt_key = NodeKey::try_from(o.commitment.as_bytes()).unwrap(); let smt_node = ValueHash::try_from(o.smt_hash(block.header().height).as_slice()).unwrap(); output_smt.insert(smt_key, smt_node).unwrap(); @@ -681,6 +698,11 @@ mod test { )); } } + + block_output_mmr + .push(normal_output_mmr.get_merkle_root().unwrap().to_vec()) + .unwrap(); + for i in block.block().body.inputs() { let smt_key = NodeKey::try_from(i.commitment().unwrap().as_bytes()).unwrap(); output_smt.delete(&smt_key).unwrap(); @@ -718,6 +740,25 @@ mod test { output_mr_hash_from_smt(&mut output_smt).unwrap().to_vec().to_hex(), block.header().output_mr.to_vec().to_hex(), ); + + // TODO: Fix this hack with the next nextnet/esme release reset!! + if network == Network::NextNet || network == Network::Esmeralda { + assert_eq!( + FixedHash::from_hex("0000000000000000000000000000000000000000000000000000000000000000") + .unwrap() + .to_vec() + .to_hex(), + block.header().block_output_mr.to_vec().to_hex(), + ); + } else { + assert_eq!( + block_output_mr_hash_from_pruned_mmr(&block_output_mmr) + .unwrap() + .to_vec() + .to_hex(), + block.header().block_output_mr.to_vec().to_hex(), + ); + } if network == Network::NextNet { // TODO: Fix this hack with the next nextnet reset!! assert_eq!( diff --git a/base_layer/core/src/chain_storage/blockchain_database.rs b/base_layer/core/src/chain_storage/blockchain_database.rs index 2f00871ac3..85b51e6b25 100644 --- a/base_layer/core/src/chain_storage/blockchain_database.rs +++ b/base_layer/core/src/chain_storage/blockchain_database.rs @@ -49,6 +49,7 @@ use tari_utilities::{epoch_time::EpochTime, hex::Hex, ByteArray}; use super::TemplateRegistrationEntry; use crate::{ + block_output_mr_hash_from_pruned_mmr, blocks::{ Block, BlockAccumulatedData, @@ -105,6 +106,7 @@ use crate::{ OutputSmt, PrunedInputMmr, PrunedKernelMmr, + PrunedOutputMmr, ValidatorNodeBMT, }; @@ -912,6 +914,7 @@ where B: BlockchainBackend block.header.kernel_mmr_size = roots.kernel_mmr_size; block.header.input_mr = roots.input_mr; block.header.output_mr = roots.output_mr; + block.header.block_output_mr = roots.block_output_mr; block.header.output_smt_size = roots.output_smt_size; block.header.validator_node_mr = roots.validator_node_mr; block.header.validator_node_size = roots.validator_node_size; @@ -1321,6 +1324,7 @@ pub struct MmrRoots { pub kernel_mmr_size: u64, pub input_mr: FixedHash, pub output_mr: FixedHash, + pub block_output_mr: FixedHash, pub output_smt_size: u64, pub validator_node_mr: FixedHash, pub validator_node_size: u64, @@ -1333,6 +1337,7 @@ impl std::fmt::Display for MmrRoots { writeln!(f, "Kernel MR : {}", self.kernel_mr)?; writeln!(f, "Kernel MMR Size : {}", self.kernel_mmr_size)?; writeln!(f, "Output MR : {}", self.output_mr)?; + writeln!(f, "Block Output MR : {}", self.block_output_mr)?; writeln!(f, "Output SMT Size : {}", self.output_smt_size)?; writeln!(f, "Validator MR : {}", self.validator_node_mr)?; Ok(()) @@ -1372,6 +1377,8 @@ pub fn calculate_mmr_roots( let mut kernel_mmr = PrunedKernelMmr::new(kernels); let mut input_mmr = PrunedInputMmr::new(PrunedHashSet::default()); + let mut block_output_mmr = PrunedOutputMmr::new(PrunedHashSet::default()); + let mut normal_output_mmr = PrunedOutputMmr::new(PrunedHashSet::default()); for kernel in body.kernels() { kernel_mmr.push(kernel.hash().to_vec())?; @@ -1379,6 +1386,11 @@ pub fn calculate_mmr_roots( let mut outputs_to_remove = Vec::new(); for output in body.outputs() { + if output.features.is_coinbase() { + block_output_mmr.push(output.hash().to_vec())?; + } else { + normal_output_mmr.push(output.hash().to_vec())?; + } if !output.is_burned() { let smt_key = NodeKey::try_from(output.commitment.as_bytes())?; let smt_node = ValueHash::try_from(output.smt_hash(header.height).as_slice())?; @@ -1393,6 +1405,7 @@ pub fn calculate_mmr_roots( } } } + block_output_mmr.push(normal_output_mmr.get_merkle_root()?.to_vec())?; let mut outputs_to_add = Vec::new(); for input in body.inputs() { @@ -1426,11 +1439,18 @@ pub fn calculate_mmr_roots( (tip_header.validator_node_mr, 0) }; + let block_output_mr = if block.version() > 0 { + block_output_mr_hash_from_pruned_mmr(&block_output_mmr)? + } else { + FixedHash::zero() + }; + let mmr_roots = MmrRoots { kernel_mr: kernel_mr_hash_from_pruned_mmr(&kernel_mmr)?, kernel_mmr_size: kernel_mmr.get_leaf_count()? as u64, input_mr: input_mr_hash_from_pruned_mmr(&input_mmr)?, output_mr: output_mr_hash_from_smt(output_smt)?, + block_output_mr, output_smt_size: output_smt.size(), validator_node_mr, validator_node_size: validator_node_size as u64, diff --git a/base_layer/core/src/consensus/consensus_constants.rs b/base_layer/core/src/consensus/consensus_constants.rs index 7762f94dc2..796a68f728 100644 --- a/base_layer/core/src/consensus/consensus_constants.rs +++ b/base_layer/core/src/consensus/consensus_constants.rs @@ -389,8 +389,8 @@ impl ConsensusConstants { let consensus_constants = vec![ConsensusConstants { effective_from_height: 0, coinbase_min_maturity: 2, - blockchain_version: 0, - valid_blockchain_version_range: 0..=0, + blockchain_version: 1, + valid_blockchain_version_range: 1..=1, future_time_limit: 540, difficulty_block_window, max_block_transaction_weight: 19500, @@ -509,7 +509,7 @@ impl ConsensusConstants { target_time: 240, }); let (input_version_range, output_version_range, kernel_version_range) = version_zero(); - let consensus_constants = vec![ConsensusConstants { + let consensus_constants1 = ConsensusConstants { effective_from_height: 0, coinbase_min_maturity: 6, blockchain_version: 0, @@ -541,9 +541,14 @@ impl ConsensusConstants { vn_registration_lock_height: 0, vn_registration_shuffle_interval: VnEpoch(100), coinbase_output_features_extra_max_length: 256, - }]; + }; + let mut consensus_constants2 = consensus_constants1.clone(); + consensus_constants2.blockchain_version = 1; + consensus_constants2.effective_from_height = 16000; + consensus_constants2.valid_blockchain_version_range = 1..=1; + let consensus_constants = vec![consensus_constants1, consensus_constants2]; #[cfg(any(test, debug_assertions))] - assert_hybrid_pow_constants(&consensus_constants, &[120], &[50], &[50]); + assert_hybrid_pow_constants(&consensus_constants, &[120, 120], &[50, 50], &[50, 50]); consensus_constants } @@ -569,8 +574,8 @@ impl ConsensusConstants { let consensus_constants = vec![ConsensusConstants { effective_from_height: 0, coinbase_min_maturity: 360, - blockchain_version: 0, - valid_blockchain_version_range: 0..=0, + blockchain_version: 1, + valid_blockchain_version_range: 1..=1, future_time_limit: 540, difficulty_block_window: 90, max_block_transaction_weight: 127_795, @@ -653,10 +658,14 @@ impl ConsensusConstants { let mut con_2 = con_1.clone(); con_2.effective_from_height = 33000; con_2.coinbase_output_features_extra_max_length = 256; + let mut con_3 = con_2.clone(); + con_3.effective_from_height = 52000; + con_3.blockchain_version = 1; + con_3.valid_blockchain_version_range = 1..=1; - let consensus_constants = vec![con_1, con_2]; + let consensus_constants = vec![con_1, con_2, con_3]; #[cfg(any(test, debug_assertions))] - assert_hybrid_pow_constants(&consensus_constants, &[120, 120], &[50, 50], &[50, 50]); + assert_hybrid_pow_constants(&consensus_constants, &[120, 120, 120], &[50, 50, 50], &[50, 50, 50]); consensus_constants } @@ -678,8 +687,8 @@ impl ConsensusConstants { let consensus_constants = vec![ConsensusConstants { effective_from_height: 0, coinbase_min_maturity: 720, - blockchain_version: 0, - valid_blockchain_version_range: 0..=0, + blockchain_version: 1, + valid_blockchain_version_range: 1..=1, future_time_limit: 540, difficulty_block_window, max_block_transaction_weight: 127_795, diff --git a/base_layer/core/src/lib.rs b/base_layer/core/src/lib.rs index 03e1b86c5b..5c8812467c 100644 --- a/base_layer/core/src/lib.rs +++ b/base_layer/core/src/lib.rs @@ -85,6 +85,7 @@ mod domain_hashing { hash_domain!(InputMmrHashDomain, "com.tari.base_layer.core.input_mmr", 1); pub type InputMmrHasherBlake256 = DomainSeparatedHasher, InputMmrHashDomain>; pub type PrunedInputMmr = MerkleMountainRange; + pub type PrunedOutputMmr = MerkleMountainRange; pub type OutputSmt = SparseMerkleTree; @@ -111,6 +112,11 @@ mod domain_hashing { Ok(FixedHash::try_from(input_mmr.get_merkle_root()?)?) } + #[inline] + pub fn block_output_mr_hash_from_pruned_mmr(output_mmr: &PrunedOutputMmr) -> Result { + Ok(FixedHash::try_from(output_mmr.get_merkle_root()?)?) + } + #[derive(Debug, thiserror::Error)] pub enum MrHashError { #[error("Output SMT conversion error: {0}")] diff --git a/base_layer/core/src/proof_of_work/monero_rx/helpers.rs b/base_layer/core/src/proof_of_work/monero_rx/helpers.rs index 100e09c4b7..7f57275e38 100644 --- a/base_layer/core/src/proof_of_work/monero_rx/helpers.rs +++ b/base_layer/core/src/proof_of_work/monero_rx/helpers.rs @@ -550,6 +550,7 @@ mod test { prev_hash: FixedHash::zero(), timestamp: EpochTime::now(), output_mr: FixedHash::zero(), + block_output_mr: FixedHash::zero(), output_smt_size: 0, kernel_mr: FixedHash::zero(), kernel_mmr_size: 0, @@ -652,6 +653,7 @@ mod test { prev_hash: FixedHash::zero(), timestamp: EpochTime::now(), output_mr: FixedHash::zero(), + block_output_mr: FixedHash::zero(), output_smt_size: 0, kernel_mr: FixedHash::zero(), kernel_mmr_size: 0, @@ -726,6 +728,7 @@ mod test { prev_hash: FixedHash::zero(), timestamp: EpochTime::now(), output_mr: FixedHash::zero(), + block_output_mr: FixedHash::zero(), output_smt_size: 0, kernel_mr: FixedHash::zero(), kernel_mmr_size: 0, @@ -798,6 +801,7 @@ mod test { prev_hash: FixedHash::zero(), timestamp: EpochTime::now(), output_mr: FixedHash::zero(), + block_output_mr: FixedHash::zero(), output_smt_size: 0, kernel_mr: FixedHash::zero(), kernel_mmr_size: 0, @@ -874,6 +878,7 @@ mod test { prev_hash: FixedHash::zero(), timestamp: EpochTime::now(), output_mr: FixedHash::zero(), + block_output_mr: FixedHash::zero(), output_smt_size: 0, kernel_mr: FixedHash::zero(), kernel_mmr_size: 0, @@ -970,6 +975,7 @@ mod test { prev_hash: FixedHash::zero(), timestamp: EpochTime::now(), output_mr: FixedHash::zero(), + block_output_mr: FixedHash::zero(), output_smt_size: 0, kernel_mr: FixedHash::zero(), kernel_mmr_size: 0, @@ -1030,6 +1036,7 @@ mod test { prev_hash: FixedHash::zero(), timestamp: EpochTime::now(), output_mr: FixedHash::zero(), + block_output_mr: FixedHash::zero(), output_smt_size: 0, kernel_mr: FixedHash::zero(), kernel_mmr_size: 0, @@ -1102,6 +1109,7 @@ mod test { prev_hash: FixedHash::zero(), timestamp: EpochTime::now(), output_mr: FixedHash::zero(), + block_output_mr: FixedHash::zero(), output_smt_size: 0, kernel_mr: FixedHash::zero(), kernel_mmr_size: 0, @@ -1163,6 +1171,7 @@ mod test { prev_hash: FixedHash::zero(), timestamp: EpochTime::now(), output_mr: FixedHash::zero(), + block_output_mr: FixedHash::zero(), output_smt_size: 0, kernel_mr: FixedHash::zero(), kernel_mmr_size: 0, diff --git a/base_layer/core/src/proof_of_work/sha3x_pow.rs b/base_layer/core/src/proof_of_work/sha3x_pow.rs index c1953826b2..af788c3288 100644 --- a/base_layer/core/src/proof_of_work/sha3x_pow.rs +++ b/base_layer/core/src/proof_of_work/sha3x_pow.rs @@ -101,6 +101,6 @@ pub mod test { let mut header = get_header(); header.nonce = 631; println!("{:?}", header); - assert_eq!(sha3x_difficulty(&header).unwrap(), Difficulty::from_u64(28).unwrap()); + assert_eq!(sha3x_difficulty(&header).unwrap(), Difficulty::from_u64(13).unwrap()); } } diff --git a/base_layer/core/src/proto/block.proto b/base_layer/core/src/proto/block.proto index 9636958120..184a8d3c53 100644 --- a/base_layer/core/src/proto/block.proto +++ b/base_layer/core/src/proto/block.proto @@ -31,9 +31,10 @@ message BlockHeader { bytes prev_hash = 4; // Timestamp at which the block was built. uint64 timestamp = 5; - // This is the UTXO merkle root of the outputs - // This is calculated as Hash (txo MMR root || roaring bitmap hash of UTXO indices) + // This is the UTXO merkle root of the outputs in the blockchain bytes output_mr = 6; + // This is the merkle root of all outputs in this block + bytes block_output_mr = 7; // This is the MMR root of the kernels bytes kernel_mr = 8; // This is the Merkle root of the inputs in this block diff --git a/base_layer/core/src/proto/block_header.rs b/base_layer/core/src/proto/block_header.rs index 3503657990..98303b34ba 100644 --- a/base_layer/core/src/proto/block_header.rs +++ b/base_layer/core/src/proto/block_header.rs @@ -52,6 +52,7 @@ impl TryFrom for BlockHeader { prev_hash: FixedHash::try_from(header.prev_hash).map_err(|err| err.to_string())?, timestamp: EpochTime::from(header.timestamp), output_mr: FixedHash::try_from(header.output_mr).map_err(|err| err.to_string())?, + block_output_mr: FixedHash::try_from(header.block_output_mr).unwrap_or_default(), output_smt_size: header.output_mmr_size, kernel_mr: FixedHash::try_from(header.kernel_mr).map_err(|err| err.to_string())?, kernel_mmr_size: header.kernel_mmr_size, @@ -74,6 +75,7 @@ impl From for proto::BlockHeader { prev_hash: header.prev_hash.to_vec(), timestamp: header.timestamp.as_u64(), output_mr: header.output_mr.to_vec(), + block_output_mr: header.block_output_mr.to_vec(), kernel_mr: header.kernel_mr.to_vec(), input_mr: header.input_mr.to_vec(), total_kernel_offset: header.total_kernel_offset.to_vec(), diff --git a/base_layer/core/src/test_helpers/mod.rs b/base_layer/core/src/test_helpers/mod.rs index a8677fbdda..24bb2d67a8 100644 --- a/base_layer/core/src/test_helpers/mod.rs +++ b/base_layer/core/src/test_helpers/mod.rs @@ -95,6 +95,7 @@ pub async fn create_block( range_proof_type: Option, ) -> (Block, WalletOutput) { let mut header = BlockHeader::from_previous(&prev_block.header); + header.version = rules.consensus_constants(header.height).blockchain_version(); let block_height = spec.height_override.unwrap_or(prev_block.header.height + 1); header.height = block_height; let reward = spec.reward_override.unwrap_or_else(|| { diff --git a/base_layer/core/src/validation/block_body/test.rs b/base_layer/core/src/validation/block_body/test.rs index fede6a9984..1afa2f3f66 100644 --- a/base_layer/core/src/validation/block_body/test.rs +++ b/base_layer/core/src/validation/block_body/test.rs @@ -94,6 +94,7 @@ async fn it_passes_if_large_output_block_is_valid() { .calculate_mmr_roots(chain_block.block().clone()) .unwrap(); block.header.input_mr = mmr_roots.input_mr; + block.header.block_output_mr = mmr_roots.block_output_mr; block.header.output_mr = mmr_roots.output_mr; block.header.output_smt_size = mmr_roots.output_smt_size; block.header.kernel_mr = mmr_roots.kernel_mr; @@ -131,6 +132,7 @@ async fn it_validates_when_a_coinbase_is_spent() { .unwrap(); block.header.input_mr = mmr_roots.input_mr; block.header.output_mr = mmr_roots.output_mr; + block.header.block_output_mr = mmr_roots.block_output_mr; block.header.output_smt_size = mmr_roots.output_smt_size; block.header.kernel_mr = mmr_roots.kernel_mr; block.header.kernel_mmr_size = mmr_roots.kernel_mmr_size; @@ -173,6 +175,7 @@ async fn it_passes_if_large_block_is_valid() { .unwrap(); block.header.input_mr = mmr_roots.input_mr; block.header.output_mr = mmr_roots.output_mr; + block.header.block_output_mr = mmr_roots.block_output_mr; block.header.output_smt_size = mmr_roots.output_smt_size; block.header.kernel_mr = mmr_roots.kernel_mr; block.header.kernel_mmr_size = mmr_roots.kernel_mmr_size; @@ -203,6 +206,7 @@ async fn it_passes_if_block_is_valid() { .unwrap(); block.header.input_mr = mmr_roots.input_mr; block.header.output_mr = mmr_roots.output_mr; + block.header.block_output_mr = mmr_roots.block_output_mr; block.header.output_smt_size = mmr_roots.output_smt_size; block.header.kernel_mr = mmr_roots.kernel_mr; block.header.kernel_mmr_size = mmr_roots.kernel_mmr_size; diff --git a/base_layer/core/src/validation/helpers.rs b/base_layer/core/src/validation/helpers.rs index 160706defe..489ee2beff 100644 --- a/base_layer/core/src/validation/helpers.rs +++ b/base_layer/core/src/validation/helpers.rs @@ -263,6 +263,7 @@ pub fn check_not_duplicate_txo( Ok(()) } +#[allow(clippy::too_many_lines)] pub fn check_mmr_roots(header: &BlockHeader, mmr_roots: &MmrRoots) -> Result<(), ValidationError> { if header.kernel_mr != mmr_roots.kernel_mr { warn!( @@ -302,7 +303,7 @@ pub fn check_mmr_roots(header: &BlockHeader, mmr_roots: &MmrRoots) -> Result<(), mmr_roots.output_mr.to_hex() ); return Err(ValidationError::BlockError(BlockValidationError::MismatchedMmrRoots { - kind: "Utxo", + kind: "Utxos", })); }; if header.output_smt_size != mmr_roots.output_smt_size { @@ -318,7 +319,20 @@ pub fn check_mmr_roots(header: &BlockHeader, mmr_roots: &MmrRoots) -> Result<(), expected: mmr_roots.output_smt_size, actual: header.output_smt_size, })); - } + }; + if header.block_output_mr != mmr_roots.block_output_mr { + warn!( + target: LOG_TARGET, + "Block header block output MMR roots in #{} {} do not match calculated roots. Expected: {}, Actual:{}", + header.height, + header.hash().to_hex(), + header.block_output_mr, + mmr_roots.block_output_mr, + ); + return Err(ValidationError::BlockError(BlockValidationError::MismatchedMmrRoots { + kind: "block outputs", + })); + }; if header.input_mr != mmr_roots.input_mr { warn!( target: LOG_TARGET, diff --git a/base_layer/core/tests/helpers/block_builders.rs b/base_layer/core/tests/helpers/block_builders.rs index dc58fb1e73..6827a9048f 100644 --- a/base_layer/core/tests/helpers/block_builders.rs +++ b/base_layer/core/tests/helpers/block_builders.rs @@ -62,6 +62,7 @@ use tari_core::{ OutputSmt, PrunedInputMmr, PrunedKernelMmr, + PrunedOutputMmr, }; use tari_key_manager::key_manager_service::KeyManagerInterface; use tari_mmr::{ @@ -206,7 +207,9 @@ fn update_genesis_block_mmr_roots(template: NewBlockTemplate) -> Result Result Date: Thu, 14 Nov 2024 10:48:36 +0200 Subject: [PATCH 05/19] chore: new release for esme v1.9.0-pre.0 (#6688) Description --- new release for esme --- Cargo.lock | 68 +++++++++---------- README.md | 4 +- applications/minotari_app_grpc/Cargo.toml | 4 +- .../minotari_app_utilities/Cargo.toml | 4 +- .../minotari_console_wallet/Cargo.toml | 6 +- .../minotari_ledger_wallet/common/Cargo.toml | 2 +- .../minotari_ledger_wallet/comms/Cargo.toml | 2 +- .../minotari_ledger_wallet/wallet/Cargo.lock | 4 +- .../minotari_ledger_wallet/wallet/Cargo.toml | 4 +- .../minotari_merge_mining_proxy/Cargo.toml | 4 +- applications/minotari_miner/Cargo.toml | 2 +- applications/minotari_node/Cargo.toml | 6 +- base_layer/chat_ffi/Cargo.toml | 2 +- base_layer/common_types/Cargo.toml | 4 +- base_layer/contacts/Cargo.toml | 20 +++--- .../contacts/src/chat_client/Cargo.toml | 2 +- base_layer/core/Cargo.toml | 36 +++++----- base_layer/key_manager/Cargo.toml | 8 +-- base_layer/mmr/Cargo.toml | 2 +- base_layer/p2p/Cargo.toml | 16 ++--- base_layer/service_framework/Cargo.toml | 4 +- base_layer/tari_mining_helper_ffi/Cargo.toml | 6 +- base_layer/wallet/Cargo.toml | 28 ++++---- base_layer/wallet_ffi/Cargo.toml | 4 +- changelog-development.md | 18 +++++ changelog-nextnet.md | 19 ++++++ common/Cargo.toml | 6 +- common/tari_features/Cargo.toml | 2 +- common_sqlite/Cargo.toml | 2 +- comms/core/Cargo.toml | 10 +-- comms/dht/Cargo.toml | 16 ++--- comms/rpc_macros/Cargo.toml | 2 +- hashing/Cargo.toml | 2 +- infrastructure/derive/Cargo.toml | 2 +- infrastructure/libtor/Cargo.toml | 2 +- infrastructure/max_size/Cargo.toml | 2 +- infrastructure/metrics/Cargo.toml | 2 +- infrastructure/shutdown/Cargo.toml | 2 +- infrastructure/storage/Cargo.toml | 2 +- infrastructure/tari_script/Cargo.toml | 2 +- infrastructure/test_utils/Cargo.toml | 6 +- package-lock.json | 2 +- 42 files changed, 189 insertions(+), 152 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9e7cc3d47b..9e58b5e9a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3550,7 +3550,7 @@ dependencies = [ [[package]] name = "minotari_app_grpc" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "argon2", "base64 0.13.1", @@ -3579,7 +3579,7 @@ dependencies = [ [[package]] name = "minotari_app_utilities" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "clap 3.2.25", "dialoguer 0.10.4", @@ -3601,7 +3601,7 @@ dependencies = [ [[package]] name = "minotari_chat_ffi" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "cbindgen", "chrono", @@ -3626,7 +3626,7 @@ dependencies = [ [[package]] name = "minotari_console_wallet" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "blake2", "chrono", @@ -3682,14 +3682,14 @@ dependencies = [ [[package]] name = "minotari_ledger_wallet_common" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "bs58 0.5.1", ] [[package]] name = "minotari_ledger_wallet_comms" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "borsh", "dialoguer 0.11.0", @@ -3711,7 +3711,7 @@ dependencies = [ [[package]] name = "minotari_merge_mining_proxy" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "anyhow", "bincode", @@ -3753,7 +3753,7 @@ dependencies = [ [[package]] name = "minotari_miner" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "base64 0.13.1", "borsh", @@ -3790,7 +3790,7 @@ dependencies = [ [[package]] name = "minotari_mining_helper_ffi" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "borsh", "cbindgen", @@ -3809,7 +3809,7 @@ dependencies = [ [[package]] name = "minotari_node" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "anyhow", "async-trait", @@ -3866,7 +3866,7 @@ dependencies = [ [[package]] name = "minotari_wallet" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "argon2", "async-trait", @@ -3917,7 +3917,7 @@ dependencies = [ [[package]] name = "minotari_wallet_ffi" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "borsh", "cbindgen", @@ -6393,7 +6393,7 @@ dependencies = [ [[package]] name = "tari_chat_client" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "anyhow", "async-trait", @@ -6420,7 +6420,7 @@ dependencies = [ [[package]] name = "tari_common" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "anyhow", "config", @@ -6445,7 +6445,7 @@ dependencies = [ [[package]] name = "tari_common_sqlite" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "diesel", "diesel_migrations", @@ -6459,7 +6459,7 @@ dependencies = [ [[package]] name = "tari_common_types" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "base64 0.21.5", "bitflags 2.4.1", @@ -6484,7 +6484,7 @@ dependencies = [ [[package]] name = "tari_comms" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "anyhow", "async-trait", @@ -6534,7 +6534,7 @@ dependencies = [ [[package]] name = "tari_comms_dht" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "anyhow", "bitflags 2.4.1", @@ -6578,7 +6578,7 @@ dependencies = [ [[package]] name = "tari_comms_rpc_macros" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "futures 0.3.29", "proc-macro2", @@ -6593,7 +6593,7 @@ dependencies = [ [[package]] name = "tari_contacts" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "chrono", "diesel", @@ -6627,7 +6627,7 @@ dependencies = [ [[package]] name = "tari_core" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "async-trait", "bincode", @@ -6727,11 +6727,11 @@ dependencies = [ [[package]] name = "tari_features" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" [[package]] name = "tari_hashing" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "blake2", "borsh", @@ -6789,7 +6789,7 @@ dependencies = [ [[package]] name = "tari_key_manager" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "argon2", "async-trait", @@ -6824,7 +6824,7 @@ dependencies = [ [[package]] name = "tari_libtor" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "derivative", "libtor", @@ -6838,7 +6838,7 @@ dependencies = [ [[package]] name = "tari_max_size" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "borsh", "serde", @@ -6848,7 +6848,7 @@ dependencies = [ [[package]] name = "tari_metrics" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "anyhow", "futures 0.3.29", @@ -6863,7 +6863,7 @@ dependencies = [ [[package]] name = "tari_mmr" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "bincode", "blake2", @@ -6881,7 +6881,7 @@ dependencies = [ [[package]] name = "tari_p2p" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "anyhow", "clap 3.2.25", @@ -6919,7 +6919,7 @@ dependencies = [ [[package]] name = "tari_script" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "blake2", "borsh", @@ -6937,7 +6937,7 @@ dependencies = [ [[package]] name = "tari_service_framework" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "anyhow", "async-trait", @@ -6954,7 +6954,7 @@ dependencies = [ [[package]] name = "tari_shutdown" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "futures 0.3.29", "tokio", @@ -6962,7 +6962,7 @@ dependencies = [ [[package]] name = "tari_storage" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "bincode", "lmdb-zero", @@ -6975,7 +6975,7 @@ dependencies = [ [[package]] name = "tari_test_utils" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "futures 0.3.29", "futures-test", diff --git a/README.md b/README.md index 6c4f93c83b..df55d32d82 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,8 @@ The recommended running versions of each network are: | Network | Version | |-----------|----------------| | Stagenet | 1.0.0-alpha.0a | -| Nextnet | 1.8.0-rc.0 | -| Esmeralda | 1.8.0-pre.0 | +| Nextnet | 1.9.0-rc.0 | +| Esmeralda | 1.9.0-pre.0 | For more detail about versioning, see [Release Ideology](https://github.com/tari-project/tari/blob/development/docs/src/branching_releases.md). diff --git a/applications/minotari_app_grpc/Cargo.toml b/applications/minotari_app_grpc/Cargo.toml index e96ea151e9..0e4d1e0234 100644 --- a/applications/minotari_app_grpc/Cargo.toml +++ b/applications/minotari_app_grpc/Cargo.toml @@ -4,7 +4,7 @@ authors = ["The Tari Development Community"] description = "This crate is to provide a single source for all cross application grpc files and conversions to and from tari::core" repository = "https://github.com/tari-project/tari" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2021" [dependencies] @@ -32,7 +32,7 @@ tonic = { version = "0.12.3", features = ["tls"] } zeroize = "1" [build-dependencies] -tari_features = { path = "../../common/tari_features", version = "1.8.0-pre.0" } +tari_features = { path = "../../common/tari_features", version = "1.9.0-pre.0" } tonic-build = "0.12.3" [package.metadata.cargo-machete] diff --git a/applications/minotari_app_utilities/Cargo.toml b/applications/minotari_app_utilities/Cargo.toml index 8a1c96c6a4..2874d987ab 100644 --- a/applications/minotari_app_utilities/Cargo.toml +++ b/applications/minotari_app_utilities/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minotari_app_utilities" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" authors = ["The Tari Development Community"] edition = "2018" license = "BSD-3-Clause" @@ -30,7 +30,7 @@ tari_common = { path = "../../common", features = [ "build", "static-application-info", ] } -tari_features = { path = "../../common/tari_features", version = "1.8.0-pre.0" } +tari_features = { path = "../../common/tari_features", version = "1.9.0-pre.0" } [features] miner_input = ["minotari_app_grpc"] diff --git a/applications/minotari_console_wallet/Cargo.toml b/applications/minotari_console_wallet/Cargo.toml index b813f6b8c9..1af92fe1b5 100644 --- a/applications/minotari_console_wallet/Cargo.toml +++ b/applications/minotari_console_wallet/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minotari_console_wallet" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" authors = ["The Tari Development Community"] edition = "2018" license = "BSD-3-Clause" @@ -8,7 +8,7 @@ license = "BSD-3-Clause" [dependencies] minotari_app_grpc = { path = "../minotari_app_grpc" } minotari_app_utilities = { path = "../minotari_app_utilities" } -minotari_ledger_wallet_comms = { path = "../../applications/minotari_ledger_wallet/comms", version = "1.8.0-pre.0", optional = true } +minotari_ledger_wallet_comms = { path = "../../applications/minotari_ledger_wallet/comms", version = "1.9.0-pre.0", optional = true } tari_common = { path = "../../common" } tari_common_types = { path = "../../base_layer/common_types" } tari_comms = { path = "../../comms/core" } @@ -84,7 +84,7 @@ default-features = false features = ["crossterm"] [build-dependencies] -tari_features = { path = "../../common/tari_features", version = "1.8.0-pre.0" } +tari_features = { path = "../../common/tari_features", version = "1.9.0-pre.0" } [features] default = ["libtor", "ledger"] diff --git a/applications/minotari_ledger_wallet/common/Cargo.toml b/applications/minotari_ledger_wallet/common/Cargo.toml index f56716b331..fb3a371c7d 100644 --- a/applications/minotari_ledger_wallet/common/Cargo.toml +++ b/applications/minotari_ledger_wallet/common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minotari_ledger_wallet_common" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" authors = ["The Tari Development Community"] license = "BSD-3-Clause" edition = "2021" diff --git a/applications/minotari_ledger_wallet/comms/Cargo.toml b/applications/minotari_ledger_wallet/comms/Cargo.toml index 5da4718c90..3b710a1011 100644 --- a/applications/minotari_ledger_wallet/comms/Cargo.toml +++ b/applications/minotari_ledger_wallet/comms/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minotari_ledger_wallet_comms" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" authors = ["The Tari Development Community"] license = "BSD-3-Clause" edition = "2021" diff --git a/applications/minotari_ledger_wallet/wallet/Cargo.lock b/applications/minotari_ledger_wallet/wallet/Cargo.lock index 90dbf6694a..b46bcd7b55 100644 --- a/applications/minotari_ledger_wallet/wallet/Cargo.lock +++ b/applications/minotari_ledger_wallet/wallet/Cargo.lock @@ -432,7 +432,7 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "minotari_ledger_wallet" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "blake2", "borsh", @@ -735,7 +735,7 @@ dependencies = [ [[package]] name = "tari_hashing" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "borsh", "digest", diff --git a/applications/minotari_ledger_wallet/wallet/Cargo.toml b/applications/minotari_ledger_wallet/wallet/Cargo.toml index 3853bca4fa..f1374485cc 100644 --- a/applications/minotari_ledger_wallet/wallet/Cargo.toml +++ b/applications/minotari_ledger_wallet/wallet/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minotari_ledger_wallet" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" authors = ["The Tari Development Community"] license = "BSD-3-Clause" edition = "2021" @@ -9,7 +9,7 @@ edition = "2021" tari_crypto = { version = "0.21.0", default-features = false, features = [ "borsh", ] } -tari_hashing = { path = "../../../hashing", version = "1.8.0-pre.0" } +tari_hashing = { path = "../../../hashing", version = "1.9.0-pre.0" } minotari_ledger_wallet_common = { path = "../common" } diff --git a/applications/minotari_merge_mining_proxy/Cargo.toml b/applications/minotari_merge_mining_proxy/Cargo.toml index 9427af3520..d3c28477d3 100644 --- a/applications/minotari_merge_mining_proxy/Cargo.toml +++ b/applications/minotari_merge_mining_proxy/Cargo.toml @@ -4,7 +4,7 @@ authors = ["The Tari Development Community"] description = "The Tari merge mining proxy for xmrig" repository = "https://github.com/tari-project/tari" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [features] @@ -55,7 +55,7 @@ url = "2.1.1" scraper = "0.19.0" [build-dependencies] -tari_features = { path = "../../common/tari_features", version = "1.8.0-pre.0" } +tari_features = { path = "../../common/tari_features", version = "1.9.0-pre.0" } [dev-dependencies] hyper = { version ="0.14.12", features = ["full"] } diff --git a/applications/minotari_miner/Cargo.toml b/applications/minotari_miner/Cargo.toml index 5fcff23fb1..1ed94a93ad 100644 --- a/applications/minotari_miner/Cargo.toml +++ b/applications/minotari_miner/Cargo.toml @@ -4,7 +4,7 @@ authors = ["The Tari Development Community"] description = "The tari miner implementation" repository = "https://github.com/tari-project/tari" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [dependencies] diff --git a/applications/minotari_node/Cargo.toml b/applications/minotari_node/Cargo.toml index f565f05f2e..5a1d7d3d95 100644 --- a/applications/minotari_node/Cargo.toml +++ b/applications/minotari_node/Cargo.toml @@ -4,7 +4,7 @@ authors = ["The Tari Development Community"] description = "The tari full base node implementation" repository = "https://github.com/tari-project/tari" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [dependencies] @@ -26,7 +26,7 @@ tari_shutdown = { path = "../../infrastructure/shutdown" } tari_utilities = { version = "0.8" } tari_key_manager = { path = "../../base_layer/key_manager", features = [ "key_manager_service", -], version = "1.8.0-pre.0" } +], version = "1.9.0-pre.0" } anyhow = "1.0.53" async-trait = "0.1.52" @@ -77,7 +77,7 @@ safe = [] libtor = ["tari_libtor"] [build-dependencies] -tari_features = { path = "../../common/tari_features", version = "1.8.0-pre.0" } +tari_features = { path = "../../common/tari_features", version = "1.9.0-pre.0" } [package.metadata.cargo-machete] ignored = [ diff --git a/base_layer/chat_ffi/Cargo.toml b/base_layer/chat_ffi/Cargo.toml index 14c14dea2e..3ba31ca33b 100644 --- a/base_layer/chat_ffi/Cargo.toml +++ b/base_layer/chat_ffi/Cargo.toml @@ -3,7 +3,7 @@ name = "minotari_chat_ffi" authors = ["The Tari Development Community"] description = "Tari cryptocurrency chat C FFI bindings" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [dependencies] diff --git a/base_layer/common_types/Cargo.toml b/base_layer/common_types/Cargo.toml index d13a3637fa..ccb2a92943 100644 --- a/base_layer/common_types/Cargo.toml +++ b/base_layer/common_types/Cargo.toml @@ -3,13 +3,13 @@ name = "tari_common_types" authors = ["The Tari Development Community"] description = "Tari cryptocurrency common types" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [dependencies] tari_crypto = { version = "0.21.0" } tari_utilities = { version = "0.8" } -tari_common = { path = "../../common", version = "1.8.0-pre.0" } +tari_common = { path = "../../common", version = "1.9.0-pre.0" } minotari_ledger_wallet_common = { path = "../../applications/minotari_ledger_wallet/common" } chacha20poly1305 = "0.10.1" bitflags = { version = "2.4", features = ["serde"] } diff --git a/base_layer/contacts/Cargo.toml b/base_layer/contacts/Cargo.toml index c49f5ea31d..123656424b 100644 --- a/base_layer/contacts/Cargo.toml +++ b/base_layer/contacts/Cargo.toml @@ -3,22 +3,22 @@ name = "tari_contacts" authors = ["The Tari Development Community"] description = "Tari contacts library" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [dependencies] -tari_common = { path = "../../common", version = "1.8.0-pre.0" } -tari_common_sqlite = { path = "../../common_sqlite", version = "1.8.0-pre.0" } -tari_common_types = { path = "../../base_layer/common_types", version = "1.8.0-pre.0" } -tari_comms = { path = "../../comms/core", version = "1.8.0-pre.0" } -tari_comms_dht = { path = "../../comms/dht", version = "1.8.0-pre.0" } +tari_common = { path = "../../common", version = "1.9.0-pre.0" } +tari_common_sqlite = { path = "../../common_sqlite", version = "1.9.0-pre.0" } +tari_common_types = { path = "../../base_layer/common_types", version = "1.9.0-pre.0" } +tari_comms = { path = "../../comms/core", version = "1.9.0-pre.0" } +tari_comms_dht = { path = "../../comms/dht", version = "1.9.0-pre.0" } tari_crypto = { version = "0.21.0" } tari_max_size = { path = "../../infrastructure/max_size" } tari_p2p = { path = "../p2p", features = [ "auto-update", -], version = "1.8.0-pre.0" } -tari_service_framework = { path = "../service_framework", version = "1.8.0-pre.0" } -tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.8.0-pre.0" } +], version = "1.9.0-pre.0" } +tari_service_framework = { path = "../service_framework", version = "1.9.0-pre.0" } +tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.9.0-pre.0" } tari_utilities = { version = "0.8" } chrono = { version = "0.4.19", default-features = false, features = ["serde"] } @@ -48,7 +48,7 @@ tari_test_utils = { path = "../../infrastructure/test_utils" } tempfile = "3.1.0" [build-dependencies] -tari_common = { path = "../../common", version = "1.8.0-pre.0" } +tari_common = { path = "../../common", version = "1.9.0-pre.0" } [package.metadata.cargo-machete] ignored = [ diff --git a/base_layer/contacts/src/chat_client/Cargo.toml b/base_layer/contacts/src/chat_client/Cargo.toml index 9ade91177d..0026962a56 100644 --- a/base_layer/contacts/src/chat_client/Cargo.toml +++ b/base_layer/contacts/src/chat_client/Cargo.toml @@ -3,7 +3,7 @@ name = "tari_chat_client" authors = ["The Tari Development Community"] description = "Tari cucumber chat client" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" diff --git a/base_layer/core/Cargo.toml b/base_layer/core/Cargo.toml index ed76607804..ab77e26c36 100644 --- a/base_layer/core/Cargo.toml +++ b/base_layer/core/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/tari-project/tari" homepage = "https://tari.com" readme = "README.md" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [features] @@ -27,26 +27,26 @@ ledger = ["minotari_ledger_wallet_comms"] metrics = ["tari_metrics"] [dependencies] -minotari_ledger_wallet_comms = { path = "../../applications/minotari_ledger_wallet/comms", version = "1.8.0-pre.0", optional = true } -tari_common = { path = "../../common", version = "1.8.0-pre.0" } -tari_common_types = { path = "../../base_layer/common_types", version = "1.8.0-pre.0" } -tari_comms = { path = "../../comms/core", version = "1.8.0-pre.0" } -tari_comms_dht = { path = "../../comms/dht", version = "1.8.0-pre.0" } -tari_comms_rpc_macros = { path = "../../comms/rpc_macros", version = "1.8.0-pre.0" } +minotari_ledger_wallet_comms = { path = "../../applications/minotari_ledger_wallet/comms", version = "1.9.0-pre.0", optional = true } +tari_common = { path = "../../common", version = "1.9.0-pre.0" } +tari_common_types = { path = "../../base_layer/common_types", version = "1.9.0-pre.0" } +tari_comms = { path = "../../comms/core", version = "1.9.0-pre.0" } +tari_comms_dht = { path = "../../comms/dht", version = "1.9.0-pre.0" } +tari_comms_rpc_macros = { path = "../../comms/rpc_macros", version = "1.9.0-pre.0" } tari_crypto = { version = "0.21.0", features = ["borsh"] } tari_max_size = { path = "../../infrastructure/max_size" } -tari_metrics = { path = "../../infrastructure/metrics", optional = true, version = "1.8.0-pre.0" } -tari_mmr = { path = "../../base_layer/mmr", optional = true, version = "1.8.0-pre.0" } -tari_p2p = { path = "../../base_layer/p2p", version = "1.8.0-pre.0" } -tari_script = { path = "../../infrastructure/tari_script", version = "1.8.0-pre.0" } -tari_service_framework = { path = "../service_framework", version = "1.8.0-pre.0" } -tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.8.0-pre.0" } -tari_storage = { path = "../../infrastructure/storage", version = "1.8.0-pre.0" } -tari_test_utils = { path = "../../infrastructure/test_utils", version = "1.8.0-pre.0" } +tari_metrics = { path = "../../infrastructure/metrics", optional = true, version = "1.9.0-pre.0" } +tari_mmr = { path = "../../base_layer/mmr", optional = true, version = "1.9.0-pre.0" } +tari_p2p = { path = "../../base_layer/p2p", version = "1.9.0-pre.0" } +tari_script = { path = "../../infrastructure/tari_script", version = "1.9.0-pre.0" } +tari_service_framework = { path = "../service_framework", version = "1.9.0-pre.0" } +tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.9.0-pre.0" } +tari_storage = { path = "../../infrastructure/storage", version = "1.9.0-pre.0" } +tari_test_utils = { path = "../../infrastructure/test_utils", version = "1.9.0-pre.0" } tari_utilities = { version = "0.8", features = ["borsh"] } tari_key_manager = { path = "../key_manager", features = [ "key_manager_service", -], version = "1.8.0-pre.0" } +], version = "1.9.0-pre.0" } tari_common_sqlite = { path = "../../common_sqlite" } tari_hashing = { path = "../../hashing" } @@ -110,8 +110,8 @@ serial_test = "0.5" [build-dependencies] tari_common = { path = "../../common", features = [ "build", -], version = "1.8.0-pre.0" } -tari_features = { path = "../../common/tari_features", version = "1.8.0-pre.0" } +], version = "1.9.0-pre.0" } +tari_features = { path = "../../common/tari_features", version = "1.9.0-pre.0" } [[bench]] name = "mempool" diff --git a/base_layer/key_manager/Cargo.toml b/base_layer/key_manager/Cargo.toml index 99c6298579..b8bef7c8b3 100644 --- a/base_layer/key_manager/Cargo.toml +++ b/base_layer/key_manager/Cargo.toml @@ -4,7 +4,7 @@ authors = ["The Tari Development Community"] description = "Tari cryptocurrency wallet key management" repository = "https://github.com/tari-project/tari" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2021" [lib] @@ -13,9 +13,9 @@ crate-type = ["lib", "cdylib"] [dependencies] tari_crypto = { version = "0.21.0" } tari_utilities = { version = "0.8" } -tari_common_sqlite = { path = "../../common_sqlite", version = "1.8.0-pre.0" } -tari_common_types = { path = "../../base_layer/common_types", version = "1.8.0-pre.0" } -tari_service_framework = { path = "../service_framework", version = "1.8.0-pre.0" } +tari_common_sqlite = { path = "../../common_sqlite", version = "1.9.0-pre.0" } +tari_common_types = { path = "../../base_layer/common_types", version = "1.9.0-pre.0" } +tari_service_framework = { path = "../service_framework", version = "1.9.0-pre.0" } async-trait = { version = "0.1.50" } chrono = { version = "0.4.19", default-features = false, features = ["serde"] } diff --git a/base_layer/mmr/Cargo.toml b/base_layer/mmr/Cargo.toml index 6159052eab..27c32cb817 100644 --- a/base_layer/mmr/Cargo.toml +++ b/base_layer/mmr/Cargo.toml @@ -4,7 +4,7 @@ authors = ["The Tari Development Community"] description = "A Merkle Mountain Range implementation" repository = "https://github.com/tari-project/tari" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [features] diff --git a/base_layer/p2p/Cargo.toml b/base_layer/p2p/Cargo.toml index 8aee2ab94d..43eb20ffab 100644 --- a/base_layer/p2p/Cargo.toml +++ b/base_layer/p2p/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tari_p2p" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" authors = ["The Tari Development community"] description = "Tari base layer-specific peer-to-peer communication features" repository = "https://github.com/tari-project/tari" @@ -10,13 +10,13 @@ license = "BSD-3-Clause" edition = "2021" [dependencies] -tari_comms = { path = "../../comms/core", version = "1.8.0-pre.0" } -tari_comms_dht = { path = "../../comms/dht", version = "1.8.0-pre.0" } -tari_common = { path = "../../common", version = "1.8.0-pre.0" } +tari_comms = { path = "../../comms/core", version = "1.9.0-pre.0" } +tari_comms_dht = { path = "../../comms/dht", version = "1.9.0-pre.0" } +tari_common = { path = "../../common", version = "1.9.0-pre.0" } tari_crypto = { version = "0.21.0" } -tari_service_framework = { path = "../service_framework", version = "1.8.0-pre.0" } -tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.8.0-pre.0" } -tari_storage = { path = "../../infrastructure/storage", version = "1.8.0-pre.0" } +tari_service_framework = { path = "../service_framework", version = "1.9.0-pre.0" } +tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.9.0-pre.0" } +tari_storage = { path = "../../infrastructure/storage", version = "1.9.0-pre.0" } tari_utilities = { version = "0.8" } anyhow = "1.0.53" @@ -52,7 +52,7 @@ tempfile = "3.1.0" [build-dependencies] tari_common = { path = "../../common", features = [ "build", -], version = "1.8.0-pre.0" } +], version = "1.9.0-pre.0" } [features] test-mocks = [] diff --git a/base_layer/service_framework/Cargo.toml b/base_layer/service_framework/Cargo.toml index 21a8a95409..25a364c2d9 100644 --- a/base_layer/service_framework/Cargo.toml +++ b/base_layer/service_framework/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tari_service_framework" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" authors = ["The Tari Development Community"] description = "The Tari communication stack service framework" repository = "https://github.com/tari-project/tari" @@ -10,7 +10,7 @@ license = "BSD-3-Clause" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.8.0-pre.0" } +tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.9.0-pre.0" } anyhow = "1.0.53" async-trait = "0.1.50" diff --git a/base_layer/tari_mining_helper_ffi/Cargo.toml b/base_layer/tari_mining_helper_ffi/Cargo.toml index 7e71d970a9..cff9a734de 100644 --- a/base_layer/tari_mining_helper_ffi/Cargo.toml +++ b/base_layer/tari_mining_helper_ffi/Cargo.toml @@ -3,7 +3,7 @@ name = "minotari_mining_helper_ffi" authors = ["The Tari Development Community"] description = "Tari cryptocurrency miningcore C FFI bindings" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [dependencies] @@ -15,7 +15,7 @@ tari_core = { path = "../core", default-features = false, features = [ "base_node_proto", "base_node", ] } -tari_common_types = { path = "../../base_layer/common_types", version = "1.8.0-pre.0" } +tari_common_types = { path = "../../base_layer/common_types", version = "1.9.0-pre.0" } tari_utilities = { version = "0.8" } libc = "0.2.65" thiserror = "1.0.26" @@ -27,7 +27,7 @@ tari_core = { path = "../core", features = ["transactions", "base_node"] } rand = "0.8" [build-dependencies] -tari_features = { path = "../../common/tari_features", version = "1.8.0-pre.0" } +tari_features = { path = "../../common/tari_features", version = "1.9.0-pre.0" } cbindgen = "0.24.3" tari_common = { path = "../../common", features = [ "build", diff --git a/base_layer/wallet/Cargo.toml b/base_layer/wallet/Cargo.toml index ab6110a596..5545dd5c43 100644 --- a/base_layer/wallet/Cargo.toml +++ b/base_layer/wallet/Cargo.toml @@ -3,32 +3,32 @@ name = "minotari_wallet" authors = ["The Tari Development Community"] description = "Tari cryptocurrency wallet library" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [dependencies] -tari_common = { path = "../../common", version = "1.8.0-pre.0" } -tari_common_sqlite = { path = "../../common_sqlite", version = "1.8.0-pre.0" } -tari_common_types = { path = "../../base_layer/common_types", version = "1.8.0-pre.0" } -tari_comms = { path = "../../comms/core", version = "1.8.0-pre.0" } -tari_comms_dht = { path = "../../comms/dht", version = "1.8.0-pre.0" } -tari_contacts = { path = "../../base_layer/contacts", version = "1.8.0-pre.0" } +tari_common = { path = "../../common", version = "1.9.0-pre.0" } +tari_common_sqlite = { path = "../../common_sqlite", version = "1.9.0-pre.0" } +tari_common_types = { path = "../../base_layer/common_types", version = "1.9.0-pre.0" } +tari_comms = { path = "../../comms/core", version = "1.9.0-pre.0" } +tari_comms_dht = { path = "../../comms/dht", version = "1.9.0-pre.0" } +tari_contacts = { path = "../../base_layer/contacts", version = "1.9.0-pre.0" } tari_core = { path = "../../base_layer/core", default-features = false, features = [ "transactions", "mempool_proto", "base_node_proto", -], version = "1.8.0-pre.0" } +], version = "1.9.0-pre.0" } tari_crypto = { version = "0.21.0" } tari_max_size = { path = "../../infrastructure/max_size" } tari_key_manager = { path = "../key_manager", features = [ "key_manager_service", -], version = "1.8.0-pre.0" } +], version = "1.9.0-pre.0" } tari_p2p = { path = "../p2p", features = [ "auto-update", -], version = "1.8.0-pre.0" } -tari_script = { path = "../../infrastructure/tari_script", version = "1.8.0-pre.0" } -tari_service_framework = { path = "../service_framework", version = "1.8.0-pre.0" } -tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.8.0-pre.0" } +], version = "1.9.0-pre.0" } +tari_script = { path = "../../infrastructure/tari_script", version = "1.9.0-pre.0" } +tari_service_framework = { path = "../service_framework", version = "1.9.0-pre.0" } +tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.9.0-pre.0" } tari_utilities = { version = "0.8" } # Uncomment for tokio tracing via tokio-console (needs "tracing" features) @@ -74,7 +74,7 @@ zeroize = "1" tari_common = { path = "../../common", features = [ "build", "static-application-info", -], version = "1.8.0-pre.0" } +], version = "1.9.0-pre.0" } [dev-dependencies] tari_p2p = { path = "../p2p", features = ["test-mocks"] } diff --git a/base_layer/wallet_ffi/Cargo.toml b/base_layer/wallet_ffi/Cargo.toml index 3b76ac2892..501f4cbaa7 100644 --- a/base_layer/wallet_ffi/Cargo.toml +++ b/base_layer/wallet_ffi/Cargo.toml @@ -3,7 +3,7 @@ name = "minotari_wallet_ffi" authors = ["The Tari Development Community"] description = "Tari cryptocurrency wallet C FFI bindings" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [dependencies] @@ -67,7 +67,7 @@ tari_common = { path = "../../common", features = [ "build", "static-application-info", ] } -tari_features = { path = "../../common/tari_features", version = "1.8.0-pre.0" } +tari_features = { path = "../../common/tari_features", version = "1.9.0-pre.0" } [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = [ diff --git a/changelog-development.md b/changelog-development.md index 204b451d90..8714dfafe9 100644 --- a/changelog-development.md +++ b/changelog-development.md @@ -2,6 +2,24 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [1.9.0-pre.0](https://github.com/tari-project/tari/compare/v1.8.0-pre.0...v1.9.0-pre.0) (2024-11-14) + + +### ⚠ BREAKING CHANGES + +* add new header field (#6686) + +### Features + +* add new header field ([#6686](https://github.com/tari-project/tari/issues/6686)) ([69a5872](https://github.com/tari-project/tari/commit/69a5872e52d8332e0b46e50614b2105bed0d22c9)) +* update ledger instructions ([#6673](https://github.com/tari-project/tari/issues/6673)) ([06f7a68](https://github.com/tari-project/tari/commit/06f7a6830661ffdc88cd0b90cf4e139123786225)) +* verify active base node peer connections and disconnect if stale ([#6655](https://github.com/tari-project/tari/issues/6655)) ([e61b5e2](https://github.com/tari-project/tari/commit/e61b5e2d172f782e953f351a81723713b150c57d)) + + +### Bug Fixes + +* **comms:** ensure that inbound messaging terminates on disconnect ([#6653](https://github.com/tari-project/tari/issues/6653)) ([47b4877](https://github.com/tari-project/tari/commit/47b48770f84e05c3dce1926d0a8d21eee4ccfe21)) + ## [1.8.0-pre.0](https://github.com/tari-project/tari/compare/v1.7.0-pre.4...v1.8.0-pre.0) (2024-10-28) diff --git a/changelog-nextnet.md b/changelog-nextnet.md index 7080c61cd2..0265a5aca2 100644 --- a/changelog-nextnet.md +++ b/changelog-nextnet.md @@ -2,6 +2,25 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. # Changelog +## [1.9.0-rc.0](https://github.com/tari-project/tari/compare/v1.8.0-rc.0...v1.9.0-rc.0) (2024-11-14) + + +### ⚠ BREAKING CHANGES + +* add new header field (#6686) + +### Features + +* add new header field ([#6686](https://github.com/tari-project/tari/issues/6686)) ([69a5872](https://github.com/tari-project/tari/commit/69a5872e52d8332e0b46e50614b2105bed0d22c9)) +* update ledger instructions ([#6673](https://github.com/tari-project/tari/issues/6673)) ([06f7a68](https://github.com/tari-project/tari/commit/06f7a6830661ffdc88cd0b90cf4e139123786225)) +* verify active base node peer connections and disconnect if stale ([#6655](https://github.com/tari-project/tari/issues/6655)) ([e61b5e2](https://github.com/tari-project/tari/commit/e61b5e2d172f782e953f351a81723713b150c57d)) + + +### Bug Fixes + +* **comms:** ensure that inbound messaging terminates on disconnect ([#6653](https://github.com/tari-project/tari/issues/6653)) ([47b4877](https://github.com/tari-project/tari/commit/47b48770f84e05c3dce1926d0a8d21eee4ccfe21)) + + ## [1.8.0-rc.0](https://github.com/tari-project/tari/compare/v1.7.0-rc.4...v1.8.0-rc.0) (2024-10-28) diff --git a/common/Cargo.toml b/common/Cargo.toml index b4ea1587d3..837ac89b9f 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/tari-project/tari" homepage = "https://tari.com" readme = "README.md" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [features] @@ -14,7 +14,7 @@ build = ["toml", "prost-build"] static-application-info = ["git2"] [dependencies] -tari_features = { path = "./tari_features", version = "1.8.0-pre.0" } +tari_features = { path = "./tari_features", version = "1.9.0-pre.0" } anyhow = "1.0.53" config = { version = "0.14.0", default-features = false, features = ["toml"] } @@ -43,7 +43,7 @@ tari_test_utils = { path = "../infrastructure/test_utils" } toml = "0.5.8" [build-dependencies] -tari_features = { path = "./tari_features", version = "1.8.0-pre.0" } +tari_features = { path = "./tari_features", version = "1.9.0-pre.0" } [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = [ diff --git a/common/tari_features/Cargo.toml b/common/tari_features/Cargo.toml index 6f5a9067aa..85348bff94 100644 --- a/common/tari_features/Cargo.toml +++ b/common/tari_features/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/tari-project/tari" homepage = "https://tari.com" readme = "README.md" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common_sqlite/Cargo.toml b/common_sqlite/Cargo.toml index 07d56792fe..674e35b7f5 100644 --- a/common_sqlite/Cargo.toml +++ b/common_sqlite/Cargo.toml @@ -3,7 +3,7 @@ name = "tari_common_sqlite" authors = ["The Tari Development Community"] description = "Tari cryptocurrency wallet library" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/comms/core/Cargo.toml b/comms/core/Cargo.toml index 706f9ff5d1..90ea7ff195 100644 --- a/comms/core/Cargo.toml +++ b/comms/core/Cargo.toml @@ -6,14 +6,14 @@ repository = "https://github.com/tari-project/tari" homepage = "https://tari.com" readme = "README.md" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2021" [dependencies] tari_crypto = { version = "0.21.0" } -tari_metrics = { path = "../../infrastructure/metrics", optional = true, version = "1.8.0-pre.0" } -tari_storage = { path = "../../infrastructure/storage", version = "1.8.0-pre.0" } -tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.8.0-pre.0" } +tari_metrics = { path = "../../infrastructure/metrics", optional = true, version = "1.9.0-pre.0" } +tari_storage = { path = "../../infrastructure/storage", version = "1.9.0-pre.0" } +tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.9.0-pre.0" } tari_utilities = { version = "0.8" } anyhow = "1.0.53" @@ -72,7 +72,7 @@ tempfile = "3.1.0" [build-dependencies] tari_common = { path = "../../common", features = [ "build", -], version = "1.8.0-pre.0" } +], version = "1.9.0-pre.0" } [features] c_integration = [] diff --git a/comms/dht/Cargo.toml b/comms/dht/Cargo.toml index 39afe03046..00652fe569 100644 --- a/comms/dht/Cargo.toml +++ b/comms/dht/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tari_comms_dht" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" authors = ["The Tari Development Community"] description = "Tari comms DHT module" repository = "https://github.com/tari-project/tari" @@ -10,14 +10,14 @@ license = "BSD-3-Clause" edition = "2021" [dependencies] -tari_comms = { path = "../core", features = ["rpc"], version = "1.8.0-pre.0" } -tari_common = { path = "../../common", version = "1.8.0-pre.0" } -tari_comms_rpc_macros = { path = "../rpc_macros", version = "1.8.0-pre.0" } +tari_comms = { path = "../core", features = ["rpc"], version = "1.9.0-pre.0" } +tari_common = { path = "../../common", version = "1.9.0-pre.0" } +tari_comms_rpc_macros = { path = "../rpc_macros", version = "1.9.0-pre.0" } tari_crypto = { version = "0.21.0" } tari_utilities = { version = "0.8" } -tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.8.0-pre.0" } -tari_storage = { path = "../../infrastructure/storage", version = "1.8.0-pre.0" } -tari_common_sqlite = { path = "../../common_sqlite", version = "1.8.0-pre.0" } +tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.9.0-pre.0" } +tari_storage = { path = "../../infrastructure/storage", version = "1.9.0-pre.0" } +tari_common_sqlite = { path = "../../common_sqlite", version = "1.9.0-pre.0" } anyhow = "1.0.53" bitflags = { version = "2.4", features = ["serde"] } @@ -67,7 +67,7 @@ clap = "3.2" [build-dependencies] -tari_common = { path = "../../common", version = "1.8.0-pre.0" } +tari_common = { path = "../../common", version = "1.9.0-pre.0" } [features] test-mocks = [] diff --git a/comms/rpc_macros/Cargo.toml b/comms/rpc_macros/Cargo.toml index 4f76705cef..01ef8c59f5 100644 --- a/comms/rpc_macros/Cargo.toml +++ b/comms/rpc_macros/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/tari-project/tari" homepage = "https://tari.com" readme = "README.md" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [lib] diff --git a/hashing/Cargo.toml b/hashing/Cargo.toml index bf0a983902..bc9d7a870d 100644 --- a/hashing/Cargo.toml +++ b/hashing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tari_hashing" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2021" description = "Tari hash domains" authors = ["The Tari Development Community"] diff --git a/infrastructure/derive/Cargo.toml b/infrastructure/derive/Cargo.toml index 5b81e08ca6..750558581c 100644 --- a/infrastructure/derive/Cargo.toml +++ b/infrastructure/derive/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/tari-project/tari" homepage = "https://tari.com" readme = "README.md" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [lib] diff --git a/infrastructure/libtor/Cargo.toml b/infrastructure/libtor/Cargo.toml index a8e0c63537..e359e3ce02 100644 --- a/infrastructure/libtor/Cargo.toml +++ b/infrastructure/libtor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tari_libtor" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2021" license = "BSD-3-Clause" diff --git a/infrastructure/max_size/Cargo.toml b/infrastructure/max_size/Cargo.toml index d93e32e569..f7283bbb4a 100644 --- a/infrastructure/max_size/Cargo.toml +++ b/infrastructure/max_size/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tari_max_size" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2021" description = "Tari max size library" authors = ["The Tari Development Community"] diff --git a/infrastructure/metrics/Cargo.toml b/infrastructure/metrics/Cargo.toml index c863312103..224cdd43cb 100644 --- a/infrastructure/metrics/Cargo.toml +++ b/infrastructure/metrics/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "tari_metrics" description = "Tari metrics" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2021" authors = ["The Tari Development Community"] repository = "https://github.com/tari-project/tari" diff --git a/infrastructure/shutdown/Cargo.toml b/infrastructure/shutdown/Cargo.toml index eafee3ffe2..a276842240 100644 --- a/infrastructure/shutdown/Cargo.toml +++ b/infrastructure/shutdown/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/tari-project/tari" homepage = "https://tari.com" readme = "README.md" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/infrastructure/storage/Cargo.toml b/infrastructure/storage/Cargo.toml index 4d827f9dc3..ebe0d50a62 100644 --- a/infrastructure/storage/Cargo.toml +++ b/infrastructure/storage/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/tari-project/tari" homepage = "https://tari.com" readme = "README.md" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [dependencies] diff --git a/infrastructure/tari_script/Cargo.toml b/infrastructure/tari_script/Cargo.toml index ccbf4c6d43..a1e1830397 100644 --- a/infrastructure/tari_script/Cargo.toml +++ b/infrastructure/tari_script/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tari_script" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2021" description = "Tari script library" authors = ["The Tari Development Community"] diff --git a/infrastructure/test_utils/Cargo.toml b/infrastructure/test_utils/Cargo.toml index e4d572a177..3af8c414f9 100644 --- a/infrastructure/test_utils/Cargo.toml +++ b/infrastructure/test_utils/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "tari_test_utils" description = "Utility functions used in Tari test functions" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" authors = ["The Tari Development Community"] edition = "2018" license = "BSD-3-Clause" @@ -9,8 +9,8 @@ license = "BSD-3-Clause" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -tari_shutdown = { path = "../shutdown", version = "1.8.0-pre.0" } -tari_comms = { path = "../../comms/core", version = "1.8.0-pre.0" } +tari_shutdown = { path = "../shutdown", version = "1.9.0-pre.0" } +tari_comms = { path = "../../comms/core", version = "1.9.0-pre.0" } futures = { version = "^0.3.1" } rand = "0.8" diff --git a/package-lock.json b/package-lock.json index 3223905177..2b54c97572 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "tari", - "version": "1.8.0-pre.0", + "version": "1.9.0-pre.0", "lockfileVersion": 2, "requires": true, "packages": {} From d58c67030c3cff20eea6a17883c2a7908dc75ea6 Mon Sep 17 00:00:00 2001 From: SW van Heerden Date: Tue, 19 Nov 2024 12:01:13 +0200 Subject: [PATCH 06/19] chore: add helper functions for generating output proofs (#6694) Description --- Adds helper function to calculate the hashes for the merkle roots of the header. --- base_layer/core/src/blocks/genesis_block.rs | 9 ++++++ .../core/src/transactions/aggregated_body.rs | 31 ++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/base_layer/core/src/blocks/genesis_block.rs b/base_layer/core/src/blocks/genesis_block.rs index 8818206ca2..a75767e192 100644 --- a/base_layer/core/src/blocks/genesis_block.rs +++ b/base_layer/core/src/blocks/genesis_block.rs @@ -751,6 +751,15 @@ mod test { block.header().block_output_mr.to_vec().to_hex(), ); } else { + let coinbases = block.block().body.get_coinbase_outputs().into_iter().cloned().collect(); + let normal_output_mr = block.block().body.calculate_header_normal_output_mr().unwrap(); + assert_eq!( + AggregateBody::calculate_header_block_output_mr(normal_output_mr, &coinbases) + .unwrap() + .to_vec() + .to_hex(), + block.header().block_output_mr.to_vec().to_hex(), + ); assert_eq!( block_output_mr_hash_from_pruned_mmr(&block_output_mmr) .unwrap() diff --git a/base_layer/core/src/transactions/aggregated_body.rs b/base_layer/core/src/transactions/aggregated_body.rs index ecdafcde2c..c6c31498b0 100644 --- a/base_layer/core/src/transactions/aggregated_body.rs +++ b/base_layer/core/src/transactions/aggregated_body.rs @@ -21,14 +21,17 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use std::{ cmp::max, + convert::TryFrom, fmt::{Display, Error, Formatter}, }; use borsh::{BorshDeserialize, BorshSerialize}; use log::*; use serde::{Deserialize, Serialize}; -use tari_common_types::types::{ComAndPubSignature, Commitment, PrivateKey}; +use tari_common_types::types::{ComAndPubSignature, Commitment, FixedHash, PrivateKey}; use tari_crypto::commitment::HomomorphicCommitmentFactory; +#[cfg(feature = "base_node")] +use tari_mmr::pruned_hashset::PrunedHashSet; use tari_utilities::hex::Hex; use crate::transactions::{ @@ -45,6 +48,8 @@ use crate::transactions::{ }, weight::TransactionWeight, }; +#[cfg(feature = "base_node")] +use crate::{block_output_mr_hash_from_pruned_mmr, MrHashError, PrunedOutputMmr}; pub const LOG_TARGET: &str = "c::tx::aggregated_body"; @@ -446,6 +451,30 @@ impl AggregateBody { .iter() .any(|k| k.features.output_type == OutputType::Coinbase) } + + #[cfg(feature = "base_node")] + pub fn calculate_header_block_output_mr( + normal_output_mr: FixedHash, + coinbases: &Vec, + ) -> Result { + let mut block_output_mmr = PrunedOutputMmr::new(PrunedHashSet::default()); + for o in coinbases { + block_output_mmr.push(o.hash().to_vec())?; + } + block_output_mmr.push(normal_output_mr.to_vec())?; + block_output_mr_hash_from_pruned_mmr(&block_output_mmr) + } + + #[cfg(feature = "base_node")] + pub fn calculate_header_normal_output_mr(&self) -> Result { + let mut normal_output_mmr = PrunedOutputMmr::new(PrunedHashSet::default()); + for o in self.outputs() { + if !o.features.is_coinbase() { + normal_output_mmr.push(o.hash().to_vec())?; + } + } + Ok(FixedHash::try_from(normal_output_mmr.get_merkle_root()?)?) + } } impl PartialEq for AggregateBody { From 0610bcceb5debb91484191f6178e2591db123263 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Ko=C5=BCuszek?= Date: Tue, 19 Nov 2024 12:00:13 +0100 Subject: [PATCH 07/19] feat: validate blockchain fetch from DNS server with local state (#6658) Description --- Add new service which will periodically get checkpoints from a DNS server and validate with it's own state. If we fail this check we will include this information in `get_new_block_template` request so the sender is aware that this node is out of sync. Motivation and Context --- This will allow miners including one from Tari Universe to avoid mining on the orphan chain. This implementation is modeled after the [Monero Pulse](https://docs.getmonero.org/infrastructure/monero-pulse/#moneropulse) How Has This Been Tested? --- Run app on the nextnet and look for logs with `tari_pulse` in the `base_layer.log` file like this: `tail -f base_layer.log | grep tari_pulse ` Make `get_new_block_template` and verify if new fields are present. Create orphan chain (eg. by turning off tor and banning all TCP peers) and check (with above methods) if nodes detects orphan chain. What process can a PR reviewer use to test or verify this change? --- Same as above Breaking Changes --- - [x] None - [ ] Requires data directory on base node to be deleted - [ ] Requires hard fork - [ ] Other - Please specify --------- Co-authored-by: SW van Heerden --- .license.ignore | 2 + Cargo.lock | 3 + .../minotari_app_grpc/proto/base_node.proto | 1 + applications/minotari_node/src/bootstrap.rs | 11 +- applications/minotari_node/src/builder.rs | 11 +- applications/minotari_node/src/config.rs | 3 + .../src/grpc/base_node_grpc_server.rs | 5 + base_layer/core/Cargo.toml | 2 + base_layer/core/src/base_node/mod.rs | 3 + .../base_node/tari_pulse_service/20326.rsa | 1 + .../base_node/tari_pulse_service/38696.rsa | 1 + .../src/base_node/tari_pulse_service/mod.rs | 245 ++++++++++++++++++ common/config/presets/c_base_node_c.toml | 3 + common/src/exit_codes.rs | 2 + 14 files changed, 288 insertions(+), 5 deletions(-) create mode 100644 base_layer/core/src/base_node/tari_pulse_service/20326.rsa create mode 100644 base_layer/core/src/base_node/tari_pulse_service/38696.rsa create mode 100644 base_layer/core/src/base_node/tari_pulse_service/mod.rs diff --git a/.license.ignore b/.license.ignore index 9af3bb095f..5df15eb5ef 100644 --- a/.license.ignore +++ b/.license.ignore @@ -2,6 +2,8 @@ ./applications/minotari_node/assets/tari_logo.rs ./applications/minotari_node/osx-pkg/entitlements.xml ./base_layer/contacts/src/schema.rs +./base_layer/core/src/base_node/tari_pulse_service/20326.rsa +./base_layer/core/src/base_node/tari_pulse_service/38696.rsa ./base_layer/key_manager/src/schema.rs ./base_layer/wallet/src/schema.rs ./docs/src/theme/book.js diff --git a/Cargo.lock b/Cargo.lock index 9e58b5e9a6..5779a4aac1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2573,6 +2573,7 @@ dependencies = [ "idna 0.5.0", "ipnet", "once_cell", + "openssl", "rand", "ring", "rustls", @@ -6629,6 +6630,7 @@ dependencies = [ name = "tari_core" version = "1.9.0-pre.0" dependencies = [ + "anyhow", "async-trait", "bincode", "bitflags 2.4.1", @@ -6647,6 +6649,7 @@ dependencies = [ "fs2", "futures 0.3.29", "hex", + "hickory-client", "integer-encoding", "libsqlite3-sys", "lmdb-zero", diff --git a/applications/minotari_app_grpc/proto/base_node.proto b/applications/minotari_app_grpc/proto/base_node.proto index 3e75dad936..9bceb0fd0c 100644 --- a/applications/minotari_app_grpc/proto/base_node.proto +++ b/applications/minotari_app_grpc/proto/base_node.proto @@ -160,6 +160,7 @@ message TipInfoResponse { MetaData metadata = 1; bool initial_sync_achieved = 2; BaseNodeState base_node_state = 3; + bool failed_checkpoints = 4; } enum BaseNodeState{ diff --git a/applications/minotari_node/src/bootstrap.rs b/applications/minotari_node/src/bootstrap.rs index 6620e7bd07..7c680a11f0 100644 --- a/applications/minotari_node/src/bootstrap.rs +++ b/applications/minotari_node/src/bootstrap.rs @@ -38,18 +38,18 @@ use tari_comms::{ }; use tari_comms_dht::Dht; use tari_core::{ - base_node, base_node::{ + self, chain_metadata_service::ChainMetadataServiceInitializer, service::BaseNodeServiceInitializer, state_machine_service::initializer::BaseNodeStateMachineInitializer, + tari_pulse_service::TariPulseServiceInitializer, LocalNodeCommsInterface, StateMachineHandle, }, chain_storage::{async_db::AsyncBlockchainDb, BlockchainBackend, BlockchainDatabase}, consensus::ConsensusManager, - mempool, - mempool::{service::MempoolHandle, Mempool, MempoolServiceInitializer, MempoolSyncInitializer}, + mempool::{self, service::MempoolHandle, Mempool, MempoolServiceInitializer, MempoolSyncInitializer}, proof_of_work::randomx_factory::RandomXFactory, transactions::CryptoFactories, }; @@ -170,6 +170,10 @@ where B: BlockchainBackend + 'static self.randomx_factory, self.app_config.base_node.bypass_range_proof_verification, )) + .add_initializer(TariPulseServiceInitializer::new( + base_node_config.tari_pulse_interval, + base_node_config.network, + )) .build() .await?; @@ -221,7 +225,6 @@ where B: BlockchainBackend + 'static }; handles.register(comms); - Ok(handles) } diff --git a/applications/minotari_node/src/builder.rs b/applications/minotari_node/src/builder.rs index 171372b04d..6b2792e2e7 100644 --- a/applications/minotari_node/src/builder.rs +++ b/applications/minotari_node/src/builder.rs @@ -30,7 +30,12 @@ use tari_common::{ use tari_comms::{peer_manager::NodeIdentity, protocol::rpc::RpcServerHandle, CommsNode}; use tari_comms_dht::Dht; use tari_core::{ - base_node::{state_machine_service::states::StatusInfo, LocalNodeCommsInterface, StateMachineHandle}, + base_node::{ + state_machine_service::states::StatusInfo, + tari_pulse_service::TariPulseHandle, + LocalNodeCommsInterface, + StateMachineHandle, + }, chain_storage::{create_lmdb_database, BlockchainDatabase, ChainStorageError, LMDBDatabase, Validators}, consensus::ConsensusManager, mempool::{service::LocalMempoolService, Mempool}, @@ -121,6 +126,10 @@ impl BaseNodeContext { self.base_node_handles.expect_handle() } + pub fn tari_pulse(&self) -> TariPulseHandle { + self.base_node_handles.expect_handle() + } + /// Returns a handle to the comms RPC server pub fn rpc_server(&self) -> RpcServerHandle { self.base_node_handles.expect_handle() diff --git a/applications/minotari_node/src/config.rs b/applications/minotari_node/src/config.rs index 01de596230..f6b704801b 100644 --- a/applications/minotari_node/src/config.rs +++ b/applications/minotari_node/src/config.rs @@ -142,6 +142,8 @@ pub struct BaseNodeConfig { pub state_machine: BaseNodeStateMachineConfig, /// Obscure GRPC error responses pub report_grpc_error: bool, + // Interval to check if the base node is still in sync with the network + pub tari_pulse_interval: Duration, } impl Default for BaseNodeConfig { @@ -180,6 +182,7 @@ impl Default for BaseNodeConfig { metadata_auto_ping_interval: Duration::from_secs(30), state_machine: Default::default(), report_grpc_error: false, + tari_pulse_interval: Duration::from_secs(120), } } } diff --git a/applications/minotari_node/src/grpc/base_node_grpc_server.rs b/applications/minotari_node/src/grpc/base_node_grpc_server.rs index ce991bad8e..1b5f2c548d 100644 --- a/applications/minotari_node/src/grpc/base_node_grpc_server.rs +++ b/applications/minotari_node/src/grpc/base_node_grpc_server.rs @@ -45,6 +45,7 @@ use tari_core::{ base_node::{ comms_interface::CommsInterfaceError, state_machine_service::states::StateInfo, + tari_pulse_service::TariPulseHandle, LocalNodeCommsInterface, StateMachineHandle, }, @@ -114,6 +115,7 @@ pub struct BaseNodeGrpcServer { comms: CommsNode, liveness: LivenessHandle, report_grpc_error: bool, + tari_pulse: TariPulseHandle, config: BaseNodeConfig, } @@ -129,6 +131,7 @@ impl BaseNodeGrpcServer { comms: ctx.base_node_comms().clone(), liveness: ctx.liveness(), report_grpc_error: ctx.get_report_grpc_error(), + tari_pulse: ctx.tari_pulse(), config, } } @@ -1637,6 +1640,7 @@ impl tari_rpc::base_node_server::BaseNode for BaseNodeGrpcServer { trace!(target: LOG_TARGET, "Incoming GRPC request for BN tip data"); let mut handler = self.node_service.clone(); + let failed_checkpoints = *self.tari_pulse.get_failed_checkpoints_notifier(); let meta = handler .get_metadata() @@ -1650,6 +1654,7 @@ impl tari_rpc::base_node_server::BaseNode for BaseNodeGrpcServer { metadata: Some(meta.into()), initial_sync_achieved: status_watch.borrow().bootstrapped, base_node_state: state.into(), + failed_checkpoints, }; trace!(target: LOG_TARGET, "Sending MetaData response to client"); diff --git a/base_layer/core/Cargo.toml b/base_layer/core/Cargo.toml index ab77e26c36..24e1393311 100644 --- a/base_layer/core/Cargo.toml +++ b/base_layer/core/Cargo.toml @@ -93,6 +93,8 @@ tiny-keccak = { package = "tari-tiny-keccak", version = "2.0.2", features = [ "keccak", ] } dirs-next = "1.0.2" +hickory-client = { version = "0.25.0-alpha.2", features = ["dns-over-rustls", "dnssec-openssl"] } +anyhow = "1.0.53" [dev-dependencies] criterion = { version = "0.4.0" } diff --git a/base_layer/core/src/base_node/mod.rs b/base_layer/core/src/base_node/mod.rs index c7a37b6524..776fc59925 100644 --- a/base_layer/core/src/base_node/mod.rs +++ b/base_layer/core/src/base_node/mod.rs @@ -65,3 +65,6 @@ pub mod proto; #[cfg(any(feature = "base_node", feature = "base_node_proto"))] pub mod rpc; + +#[cfg(feature = "base_node")] +pub mod tari_pulse_service; diff --git a/base_layer/core/src/base_node/tari_pulse_service/20326.rsa b/base_layer/core/src/base_node/tari_pulse_service/20326.rsa new file mode 100644 index 0000000000..acd48e8bd6 --- /dev/null +++ b/base_layer/core/src/base_node/tari_pulse_service/20326.rsa @@ -0,0 +1 @@ +AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3+/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kvArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+eoZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfdRUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwNR1AkUTV74bU= \ No newline at end of file diff --git a/base_layer/core/src/base_node/tari_pulse_service/38696.rsa b/base_layer/core/src/base_node/tari_pulse_service/38696.rsa new file mode 100644 index 0000000000..7948d28a47 --- /dev/null +++ b/base_layer/core/src/base_node/tari_pulse_service/38696.rsa @@ -0,0 +1 @@ +AwEAAa96jeuknZlaeSrvyAJj6ZHv28hhOKkx3rLGXVaC6rXTsDc449/cidltpkyGwCJNnOAlFNKF2jBosZBU5eeHspaQWOmOElZsjICMQMC3aeHbGiShvZsx4wMYSjH8e7Vrhbu6irwCzVBApESjbUdpWWmEnhathWu1jo+siFUiRAAxm9qyJNg/wOZqqzL/dL/q8PkcRU5oUKEpUge71M3ej2/7CPqpdVwuMoTvoB+ZOT4YeGyxMvHmbrxlFzGOHOijtzN+u1TQNatX2XBuzZNQ1K+s2CXkPIZo7s6JgZyvaBevYtxPvYLw4z9mR7K2vaF18UYH9Z9GNUUeayffKC73PYc= \ No newline at end of file diff --git a/base_layer/core/src/base_node/tari_pulse_service/mod.rs b/base_layer/core/src/base_node/tari_pulse_service/mod.rs new file mode 100644 index 0000000000..20de1f4339 --- /dev/null +++ b/base_layer/core/src/base_node/tari_pulse_service/mod.rs @@ -0,0 +1,245 @@ +// Copyright 2024. The Tari Project +// +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +// following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +// disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +// following disclaimer in the documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +// products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use std::{str::FromStr, time::Duration}; + +use futures::future; +use hickory_client::{ + client::{AsyncDnssecClient, ClientHandle}, + proto::{ + iocompat::AsyncIoTokioAsStd, + rr::dnssec::{public_key::Rsa, SigSigner, TrustAnchor}, + xfer::DnsMultiplexer, + }, + rr::{DNSClass, Name, RData, Record, RecordType}, + tcp::TcpClientStream, +}; +use log::{error, info}; +use serde::{Deserialize, Serialize}; +use tari_p2p::Network; +use tari_service_framework::{async_trait, ServiceInitializationError, ServiceInitializer, ServiceInitializerContext}; +use tari_shutdown::ShutdownSignal; +use tari_utilities::hex::Hex; +use tokio::{net::TcpStream as TokioTcpStream, sync::watch, time}; + +use super::LocalNodeCommsInterface; +use crate::base_node::comms_interface::CommsInterfaceError; + +const LOG_TARGET: &str = "c::bn::tari_pulse"; +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct TariPulseConfig { + pub check_interval: Duration, + pub network: Network, +} + +impl Default for TariPulseConfig { + fn default() -> Self { + Self { + check_interval: Duration::from_secs(120), + network: Network::default(), + } + } +} + +fn get_network_dns_name(network: Network) -> Name { + match network { + Network::NextNet => Name::from_str("checkpoints-nextnet.tari.com").expect("infallible"), + Network::MainNet => Name::from_str("checkpoints-mainnet.tari.com").expect("infallible"), + Network::Esmeralda => Name::from_str("checkpoints-esmeralda.tari.com").expect("infallible"), + Network::StageNet => Name::from_str("checkpoints-stagenet.tari.com").expect("infallible"), + Network::Igor => Name::from_str("checkpoints-igor.tari.com").expect("infallible"), + Network::LocalNet => Name::from_str("checkpoints-localnet.tari.com").expect("infallible"), + } +} + +pub struct TariPulseService { + dns_name: Name, + config: TariPulseConfig, +} + +impl TariPulseService { + pub async fn new(config: TariPulseConfig) -> Result { + let dns_name: Name = get_network_dns_name(config.clone().network); + info!(target: LOG_TARGET, "Tari Pulse Service initialized with DNS name: {}", dns_name); + Ok(Self { dns_name, config }) + } + + pub fn default_trust_anchor() -> TrustAnchor { + const ROOT_ANCHOR_ORIG: &[u8] = include_bytes!("20326.rsa"); + const ROOT_ANCHOR_CURRENT: &[u8] = include_bytes!("38696.rsa"); + + let mut anchor = TrustAnchor::new(); + anchor.insert_trust_anchor(&Rsa::from_public_bytes(ROOT_ANCHOR_ORIG).expect("Invalid ROOT_ANCHOR_ORIG")); + anchor.insert_trust_anchor(&Rsa::from_public_bytes(ROOT_ANCHOR_CURRENT).expect("Invalid ROOT_ANCHOR_CURRENT")); + anchor + } + + async fn get_dns_client(&self) -> Result { + let timeout: Duration = Duration::from_secs(5); + let trust_anchor = Self::default_trust_anchor(); + + let (stream, handle) = TcpClientStream::>::new(([1, 1, 1, 1], 53).into()); + let dns_muxer = DnsMultiplexer::<_, SigSigner>::with_timeout(stream, handle, timeout, None); + let (client, bg) = AsyncDnssecClient::builder(dns_muxer) + .trust_anchor(trust_anchor) + .build() + .await?; + + tokio::spawn(bg); + + Ok(client) + } + + pub async fn run( + &mut self, + mut base_node_service: LocalNodeCommsInterface, + notify_passed_checkpoints: watch::Sender, + ) { + let mut interval = time::interval(self.config.check_interval); + let mut interval_failed = time::interval(Duration::from_millis(100)); + loop { + let passed_checkpoints = match self.passed_checkpoints(&mut base_node_service).await { + Ok(passed) => passed, + Err(err) => { + error!(target: LOG_TARGET, "Error checking if node passed checkpoints: {:?}", err); + interval_failed.tick().await; + continue; + }, + }; + + notify_passed_checkpoints + .send(!passed_checkpoints) + .expect("Channel should be open"); + interval.tick().await; + } + } + + async fn passed_checkpoints( + &mut self, + base_node_service: &mut LocalNodeCommsInterface, + ) -> Result { + let dns_checkpoints = self.fetch_checkpoints().await?; + + let max_height_block = dns_checkpoints + .iter() + .max_by(|a, b| a.0.cmp(&b.0)) + .ok_or(CommsInterfaceError::InternalError("No checkpoints found".to_string()))?; + let local_checkpoints = self.get_node_block(base_node_service, max_height_block.0).await?; + Ok(local_checkpoints.1 == max_height_block.1) + } + + async fn get_node_block( + &mut self, + base_node_service: &mut LocalNodeCommsInterface, + block_height: u64, + ) -> Result<(u64, String), anyhow::Error> { + let historical_block = base_node_service + .get_header(block_height) + .await + .and_then(|header| match header { + Some(header) => Ok((header.height(), header.hash().to_hex())), + None => { + error!(target: LOG_TARGET, "Header not found for height: {}", block_height); + Err(CommsInterfaceError::InternalError("Header not found".to_string())) + }, + })?; + + Ok(historical_block) + } + + async fn fetch_checkpoints(&mut self) -> Result, anyhow::Error> { + let mut client = self.get_dns_client().await?; + let query = client.query(self.dns_name.clone(), DNSClass::IN, RecordType::TXT); + let response = query.await?; + let answers: &[Record] = response.answers(); + let checkpoints: Vec<(u64, String)> = answers + .iter() + .filter_map(|record| { + if let RData::TXT(txt) = record.data() { + let ascii_txt = txt.txt_data().iter().fold(String::new(), |mut acc, bytes| { + acc.push_str(&String::from_utf8_lossy(bytes)); + acc + }); + let (height, hash) = ascii_txt.split_once(':')?; + return Some((height.parse().ok()?, hash.to_string())); + } + None + }) + .collect(); + + Ok(checkpoints) + } +} + +#[derive(Clone)] +pub struct TariPulseHandle { + pub shutdown_signal: ShutdownSignal, + pub failed_checkpoints_notifier: watch::Receiver, +} + +impl TariPulseHandle { + pub fn get_failed_checkpoints_notifier(&self) -> watch::Ref<'_, bool> { + self.failed_checkpoints_notifier.borrow() + } +} + +pub struct TariPulseServiceInitializer { + interval: Duration, + network: Network, +} + +impl TariPulseServiceInitializer { + pub fn new(interval: Duration, network: Network) -> Self { + Self { interval, network } + } +} + +#[async_trait] +impl ServiceInitializer for TariPulseServiceInitializer { + async fn initialize(&mut self, context: ServiceInitializerContext) -> Result<(), ServiceInitializationError> { + info!(target: LOG_TARGET, "Initializing Tari Pulse Service"); + let shutdown_signal = context.get_shutdown_signal(); + let (sender, receiver) = watch::channel(false); + context.register_handle(TariPulseHandle { + shutdown_signal: shutdown_signal.clone(), + failed_checkpoints_notifier: receiver, + }); + let config = TariPulseConfig { + check_interval: self.interval, + network: self.network, + }; + + context.spawn_when_ready(move |handles| async move { + let base_node_service = handles.expect_handle::(); + let mut tari_pulse_service = TariPulseService::new(config) + .await + .expect("Should be able to get the service"); + let tari_pulse_service = tari_pulse_service.run(base_node_service, sender); + futures::pin_mut!(tari_pulse_service); + future::select(tari_pulse_service, shutdown_signal).await; + info!(target: LOG_TARGET, "Tari Pulse Service shutdown"); + }); + info!(target: LOG_TARGET, "Tari Pulse Service initialized"); + Ok(()) + } +} diff --git a/common/config/presets/c_base_node_c.toml b/common/config/presets/c_base_node_c.toml index 8aeeec7c23..fe7c1e5ea3 100644 --- a/common/config/presets/c_base_node_c.toml +++ b/common/config/presets/c_base_node_c.toml @@ -45,6 +45,9 @@ # Obscure GRPC error responses (default = false) #report_grpc_error = false +# Interval between each request to the dns server for hte checkpoints to compare it with the local blockchain (default = 120 s) +# tari_pulse_interval = 120 + [base_node.lmdb] #init_size_bytes = 16_777_216 # 16 *1024 * 1024 #grow_size_bytes = 16_777_216 # 16 *1024 * 1024 diff --git a/common/src/exit_codes.rs b/common/src/exit_codes.rs index 412afe54e2..c11b64deb7 100644 --- a/common/src/exit_codes.rs +++ b/common/src/exit_codes.rs @@ -130,6 +130,8 @@ pub enum ExitCode { WalletPaymentAddress = 123, #[error("Unable to configure TLS")] TlsConfigurationError = 124, + #[error("Unable to setup tari pulse")] + TariPulseError = 125, } impl From for ExitError { From d22ef6582e9a671577efc419e5d121c384972aad Mon Sep 17 00:00:00 2001 From: Hansie Odendaal <39146854+hansieodendaal@users.noreply.github.com> Date: Fri, 22 Nov 2024 09:21:57 +0200 Subject: [PATCH 08/19] feat: fix base node shutdown (#6697) Description --- Fixed the base node shutdown on Ubuntu (and hopefully on MacOS) whereas pressing Ctrl-C multiple times rendered the command line interface in an undefined state. This was not issue on Windows. **Note:** The change to 'base_layer\core\src\base_node\tari_pulse_service\mod.rs' is an interim change to enable testing (getting rid of the repeated command-line spam) but not required for the base node to shut down. More changes in #6696. Motivation and Context --- The base node did not shut down properly on Ubuntu and MacOs. How Has This Been Tested? --- System-level testing on Windows and Ubuntu (WSL). What process can a PR reviewer use to test or verify this change? --- System-level testing - still outstanding on MacOS Breaking Changes --- - [x] None - [ ] Requires data directory on base node to be deleted - [ ] Requires hard fork - [ ] Other - Please specify --- .../minotari_node/src/commands/cli_loop.rs | 29 ++++++++++++++++--- .../minotari_node/src/commands/command/mod.rs | 6 ++++ applications/minotari_node/src/config.rs | 3 +- .../src/base_node/tari_pulse_service/mod.rs | 2 +- 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/applications/minotari_node/src/commands/cli_loop.rs b/applications/minotari_node/src/commands/cli_loop.rs index a3cd47b7f5..be4a34c7e2 100644 --- a/applications/minotari_node/src/commands/cli_loop.rs +++ b/applications/minotari_node/src/commands/cli_loop.rs @@ -16,7 +16,7 @@ use tokio::{signal, time}; use crate::{ commands::{ cli, - command::{CommandContext, WatchCommand}, + command::{Args, CommandContext, WatchCommand}, parser::Parser, reader::CommandReader, }, @@ -87,7 +87,9 @@ impl CliLoop { } else { while !self.done { self.watch_loop().await; - self.execute_command().await; + if !self.done { + self.execute_command().await; + } } } } @@ -129,12 +131,19 @@ impl CliLoop { println!("Wrong command to watch `{}`. Failed with: {}", line, err); } else { let mut events = EventStream::new(); - loop { + while !self.done { let interval = time::sleep(interval); tokio::select! { _ = interval => { if let Err(err) = self.context.handle_command_str(line).await { println!("Watched command `{}` failed: {}", line, err); + } else { + let args: Result = line.parse(); + if let Ok(command) = args { + if command.is_quit() { + self.done = true; + } + } } continue; }, @@ -158,7 +167,9 @@ impl CliLoop { } } } - crossterm::execute!(io::stdout(), cursor::MoveToNextLine(1)).ok(); + if !self.done { + crossterm::execute!(io::stdout(), cursor::MoveToNextLine(1)).ok(); + } } terminal::disable_raw_mode().ok(); } @@ -183,6 +194,13 @@ impl CliLoop { _ = interval => { if let Err(err) = self.context.handle_command_str(line).await { println!("Watched command `{}` failed: {}", line, err); + } else { + let args: Result = line.parse(); + if let Ok(command) = args { + if command.is_quit() { + self.done = true; + } + } } continue; }, @@ -242,6 +260,9 @@ impl CliLoop { } else { self.done = true; } + if self.done && !self.shutdown_signal.is_triggered() { + self.context.shutdown.trigger(); + } }, _ = self.shutdown_signal.wait() => { self.done = true; diff --git a/applications/minotari_node/src/commands/command/mod.rs b/applications/minotari_node/src/commands/command/mod.rs index 14184a036b..fa11545b02 100644 --- a/applications/minotari_node/src/commands/command/mod.rs +++ b/applications/minotari_node/src/commands/command/mod.rs @@ -97,6 +97,12 @@ pub struct Args { pub command: Command, } +impl Args { + pub fn is_quit(&self) -> bool { + matches!(self.command, Command::Quit(_) | Command::Exit(_)) + } +} + #[derive(Debug, Subcommand, EnumVariantNames)] #[strum(serialize_all = "kebab-case")] pub enum Command { diff --git a/applications/minotari_node/src/config.rs b/applications/minotari_node/src/config.rs index f6b704801b..f209e5b23a 100644 --- a/applications/minotari_node/src/config.rs +++ b/applications/minotari_node/src/config.rs @@ -142,7 +142,8 @@ pub struct BaseNodeConfig { pub state_machine: BaseNodeStateMachineConfig, /// Obscure GRPC error responses pub report_grpc_error: bool, - // Interval to check if the base node is still in sync with the network + /// Interval to check if the base node is still in sync with the network + #[serde(with = "serializers::seconds")] pub tari_pulse_interval: Duration, } diff --git a/base_layer/core/src/base_node/tari_pulse_service/mod.rs b/base_layer/core/src/base_node/tari_pulse_service/mod.rs index 20de1f4339..5d2a277533 100644 --- a/base_layer/core/src/base_node/tari_pulse_service/mod.rs +++ b/base_layer/core/src/base_node/tari_pulse_service/mod.rs @@ -118,6 +118,7 @@ impl TariPulseService { let mut interval = time::interval(self.config.check_interval); let mut interval_failed = time::interval(Duration::from_millis(100)); loop { + interval.tick().await; let passed_checkpoints = match self.passed_checkpoints(&mut base_node_service).await { Ok(passed) => passed, Err(err) => { @@ -130,7 +131,6 @@ impl TariPulseService { notify_passed_checkpoints .send(!passed_checkpoints) .expect("Channel should be open"); - interval.tick().await; } } From 321e9ba4758365f7d5f5944d4f2fd086dd250037 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Ko=C5=BCuszek?= Date: Tue, 26 Nov 2024 10:08:18 +0100 Subject: [PATCH 09/19] fix(tari-pulse): await shutdown signal in main loop (#6696) Description --- Await shutdown signal and reduce error logging when node failed to compare blocks hashes. Motivation and Context --- Error logs were spamming on not supported network, greatly reducing readability and shutdown signal wasn't working propely. How Has This Been Tested? --- Run local node on esmeralda network (which is not supported yet) and watch for error logs. Also check shutdown behavior. What process can a PR reviewer use to test or verify this change? --- Same as above Breaking Changes --- - [x] None - [ ] Requires data directory on base node to be deleted - [ ] Requires hard fork - [ ] Other - Please specify --------- Co-authored-by: SW van Heerden Co-authored-by: Hansie Odendaal <39146854+hansieodendaal@users.noreply.github.com> --- applications/minotari_node/src/config.rs | 2 +- .../src/base_node/tari_pulse_service/mod.rs | 63 ++++++++++++++----- 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/applications/minotari_node/src/config.rs b/applications/minotari_node/src/config.rs index f209e5b23a..044caee2cd 100644 --- a/applications/minotari_node/src/config.rs +++ b/applications/minotari_node/src/config.rs @@ -142,7 +142,7 @@ pub struct BaseNodeConfig { pub state_machine: BaseNodeStateMachineConfig, /// Obscure GRPC error responses pub report_grpc_error: bool, - /// Interval to check if the base node is still in sync with the network + // Interval to check if the base node is still in sync with the network #[serde(with = "serializers::seconds")] pub tari_pulse_interval: Duration, } diff --git a/base_layer/core/src/base_node/tari_pulse_service/mod.rs b/base_layer/core/src/base_node/tari_pulse_service/mod.rs index 5d2a277533..0d7492b686 100644 --- a/base_layer/core/src/base_node/tari_pulse_service/mod.rs +++ b/base_layer/core/src/base_node/tari_pulse_service/mod.rs @@ -33,7 +33,7 @@ use hickory_client::{ rr::{DNSClass, Name, RData, Record, RecordType}, tcp::TcpClientStream, }; -use log::{error, info}; +use log::{error, info, warn}; use serde::{Deserialize, Serialize}; use tari_p2p::Network; use tari_service_framework::{async_trait, ServiceInitializationError, ServiceInitializer, ServiceInitializerContext}; @@ -75,13 +75,18 @@ fn get_network_dns_name(network: Network) -> Name { pub struct TariPulseService { dns_name: Name, config: TariPulseConfig, + shutdown_signal: ShutdownSignal, } impl TariPulseService { - pub async fn new(config: TariPulseConfig) -> Result { + pub async fn new(config: TariPulseConfig, shutdown_signal: ShutdownSignal) -> Result { let dns_name: Name = get_network_dns_name(config.clone().network); info!(target: LOG_TARGET, "Tari Pulse Service initialized with DNS name: {}", dns_name); - Ok(Self { dns_name, config }) + Ok(Self { + dns_name, + config, + shutdown_signal, + }) } pub fn default_trust_anchor() -> TrustAnchor { @@ -116,21 +121,45 @@ impl TariPulseService { notify_passed_checkpoints: watch::Sender, ) { let mut interval = time::interval(self.config.check_interval); - let mut interval_failed = time::interval(Duration::from_millis(100)); + let mut shutdown_signal = self.shutdown_signal.clone(); + loop { - interval.tick().await; - let passed_checkpoints = match self.passed_checkpoints(&mut base_node_service).await { - Ok(passed) => passed, - Err(err) => { - error!(target: LOG_TARGET, "Error checking if node passed checkpoints: {:?}", err); - interval_failed.tick().await; - continue; - }, - }; + tokio::select! { + _ = interval.tick() => { + let passed_checkpoints = match self.passed_checkpoints(&mut base_node_service).await { + Ok(passed) => { + interval = time::interval(self.config.check_interval); // reset interval if back to healthy + passed + }, + Err(err) => { + warn!(target: LOG_TARGET, "Failed to check if node has passed checkpoints: {:?}", err); + let old_interval = interval.period().as_secs(); + let new_interval = if old_interval > (60 * 30) { + warn!(target: LOG_TARGET, "Reached maximum retry interval of 30 minutes."); + old_interval + } else { + // increase interval if node repeatedly (up to 30 min) fails to fetch checkpoints + interval = time::interval(Duration::from_secs(old_interval * 2)); + interval.tick().await; + interval.period().as_secs() + }; + warn!(target: LOG_TARGET, "Retrying in {} seconds", new_interval); + continue; + }, + }; - notify_passed_checkpoints - .send(!passed_checkpoints) - .expect("Channel should be open"); + notify_passed_checkpoints + .send(!passed_checkpoints) + .expect("Channel should be open"); + }, + _ = shutdown_signal.wait() => { + info!( + target: LOG_TARGET, + "Tari Pulse shutting down because the shutdown signal was received" + ); + break; + }, + } } } @@ -231,7 +260,7 @@ impl ServiceInitializer for TariPulseServiceInitializer { context.spawn_when_ready(move |handles| async move { let base_node_service = handles.expect_handle::(); - let mut tari_pulse_service = TariPulseService::new(config) + let mut tari_pulse_service = TariPulseService::new(config, shutdown_signal.clone()) .await .expect("Should be able to get the service"); let tari_pulse_service = tari_pulse_service.run(base_node_service, sender); From e22bc0eb073cc93a86a2ffdbb4eb9c1a4ffeebc5 Mon Sep 17 00:00:00 2001 From: Hansie Odendaal <39146854+hansieodendaal@users.noreply.github.com> Date: Wed, 27 Nov 2024 08:42:39 +0200 Subject: [PATCH 10/19] feat: add connectivity timeout (#6703) Description --- Added a wallet connectivity timeout so that long-winded dial-peer failures can be managed timeously. Motivation and Context --- On some mobile wallets, the `dial_peer` command can take up to 6 minutes to return an error or timeout. See the nextnet mobile wallet log below and notice the timestamp difference between `Attempting base node peer` and `Connectivity error: ConnectionFailed`: ``` 2024-11-26 09:48:39.078496504 [wallet::connectivity] DEBUG Attempting base node peer '1c8b393640e1cd7d1a86957eb3'... (last attempt Some(895ns)) 2024-11-26 09:54:32.664270603 [wallet::connectivity] WARN Connectivity error: ConnectionFailed: Failed to connect to peer within the maximum number of attempts 2024-11-26 09:54:32.667991713 [wallet::connectivity] DEBUG Attempting base node peer 'a04e78a02df887a26ffa9eadaa'... (last attempt Some(122ns)) 2024-11-26 09:58:35.639455170 [wallet::connectivity] WARN Connectivity error: ConnectionFailed: Failed to connect to peer within the maximum number of attempts 2024-11-26 09:58:35.642903697 [wallet::connectivity] DEBUG Attempting base node peer 'e108eb7fbf44d58199908aa928'... (last attempt Some(244ns)) 2024-11-26 10:00:03.975743624 [wallet::connectivity] WARN Connectivity error: ConnectionFailed: Failed to connect to peer within the maximum number of attempts 2024-11-26 10:00:03.978222425 [wallet::connectivity] DEBUG Attempting base node peer '6ea597117476676d5ddcb18153'... (last attempt Some(163ns)) 2024-11-26 10:04:24.017030169 [wallet::connectivity] WARN Connectivity error: ConnectionFailed: Failed to connect to peer within the maximum number of attempts 2024-11-26 10:04:24.022077451 [wallet::connectivity] DEBUG Attempting base node peer '63718f177e749a0484a7050f8d'... (last attempt Some(366ns)) 2024-11-26 10:09:52.935971247 [wallet::connectivity] WARN Connectivity error: ConnectionFailed: Failed to connect to peer within the maximum number of attempts 2024-11-26 10:09:52.939635269 [wallet::connectivity] DEBUG Attempting base node peer 'db5ab85a84ce79bcd2ea700f13'... (last attempt Some(285ns)) 2024-11-26 10:16:01.668541211 [wallet::connectivity] WARN Connectivity error: ConnectionFailed: Failed to connect to peer within the maximum number of attempts 2024-11-26 10:16:01.672009107 [wallet::connectivity] DEBUG Attempting base node peer '81e258cb5e8419dfdd863282c3'... (last attempt Some(610ns)) 2024-11-26 10:20:25.197734699 [wallet::connectivity] WARN Connectivity error: ConnectionFailed: Failed to connect to peer within the maximum number of attempts 2024-11-26 10:20:25.202187051 [wallet::connectivity] DEBUG Attempting base node peer '6d9043bba0c196ded52a9f79da'... (last attempt Some(244ns)) 2024-11-26 10:20:26.038427123 [wallet::connectivity] DEBUG Established peer connection to base node '6d9043bba0c196ded52a9f79da' ``` This PR, as tested on Windows console wallet, with many dysfunctional peer seeds on purpose ``` 2024-11-26 16:29:06.603475100 [wallet::connectivity] DEBUG Attempting base node peer '1c8b393640e1cd7d1a86957eb3'... (last attempt Some(100ns)) 2024-11-26 16:29:06.603488500 [wallet::connectivity] TRACE Attempt dial with client timeout 1s 2024-11-26 16:29:07.615599600 [wallet::connectivity] WARN Connectivity error: Client cancelled: 'Could not connect to '1c8b393640e1cd7d1a86957eb3' in 1s' 2024-11-26 16:29:07.615740400 [wallet::connectivity] DEBUG Attempting base node peer 'e108eb7fbf44d58199908aa928'... (last attempt Some(100ns)) 2024-11-26 16:29:07.615751700 [wallet::connectivity] TRACE Attempt dial with client timeout 1s 2024-11-26 16:29:08.617694200 [wallet::connectivity] WARN Connectivity error: Client cancelled: 'Could not connect to 'e108eb7fbf44d58199908aa928' in 1s' 2024-11-26 16:29:08.617884800 [wallet::connectivity] DEBUG Attempting base node peer '63718f177e749a0484a7050f8d'... (last attempt Some(100ns)) 2024-11-26 16:29:08.617903900 [wallet::connectivity] TRACE Attempt dial with client timeout 1s 2024-11-26 16:29:09.631693800 [wallet::connectivity] WARN Connectivity error: Client cancelled: 'Could not connect to '63718f177e749a0484a7050f8d' in 1s' 2024-11-26 16:29:09.631830300 [wallet::connectivity] DEBUG Attempting base node peer 'b02156f7ec30db5d661dd9b6e2'... (last attempt Some(0ns)) 2024-11-26 16:29:09.631840600 [wallet::connectivity] TRACE Attempt dial with client timeout 1s 2024-11-26 16:29:09.650843600 [wallet::connectivity] WARN Connectivity error: ConnectionFailed: Noise handshake error: An established connection was aborted by the software in your host machine. (os error 10053) 2024-11-26 16:29:09.650927000 [wallet::connectivity] DEBUG Attempting base node peer 'a04e78a02df887a26ffa9eadaa'... (last attempt Some(0ns)) 2024-11-26 16:29:09.650937900 [wallet::connectivity] TRACE Attempt dial with client timeout 1s 2024-11-26 16:29:10.663273200 [wallet::connectivity] WARN Connectivity error: Client cancelled: 'Could not connect to 'a04e78a02df887a26ffa9eadaa' in 1s' 2024-11-26 16:29:10.663415700 [wallet::connectivity] DEBUG Attempting base node peer 'a12b205abe9023e621910f0ee9'... (last attempt Some(100ns)) 2024-11-26 16:29:10.663430500 [wallet::connectivity] TRACE Attempt dial with client timeout 1s 2024-11-26 16:29:11.678154700 [wallet::connectivity] WARN Connectivity error: Client cancelled: 'Could not connect to 'a12b205abe9023e621910f0ee9' in 1s' 2024-11-26 16:29:11.678311700 [wallet::connectivity] DEBUG Attempting base node peer '81e258cb5e8419dfdd863282c3'... (last attempt Some(0ns)) 2024-11-26 16:29:11.678338700 [wallet::connectivity] TRACE Attempt dial with client timeout 1s 2024-11-26 16:29:12.695260800 [wallet::connectivity] WARN Connectivity error: Client cancelled: 'Could not connect to '81e258cb5e8419dfdd863282c3' in 1s' 2024-11-26 16:29:12.695391800 [wallet::connectivity] DEBUG Attempting base node peer '6d9043bba0c196ded52a9f79da'... (last attempt Some(100ns)) 2024-11-26 16:29:12.695401300 [wallet::connectivity] TRACE Attempt dial with client timeout 1s 2024-11-26 16:29:13.708776300 [wallet::connectivity] WARN Connectivity error: Client cancelled: 'Could not connect to '6d9043bba0c196ded52a9f79da' in 1s' 2024-11-26 16:29:13.708929300 [wallet::connectivity] DEBUG Attempting base node peer 'fb593780d69882b938429beb69'... (last attempt Some(0ns)) 2024-11-26 16:29:13.708951900 [wallet::connectivity] TRACE Attempt dial with client timeout 1s 2024-11-26 16:29:14.721569600 [wallet::connectivity] WARN Connectivity error: Client cancelled: 'Could not connect to 'fb593780d69882b938429beb69' in 1s' 2024-11-26 16:29:14.721697500 [wallet::connectivity] DEBUG Attempting base node peer 'db5ab85a84ce79bcd2ea700f13'... (last attempt Some(100ns)) 2024-11-26 16:29:14.721708200 [wallet::connectivity] TRACE Attempt dial with client timeout 1s 2024-11-26 16:29:15.734914000 [wallet::connectivity] WARN Connectivity error: Client cancelled: 'Could not connect to 'db5ab85a84ce79bcd2ea700f13' in 1s' 2024-11-26 16:29:15.735066300 [wallet::connectivity] DEBUG Attempting base node peer '6ea597117476676d5ddcb18153'... (last attempt Some(0ns)) 2024-11-26 16:29:15.735099300 [wallet::connectivity] TRACE Attempt dial with client timeout 1s 2024-11-26 16:29:16.740185800 [wallet::connectivity] WARN Connectivity error: Client cancelled: 'Could not connect to '6ea597117476676d5ddcb18153' in 1s' 2024-11-26 16:29:16.740313200 [wallet::connectivity] DEBUG Attempting base node peer '647db13c611aa70dcd9f06a8b1'... (last attempt Some(100ns)) 2024-11-26 16:29:16.740324900 [wallet::connectivity] TRACE Attempt dial with client timeout 1s 2024-11-26 16:29:17.740956000 [wallet::connectivity] WARN Connectivity error: Client cancelled: 'Could not connect to '647db13c611aa70dcd9f06a8b1' in 1s' 2024-11-26 16:29:17.741152500 [wallet::connectivity] DEBUG Attempting base node peer 'a4dbaf87693acaa0fe92f8f4f0'... (last attempt Some(0ns)) 2024-11-26 16:29:17.741166200 [wallet::connectivity] TRACE Attempt dial with client timeout 1s 2024-11-26 16:29:18.744368800 [wallet::connectivity] WARN Connectivity error: Client cancelled: 'Could not connect to 'a4dbaf87693acaa0fe92f8f4f0' in 1s' 2024-11-26 16:29:18.744526000 [wallet::connectivity] DEBUG Attempting base node peer 'e7b0d91465d5386e9d07e53cff'... (last attempt Some(0ns)) 2024-11-26 16:29:18.744538900 [wallet::connectivity] TRACE Attempt dial with client timeout 1s 2024-11-26 16:29:19.745518100 [wallet::connectivity] WARN Connectivity error: Client cancelled: 'Could not connect to 'e7b0d91465d5386e9d07e53cff' in 1s' 2024-11-26 16:29:19.745680000 [wallet::connectivity] DEBUG Attempting base node peer '17bfe6ee47f45491ea9407ad89'... (last attempt Some(0ns)) 2024-11-26 16:29:19.745797100 [wallet::connectivity] TRACE Attempt dial with client timeout 1s 2024-11-26 16:29:20.747956700 [wallet::connectivity] WARN Connectivity error: Client cancelled: 'Could not connect to '17bfe6ee47f45491ea9407ad89' in 1s' 2024-11-26 16:29:20.748180600 [wallet::connectivity] DEBUG Attempting base node peer 'bd11a65bb14f8188e0bde642d0'... (last attempt Some(0ns)) 2024-11-26 16:29:20.748227700 [wallet::connectivity] TRACE Attempt dial with client timeout 1s 2024-11-26 16:29:21.755291100 [wallet::connectivity] WARN Connectivity error: Client cancelled: 'Could not connect to 'bd11a65bb14f8188e0bde642d0' in 1s' 2024-11-26 16:29:21.755439100 [wallet::connectivity] DEBUG Attempting base node peer 'b7c07e293f2186689e88978bff'... (last attempt Some(0ns)) 2024-11-26 16:29:21.755453200 [wallet::connectivity] TRACE Attempt dial with client timeout 10s 2024-11-26 16:29:23.810412000 [wallet::connectivity] WARN Connectivity error: ConnectionFailed: Failed to connect to peer within the maximum number of attempts 2024-11-26 16:29:23.810491600 [wallet::connectivity] DEBUG Attempting base node peer '1c8b393640e1cd7d1a86957eb3'... (last attempt Some(0ns)) 2024-11-26 16:29:23.810501100 [wallet::connectivity] TRACE Attempt dial with client timeout 10s 2024-11-26 16:29:33.811236800 [wallet::connectivity] WARN Connectivity error: Client cancelled: 'Could not connect to '1c8b393640e1cd7d1a86957eb3' in 10s' 2024-11-26 16:29:33.811393800 [wallet::connectivity] DEBUG Attempting base node peer 'e108eb7fbf44d58199908aa928'... (last attempt Some(100ns)) 2024-11-26 16:29:33.811404200 [wallet::connectivity] TRACE Attempt dial with client timeout 10s 2024-11-26 16:29:43.822083900 [wallet::connectivity] WARN Connectivity error: Client cancelled: 'Could not connect to 'e108eb7fbf44d58199908aa928' in 10s' 2024-11-26 16:29:43.822250500 [wallet::connectivity] DEBUG Attempting base node peer '63718f177e749a0484a7050f8d'... (last attempt Some(100ns)) 2024-11-26 16:29:43.822263700 [wallet::connectivity] TRACE Attempt dial with client timeout 10s 2024-11-26 16:29:53.850035700 [wallet::connectivity] WARN Connectivity error: Client cancelled: 'Could not connect to '63718f177e749a0484a7050f8d' in 10s' 2024-11-26 16:29:53.850223800 [wallet::connectivity] DEBUG Attempting base node peer 'b02156f7ec30db5d661dd9b6e2'... (last attempt Some(0ns)) 2024-11-26 16:29:53.850241100 [wallet::connectivity] TRACE Attempt dial with client timeout 10s 2024-11-26 16:29:53.870034300 [wallet::connectivity] WARN Connectivity error: ConnectionFailed: Noise handshake error: An existing connection was forcibly closed by the remote host. (os error 10054) 2024-11-26 16:29:53.870101100 [wallet::connectivity] DEBUG Attempting base node peer 'a04e78a02df887a26ffa9eadaa'... (last attempt Some(100ns)) 2024-11-26 16:29:53.870110100 [wallet::connectivity] TRACE Attempt dial with client timeout 10s 2024-11-26 16:30:00.043621300 [wallet::connectivity] WARN Connectivity error: ConnectionFailed: Failed to connect to peer within the maximum number of attempts 2024-11-26 16:30:00.047536900 [wallet::connectivity] DEBUG Attempting base node peer 'a12b205abe9023e621910f0ee9'... (last attempt Some(100ns)) 2024-11-26 16:30:00.047550400 [wallet::connectivity] TRACE Attempt dial with client timeout 10s 2024-11-26 16:30:10.053350900 [wallet::connectivity] WARN Connectivity error: Client cancelled: 'Could not connect to 'a12b205abe9023e621910f0ee9' in 10s' 2024-11-26 16:30:10.053487900 [wallet::connectivity] DEBUG Attempting base node peer '81e258cb5e8419dfdd863282c3'... (last attempt Some(100ns)) 2024-11-26 16:30:10.053501000 [wallet::connectivity] TRACE Attempt dial with client timeout 10s 2024-11-26 16:30:20.068640100 [wallet::connectivity] WARN Connectivity error: Client cancelled: 'Could not connect to '81e258cb5e8419dfdd863282c3' in 10s' 2024-11-26 16:30:20.068766200 [wallet::connectivity] DEBUG Attempting base node peer '6d9043bba0c196ded52a9f79da'... (last attempt Some(100ns)) 2024-11-26 16:30:20.068777100 [wallet::connectivity] TRACE Attempt dial with client timeout 10s 2024-11-26 16:30:20.068813900 [wallet::connectivity] DEBUG Established peer connection to base node '6d9043bba0c196ded52a9f79da' ``` How Has This Been Tested? --- System-level testing What process can a PR reviewer use to test or verify this change? --- Code review System-level testing Breaking Changes --- - [x] None - [ ] Requires data directory on base node to be deleted - [ ] Requires hard fork - [ ] Other - Please specify --- .../src/connectivity_service/service.rs | 41 +++++++++++++++---- comms/core/src/connectivity/error.rs | 2 + 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/base_layer/wallet/src/connectivity_service/service.rs b/base_layer/wallet/src/connectivity_service/service.rs index ab5ac039bf..ce097096f8 100644 --- a/base_layer/wallet/src/connectivity_service/service.rs +++ b/base_layer/wallet/src/connectivity_service/service.rs @@ -20,7 +20,12 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use std::{collections::HashMap, mem, time::Duration}; +use std::{ + cmp::{max, min}, + collections::HashMap, + mem, + time::Duration, +}; use log::*; use tari_comms::{ @@ -34,7 +39,7 @@ use tari_core::base_node::{rpc::BaseNodeWalletRpcClient, sync::rpc::BaseNodeSync use tokio::{ sync::{mpsc, oneshot, watch}, time, - time::MissedTickBehavior, + time::{timeout, Duration as TokioDuration, MissedTickBehavior}, }; use crate::{ @@ -297,7 +302,10 @@ impl WalletConnectivityService { } else { return; }; + let mut loop_count = 0; + let number_of_seeds = peer_manager.get_state().1.len(); loop { + loop_count += 1; let node_id = if let Some(_time) = peer_manager.time_since_last_connection_attempt() { if peer_manager.get_current_peer().node_id == peer_manager.get_next_peer().node_id { // If we only have one peer in the list, wait a bit before retrying @@ -321,7 +329,10 @@ impl WalletConnectivityService { peer_manager.time_since_last_connection_attempt() ); self.pools.remove(&node_id); - match self.try_setup_rpc_pool(node_id.clone()).await { + match self + .try_setup_rpc_pool(node_id.clone(), loop_count / number_of_seeds + 1) + .await + { Ok(true) => { if self.peer_list_change_detected(&peer_manager) { debug!( @@ -391,13 +402,29 @@ impl WalletConnectivityService { self.online_status_watch.send(status); } - async fn try_setup_rpc_pool(&mut self, peer_node_id: NodeId) -> Result { - let conn = match self.try_dial_peer(peer_node_id.clone()).await? { - Some(c) => c, - None => { + async fn try_setup_rpc_pool( + &mut self, + peer_node_id: NodeId, + dial_cycle: usize, + ) -> Result { + // dial_timeout: 1 = 1s, 2 = 10s, 3 = 20s, 4 = 30s, 5 = 40s, 6 = 50s, 7 = 60s, 8 = 70s, 9 = 80s, 10 = 90s + let dial_timeout = TokioDuration::from_secs(min((max(1, 10 * (dial_cycle.saturating_sub(1)))) as u64, 90)); + trace!(target: LOG_TARGET, "Attempt dial with client timeout {:?}", dial_timeout); + let conn = match timeout(dial_timeout, self.try_dial_peer(peer_node_id.clone())).await { + Ok(Ok(Some(c))) => c, + Ok(Ok(None)) => { warn!(target: LOG_TARGET, "Could not dial base node peer '{}'", peer_node_id); return Ok(false); }, + Ok(Err(e)) => return Err(e), + Err(_) => { + return Err(WalletConnectivityError::ConnectivityError( + ConnectivityError::ClientCancelled(format!( + "Could not connect to '{}' in {:?}", + peer_node_id, dial_timeout + )), + )); + }, }; debug!( target: LOG_TARGET, diff --git a/comms/core/src/connectivity/error.rs b/comms/core/src/connectivity/error.rs index acb554ac79..5dbfe2849d 100644 --- a/comms/core/src/connectivity/error.rs +++ b/comms/core/src/connectivity/error.rs @@ -43,6 +43,8 @@ pub enum ConnectivityError { OnlineWaitTimeout(usize), #[error("Pending dial was cancelled")] DialCancelled, + #[error("Client cancelled: '{0}'")] + ClientCancelled(String), } impl From for ConnectivityError { From dc57806ce144305e7380186e0c27ae8eb3b0ab55 Mon Sep 17 00:00:00 2001 From: "C.Lee Taylor" <47312074+leet4tari@users.noreply.github.com> Date: Wed, 27 Nov 2024 08:44:32 +0200 Subject: [PATCH 11/19] chore(ci): add docs for Windows build setup, update randomx-rs and fix openssl builds (#6701) Description Add basic doc for Windows build setup Update randomx-rs Fix Windows openssl dependency for build binary workflow Remove some older dependency and some envs Motivation and Context Improve builds for Windows How Has This Been Tested? Builds in local fork --- .github/workflows/build_binaries.yml | 18 +- Cargo.lock | 4 +- buildtools/windows-dev-environment-notes.md | 418 ++++++++++++++++++++ 3 files changed, 427 insertions(+), 13 deletions(-) create mode 100644 buildtools/windows-dev-environment-notes.md diff --git a/.github/workflows/build_binaries.yml b/.github/workflows/build_binaries.yml index 63df4f32c9..2736d90386 100644 --- a/.github/workflows/build_binaries.yml +++ b/.github/workflows/build_binaries.yml @@ -218,14 +218,8 @@ jobs: - name: Install Windows dependencies if: startsWith(runner.os,'Windows') run: | - vcpkg.exe install sqlite3:x64-windows zlib:x64-windows # Bug in choco - need to install each package individually - choco upgrade llvm -y - # psutils is out of date - # choco upgrade psutils -y - choco upgrade openssl -y - # Should already be installed - # choco upgrade strawberryperl -y + vcpkg install openssl:x64-windows-static choco upgrade protoc -y rustup target add ${{ matrix.builds.target }} @@ -277,10 +271,8 @@ jobs: echo "SHELL_EXT=.bat" >> $GITHUB_ENV echo "TS_DIST=\dist" >> $GITHUB_ENV echo "PLATFORM_SPECIFIC_DIR=windows" >> $GITHUB_ENV - echo "SQLITE3_LIB_DIR=C:\vcpkg\installed\x64-windows\lib" >> $GITHUB_ENV - echo "OPENSSL_DIR=C:\Program Files\OpenSSL-Win64" >> $GITHUB_ENV - echo "LIBCLANG_PATH=C:\Program Files\LLVM\bin" >> $GITHUB_ENV - echo "C:\Strawberry\perl\bin" >> $GITHUB_PATH + echo "VCPKG_ROOT=C:\vcpkg" >> $GITHUB_ENV + echo "OPENSSL_DIR=C:\vcpkg\packages\openssl_x64-windows-static" >> $GITHUB_ENV - name: Cache cargo files and outputs if: ${{ ( ! startsWith(github.ref, 'refs/tags/v') ) && ( ! matrix.builds.cross ) && ( env.CARGO_CACHE ) }} @@ -320,6 +312,10 @@ jobs: echo "cargo options is: ${{ env.CARGO_OPTIONS }}" echo "cross flag: ${{ matrix.builds.cross }}" + - name: Debug environment variables - Windows + if: startsWith(runner.os,'Windows') + run: printenv + - name: Build release binaries shell: bash run: | diff --git a/Cargo.lock b/Cargo.lock index 5779a4aac1..3af07ca93f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5235,9 +5235,9 @@ dependencies = [ [[package]] name = "randomx-rs" -version = "1.3.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9abb8f2aa3432700c2b64a67406ac0da4956d78991f50559509cecc2b6abf249" +checksum = "09c347596479c4796192e68aec20e62e31655b57753586f2b1ec320b779ef14c" dependencies = [ "bitflags 1.3.2", "libc", diff --git a/buildtools/windows-dev-environment-notes.md b/buildtools/windows-dev-environment-notes.md new file mode 100644 index 0000000000..70a6951281 --- /dev/null +++ b/buildtools/windows-dev-environment-notes.md @@ -0,0 +1,418 @@ + +# Basic build environment setup guide for Windows using winget for quick developer package testing - neither definitive nor exhaustive + +Lots of info collected from - https://github.com/KhronosGroup/OpenCL-Guide/blob/main/chapters/getting_started_windows.md + +and ```needed for developing Tauri apps.``` - https://v1.tauri.app/v1/guides/getting-started/prerequisites + +Need to have ```winget``` installed and working, which requires ```App Installer```, not only installed, but updated to the latest version. + +Using Microsoft Edge, open the following URL: + +https://www.microsoft.com/p/app-installer/9nblggh4nns1#activetab=pivot:overviewtab + +then click the ```App Installer``` install button. + +Found that after installing and rebooting Windows and checking for ```App Installer``` updates and appling any outstanding updates. + +Check that ```winget``` is working, run in PowerShell. +```PowerShell +winget list +``` +sample of output without ```App Installer``` installed +``` +PS C:\Users\leet> winget list + | +PS C:\Users\leet> +``` + +sample output where ```winget``` has not be run yet: +```PowerShell +PS C:\Users\leet> winget list +Failed in attempting to update the source: winget +The `msstore` source requires that you view the following agreements before using. +Terms of Transaction: https://aka.ms/microsoft-store-terms-of-transaction +The source requires the current machine's 2-letter geographic region to be sent to the backend service to function properly (ex. "US"). + +Do you agree to all the source agreements terms? +[Y] Yes [N] No: y +Failed when searching source; results will not be included: winget +Name Id Version +----------------------------------------------------------------------------------------------------------------------- +Clipchamp Clipchamp.Clipchamp_yxz26nhyzhsrt 2.2.8.0 +Microsoft Edge Microsoft Edge 130.0.2849.80 +Microsoft Edge WebView2 Runtime Microsoft EdgeWebView 130.0.2849.80 +``` +please notice ```Failed when searching source; results will not be included: winget```, normally means that ```App Installer``` needs to be updated. + +sample output where ```App Installer``` is installed, but not updated to the latest: +``` +PS C:\Users\leet> winget list +Failed in attempting to update the source: winget +Failed when searching source; results will not be included: winget +``` + +sample of output where ```winget``` is ready to be used for installing tools: +``` +PS C:\Users\leet> winget list +Name Id Version Available Source +----------------------------------------------------------------------------------------------------------------------- +Microsoft Visual Studio Installer ARP\Machine\X64\{6F320B93-EE3C-4826-85E… 3.11.2180.21897 +Tari Universe (Beta) ARP\Machine\X64\{A2500DE1-1C20-4E7E-9C5… 0.5.60.41105 +Visual Studio Build Tools 2022 Microsoft.VisualStudio.2022.BuildTools 17.11.5 winget +Microsoft Edge Microsoft.Edge 130.0.2849.68 winget +Microsoft Edge Update ARP\Machine\X86\Microsoft Edge Update 1.3.195.31 +Microsoft Edge WebView2 Runtime Microsoft.EdgeWebView2Runtime 130.0.2849.56 winget +Microsoft Visual C++ 2015-2022 Redistr… Microsoft.VCRedist.2015+.x64 14.40.33810.0 14.40.33816.0 winget +Microsoft OneDrive Microsoft.OneDrive 24.201.1006.0005 winget +Clipchamp MSIX\Clipchamp.Clipchamp_2.2.8.0_neutra… 2.2.8.0 +``` + +Then we can start installing components that will be needed in Compiling ```The Tari protocol tools``` locally + +# Install Visual Studio BuildTools 2022 +```PowerShell +winget install "Visual Studio BuildTools 2022" +``` +sample output would look something like: +``` +PS C:\Users\leet> winget install "Visual Studio BuildTools 2022" +Found Visual Studio BuildTools 2022 [Microsoft.VisualStudio.2022.BuildTools] Version 17.11.5 +This application is licensed to you by its owner. +Microsoft is not responsible for, nor does it grant any licenses to, third-party packages. +Downloading https://download.visualstudio.microsoft.com/download/pr/69e24482-3b48-44d3-af65-51f866a08313/471c9a89fa8ba27d356748ae0cf25eb1f362184992dc0bb6e9ccf10178c43c27/vs_BuildTools.exe + β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 4.22 MB / 4.22 MB +Successfully verified installer hash +Starting package install... +Successfully installed +``` + +# Install Visual Studio components for Windows 11 +```PowerShell +& "C:\Program Files (x86)\Microsoft Visual Studio\Installer\setup.exe" install --passive --norestart --productId Microsoft.VisualStudio.Product.BuildTools --channelId VisualStudio.17.Release --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.VisualStudio.Component.VC.Redist.14.Latest --add Microsoft.VisualStudio.Component.Windows11SDK.26100 --add Microsoft.VisualStudio.Component.VC.CMake.Project --add Microsoft.VisualStudio.Component.VC.CoreBuildTools --add Microsoft.VisualStudio.Component.VC.CoreIde --add Microsoft.VisualStudio.Component.VC.Redist.14.Latest --add Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core +```` +sample of the begining of output: +``` +PS C:\Users\leet> & "C:\Program Files (x86)\Microsoft Visual Studio\Installer\setup.exe" install --passive --norestart --productId Microsoft.VisualStudio.Product.BuildTools --channelId VisualStudio.17.Release --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.VisualStudio.Component.VC.Redist.14.Latest --add Microsoft.VisualStudio.Component.Windows11SDK.22000 +PS C:\Users\leet> [1d44:0001][2024-11-05T02:37:56] Saving the current locale (en-US) to user.json. +[1d44:0001][2024-11-05T02:37:56] Setting the telemetry services +[1d44:0005][2024-11-05T02:37:56] Creating a new telemetry service. +[1d44:0001][2024-11-05T02:37:56] Visual Studio Installer Version: 3.11.2180 +[1d44:0001][2024-11-05T02:37:56] Raw Command line: "C:\Program Files (x86)\Microsoft Visual Studio\Installer\setup.exe" install --passive --norestart --productId Microsoft.VisualStudio.Product.BuildTools --channelId VisualStudio.17.Release --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.VisualStudio.Component.VC.Redist.14.Latest --add Microsoft.VisualStudio.Component.Windows11SDK.22000 +[1d44:0001][2024-11-05T02:37:56] Parsed command line options: install --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 Microsoft.VisualStudio.Component.VC.Redist.14.Latest Microsoft.VisualStudio.Component.Windows11SDK.22000 --channelId VisualStudio.17.Release --norestart --passive --productId Microsoft.VisualStudio.Product.BuildTools +[1d44:0005][2024-11-05T02:37:56] Telemetry session ID: 8c0666e6-122f-43a2-8400-3c9a47d5d8d1 +[1d44:0004][2024-11-05T02:37:56] Creating new ExperimentationService +``` +Visual Studio Installer should download and install components requested. + +# Install git - https://git-scm.com/downloads/win +```PowerShell +winget install --id Git.Git -e --source winget +``` +sample output: +``` +PS C:\Users\leet> winget install --id Git.Git -e --source winget +>> +Found Git [Git.Git] Version 2.47.0.2 +This application is licensed to you by its owner. +Microsoft is not responsible for, nor does it grant any licenses to, third-party packages. +Downloading https://github.com/git-for-windows/git/releases/download/v2.47.0.windows.2/Git-2.47.0.2-64-bit.exe + β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 65.5 MB / 65.5 MB +Successfully verified installer hash +Starting package install... +Successfully installed +``` + +# Install Windows chocolatey package manager, helps with easy installation of additional components (protobuf) +```PowerShell +winget install --id chocolatey.chocolatey +``` +sample output: +``` +PS C:\Users\leet> winget install --id chocolatey.chocolatey +Found Chocolatey [Chocolatey.Chocolatey] Version 2.3.0.0 +This application is licensed to you by its owner. +Microsoft is not responsible for, nor does it grant any licenses to, third-party packages. +Downloading https://github.com/chocolatey/choco/releases/download/2.3.0/chocolatey-2.3.0.0.msi + β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 6.03 MB / 6.03 MB +Successfully verified installer hash +Starting package install... +Successfully installed +Notes: The Chocolatey CLI MSI is intended for installation only! If upgrading from 5.x of Licensed Extension, or 1.x of other Chocolatey products, see the upgrade guide at https://ch0.co/upv2v6 before continuing. Otherwise, run `choco upgrade chocolatey`. +``` + +# Install Protobuf with chocolatey +Use a new PowerShell console, as choco will not be in the current console path and seem broken. +```PowerShell +choco upgrade protoc -y +``` +sample output: +``` +PS C:\Users\leet> choco upgrade protoc -y +Chocolatey v2.3.0 +Upgrading the following packages: +protoc +By upgrading, you accept licenses for the packages. +protoc is not installed. Installing... +Downloading package from source 'https://community.chocolatey.org/api/v2/' +Progress: Downloading chocolatey-compatibility.extension 1.0.0... 100% + +chocolatey-compatibility.extension v1.0.0 [Approved] +chocolatey-compatibility.extension package files upgrade completed. Performing other installation steps. + Installed/updated chocolatey-compatibility extensions. + The upgrade of chocolatey-compatibility.extension was successful. + Deployed to 'C:\ProgramData\chocolatey\extensions\chocolatey-compatibility' +Downloading package from source 'https://community.chocolatey.org/api/v2/' +Progress: Downloading chocolatey-core.extension 1.4.0... 100% + +chocolatey-core.extension v1.4.0 [Approved] +chocolatey-core.extension package files upgrade completed. Performing other installation steps. + Installed/updated chocolatey-core extensions. + The upgrade of chocolatey-core.extension was successful. + Deployed to 'C:\ProgramData\chocolatey\extensions\chocolatey-core' +Downloading package from source 'https://community.chocolatey.org/api/v2/' +Progress: Downloading protoc 28.3.0... 100% + +protoc v28.3.0 [Approved] +protoc package files upgrade completed. Performing other installation steps. +Extracting 64-bit C:\ProgramData\chocolatey\lib\protoc\tools\protoc-28.3-win64.zip to C:\ProgramData\chocolatey\lib\protoc\tools... +C:\ProgramData\chocolatey\lib\protoc\tools + ShimGen has successfully created a shim for protoc.exe + The upgrade of protoc was successful. + Deployed to 'C:\ProgramData\chocolatey\lib\protoc\tools' + +Chocolatey upgraded 3/3 packages. + See the log for details (C:\ProgramData\chocolatey\logs\chocolatey.log). +``` + +# Install Windows vcpkg package manager, helps with easy installation of additional components (openssl) +```PowerShell +git clone https://github.com/microsoft/vcpkg.git \vcpkg +cd \vcpkg +.\bootstrap-vcpkg.bat +``` +sample output: +``` +PS C:\Users\leet> git clone https://github.com/microsoft/vcpkg.git C:\ +>> +fatal: destination path 'C:' already exists and is not an empty directory. +PS C:\Users\leet> git clone https://github.com/microsoft/vcpkg.git \vcpkg\ +>> +Cloning into '\vcpkg'... +remote: Enumerating objects: 254680, done. +remote: Counting objects: 100% (17338/17338), done. +remote: Compressing objects: 100% (686/686), done. +remote: Total 254680 (delta 17021), reused 16753 (delta 16652), pack-reused 237342 (from 1) +Receiving objects: 100% (254680/254680), 78.44 MiB | 6.35 MiB/s, done. +Resolving deltas: 100% (168180/168180), done. +Updating files: 100% (11832/11832), done. +PS C:\Users\leet> cd \vcpkg\ +PS C:\vcpkg> .\bootstrap-vcpkg.bat +Downloading https://github.com/microsoft/vcpkg-tool/releases/download/2024-11-12/vcpkg.exe -> C:\vcpkg\vcpkg.exe... done. +Validating signature... done. + +vcpkg package management program version 2024-11-12-eb492805e92a2c14a230f5c3deb3e89f6771c321 + +See LICENSE.txt for license information. +Telemetry +--------- +vcpkg collects usage data in order to help us improve your experience. +The data collected by Microsoft is anonymous. +You can opt-out of telemetry by re-running the bootstrap-vcpkg script with -disableMetrics, +passing --disable-metrics to vcpkg on the command line, +or by setting the VCPKG_DISABLE_METRICS environment variable. + +Read more about vcpkg telemetry at docs/about/privacy.md +``` + +# Install Openssl with vcpkg +```PowerShell +$Env:Path += ';C:\vcpkg' +vcpkg install openssl:x64-windows-static +``` +sample output: +``` +PS C:\Users\leet> $Env:Path += ';C:\vcpkg' +>> +PS C:\Users\leet> vcpkg install openssl:x64-windows-static +>> +Computing installation plan... +Computing installation plan... +A suitable version of cmake was not found (required v3.30.1). +Downloading cmake-3.30.1-windows-i386.zip +Successfully downloaded cmake-3.30.1-windows-i386.zip. +Extracting cmake... +A suitable version of 7zip was not found (required v24.8.0). +Downloading 7z2408-extra.7z +Successfully downloaded 7z2408-extra.7z. +Extracting 7zip... +A suitable version of 7zr was not found (required v24.8.0). +Downloading 424196f2-7zr.exe +Successfully downloaded 424196f2-7zr.exe. +The following packages will be built and installed: + openssl:x64-windows-static@3.4.0 + * vcpkg-cmake:x64-windows@2024-04-23 + * vcpkg-cmake-config:x64-windows@2024-05-23 + * vcpkg-cmake-get-vars:x64-windows@2024-09-22 +Additional packages (*) will be modified to complete this operation. +Detecting compiler hash for triplet x64-windows... +A suitable version of powershell-core was not found (required v7.2.24). +Downloading PowerShell-7.2.24-win-x64.zip +Successfully downloaded PowerShell-7.2.24-win-x64.zip. +Extracting powershell-core... +Compiler found: C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Tools/MSVC/14.42.34433/bin/Hostx64/x64/cl.exe +Detecting compiler hash for triplet x64-windows-static... +Compiler found: C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Tools/MSVC/14.42.34433/bin/Hostx64/x64/cl.exe +Restored 0 package(s) from C:\Users\leet\AppData\Local\vcpkg\archives in 523 us. Use --debug to see more details. +Installing 1/4 vcpkg-cmake:x64-windows@2024-04-23... +Building vcpkg-cmake:x64-windows@2024-04-23... +-- Installing: C:/vcpkg/packages/vcpkg-cmake_x64-windows/share/vcpkg-cmake/vcpkg_cmake_configure.cmake +-- Installing: C:/vcpkg/packages/vcpkg-cmake_x64-windows/share/vcpkg-cmake/vcpkg_cmake_build.cmake +-- Installing: C:/vcpkg/packages/vcpkg-cmake_x64-windows/share/vcpkg-cmake/vcpkg_cmake_install.cmake +-- Installing: C:/vcpkg/packages/vcpkg-cmake_x64-windows/share/vcpkg-cmake/vcpkg-port-config.cmake +-- Installing: C:/vcpkg/packages/vcpkg-cmake_x64-windows/share/vcpkg-cmake/copyright +-- Performing post-build validation +Stored binaries in 1 destinations in 123 ms. +Elapsed time to handle vcpkg-cmake:x64-windows: 428 ms +vcpkg-cmake:x64-windows package ABI: 1c9cd6d15b6bd6353941d2a7172da60b44407b254c8a998e11ac63a691d88c8c +Installing 2/4 vcpkg-cmake-config:x64-windows@2024-05-23... +Building vcpkg-cmake-config:x64-windows@2024-05-23... +-- Installing: C:/vcpkg/packages/vcpkg-cmake-config_x64-windows/share/vcpkg-cmake-config/vcpkg_cmake_config_fixup.cmake +-- Installing: C:/vcpkg/packages/vcpkg-cmake-config_x64-windows/share/vcpkg-cmake-config/vcpkg-port-config.cmake +-- Installing: C:/vcpkg/packages/vcpkg-cmake-config_x64-windows/share/vcpkg-cmake-config/copyright +-- Skipping post-build validation due to VCPKG_POLICY_EMPTY_PACKAGE +Stored binaries in 1 destinations in 139 ms. +Elapsed time to handle vcpkg-cmake-config:x64-windows: 371 ms +vcpkg-cmake-config:x64-windows package ABI: 3d79309c04958a43ccac3d839dceb8b3bf77fe6483ba5d7139e011f522841777 +Installing 3/4 vcpkg-cmake-get-vars:x64-windows@2024-09-22... +Building vcpkg-cmake-get-vars:x64-windows@2024-09-22... +-- Installing: C:/vcpkg/packages/vcpkg-cmake-get-vars_x64-windows/share/vcpkg-cmake-get-vars/vcpkg_cmake_get_vars.cmake +-- Installing: C:/vcpkg/packages/vcpkg-cmake-get-vars_x64-windows/share/vcpkg-cmake-get-vars/cmake_get_vars +-- Installing: C:/vcpkg/packages/vcpkg-cmake-get-vars_x64-windows/share/vcpkg-cmake-get-vars/cmake_get_vars/CMakeLists.txt +-- Installing: C:/vcpkg/packages/vcpkg-cmake-get-vars_x64-windows/share/vcpkg-cmake-get-vars/vcpkg-port-config.cmake +-- Installing: C:/vcpkg/packages/vcpkg-cmake-get-vars_x64-windows/share/vcpkg-cmake-get-vars/copyright +-- Performing post-build validation +Stored binaries in 1 destinations in 144 ms. +Elapsed time to handle vcpkg-cmake-get-vars:x64-windows: 375 ms +vcpkg-cmake-get-vars:x64-windows package ABI: 06e4bf7043f81750b3aaa7aa31a68dec84d1b064d55b6130ffea76f8ce300ffe +Installing 4/4 openssl:x64-windows-static@3.4.0... +Building openssl:x64-windows-static@3.4.0... +Downloading openssl-openssl-openssl-3.4.0.tar.gz +Successfully downloaded openssl-openssl-openssl-3.4.0.tar.gz. +-- Extracting source C:/vcpkg/downloads/openssl-openssl-openssl-3.4.0.tar.gz +-- Applying patch cmake-config.patch +-- Applying patch command-line-length.patch +-- Applying patch script-prefix.patch +-- Applying patch asm-armcap.patch +-- Applying patch windows/install-layout.patch +-- Applying patch windows/install-pdbs.patch +-- Applying patch unix/android-cc.patch +-- Applying patch unix/move-openssldir.patch +-- Applying patch unix/no-empty-dirs.patch +-- Applying patch unix/no-static-libs-for-shared.patch +-- Using source at C:/vcpkg/buildtrees/openssl/src/nssl-3.4.0-821e8e5bdc.clean +Downloading strawberry-perl-5.40.0.1-64bit-portable.zip +Successfully downloaded strawberry-perl-5.40.0.1-64bit-portable.zip. +-- Found external ninja('1.12.1'). +-- Getting CMake variables for x64-windows-static +Downloading nasm-2.16.01-win64.zip +Successfully downloaded nasm-2.16.01-win64.zip. +-- Getting CMake variables for x64-windows-static +Downloading jom_1_1_4.zip +Successfully downloaded jom_1_1_4.zip. +-- Prerunning x64-windows-static-dbg +-- Building x64-windows-static-dbg +-- Prerunning x64-windows-static-rel +-- Building x64-windows-static-rel +-- Fixing pkgconfig file: C:/vcpkg/packages/openssl_x64-windows-static/lib/pkgconfig/libcrypto.pc +-- Fixing pkgconfig file: C:/vcpkg/packages/openssl_x64-windows-static/lib/pkgconfig/libssl.pc +-- Fixing pkgconfig file: C:/vcpkg/packages/openssl_x64-windows-static/lib/pkgconfig/openssl.pc +Downloading msys2-mingw-w64-x86_64-pkgconf-1~2.3.0-1-any.pkg.tar.zst +Successfully downloaded msys2-mingw-w64-x86_64-pkgconf-1~2.3.0-1-any.pkg.tar.zst. +Downloading msys2-msys2-runtime-3.5.4-2-x86_64.pkg.tar.zst +Successfully downloaded msys2-msys2-runtime-3.5.4-2-x86_64.pkg.tar.zst. +-- Using msys root at C:/vcpkg/downloads/tools/msys2/21caed2f81ec917b +-- Fixing pkgconfig file: C:/vcpkg/packages/openssl_x64-windows-static/debug/lib/pkgconfig/libcrypto.pc +-- Fixing pkgconfig file: C:/vcpkg/packages/openssl_x64-windows-static/debug/lib/pkgconfig/libssl.pc +-- Fixing pkgconfig file: C:/vcpkg/packages/openssl_x64-windows-static/debug/lib/pkgconfig/openssl.pc +-- Installing: C:/vcpkg/packages/openssl_x64-windows-static/share/openssl/usage +-- Installing: C:/vcpkg/packages/openssl_x64-windows-static/share/openssl/copyright +-- Performing post-build validation +Stored binaries in 1 destinations in 13 s. +Elapsed time to handle openssl:x64-windows-static: 12 min +openssl:x64-windows-static package ABI: 746f9866315ce83ce1152f628b0dc320c6c36af665378d4a042c3385da77ce43 +Total install time: 12 min +openssl is compatible with built-in CMake targets: + + find_package(OpenSSL REQUIRED) + target_link_libraries(main PRIVATE OpenSSL::SSL) + target_link_libraries(main PRIVATE OpenSSL::Crypto) +``` + +# Install rust +```PowerShell +winget install --id Rustlang.Rustup +``` +sample ouput: +``` +PS C:\Users\leet\src\vcpkg> winget install --id Rustlang.Rustup +Found Rustup: the Rust toolchain installer [Rustlang.Rustup] Version 1.27.1 +This application is licensed to you by its owner. +Microsoft is not responsible for, nor does it grant any licenses to, third-party packages. +Downloading https://static.rust-lang.org/rustup/archive/1.27.1/x86_64-pc-windows-msvc/rustup-init.exe + β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 8.53 MB / 8.53 MB +Successfully verified installer hash +Starting package install... +Successfully installed +``` + +# Get the Tari code base +```PowerShell +cd src +git clone https://github.com/tari-project/tari.git +cd tari +``` +sample output: +``` +PS C:\Users\leet\src> git clone https://github.com/tari-project/tari.git +>> +Cloning into 'tari'... +remote: Enumerating objects: 133401, done. +remote: Counting objects: 100% (7577/7577), done. +remote: Compressing objects: 100% (3635/3635), done. +remote: Total 133401 (delta 4830), reused 6216 (delta 3900), pack-reused 125824 (from 1) +Receiving objects: 100% (133401/133401), 144.04 MiB | 5.98 MiB/s, done. +Resolving deltas: 100% (99974/99974), done. +Updating files: 100% (1786/1786), done. +``` + +# Build Tari Tools +```PowerShell +$Env:VCPKG_ROOT = 'C:\vcpkg' +$Env:OPENSSL_DIR = 'C:\vcpkg\packages\openssl_x64-windows-static' +cargo build --release --bin minotari_miner +``` +sample output: +``` +PS C:\Users\leet> cd src\tari +PS C:\Users\leet\src\tari> cargo build --release --bin minotari_miner +info: syncing channel updates for 'nightly-2024-07-07-x86_64-pc-windows-msvc' +info: latest update on 2024-07-07, rust version 1.81.0-nightly (ed7e35f34 2024-07-06) +info: downloading component 'cargo' +info: downloading component 'clippy' +info: downloading component 'rust-docs' +info: downloading component 'rust-std' +info: downloading component 'rustc' +info: downloading component 'rustfmt' +info: installing component 'cargo' +info: installing component 'clippy' +info: installing component 'rust-docs' +info: installing component 'rust-std' +info: installing component 'rustc' +info: installing component 'rustfmt' + Updating git repository `https://github.com/tari-project/lmdb-rs` + Updating git submodule `https://github.com/LMDB/lmdb.git` + Updating crates.io index + Updating git repository `https://github.com/Zondax/ledger-rs` + Downloading 516 crates +``` From eaa0306d1928f5a31b29f08863a070ea1343cbf0 Mon Sep 17 00:00:00 2001 From: SW van Heerden Date: Wed, 27 Nov 2024 11:12:08 +0200 Subject: [PATCH 12/19] feat: make hickory dns optional (#6705) Description --- Hickory dns inclused open ssl which has trouble compiling on all platforms. Making it optional only when needed removes the need to solve this --- base_layer/core/Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base_layer/core/Cargo.toml b/base_layer/core/Cargo.toml index 24e1393311..e96ed74872 100644 --- a/base_layer/core/Cargo.toml +++ b/base_layer/core/Cargo.toml @@ -20,6 +20,7 @@ base_node = [ "base_node_proto", "monero", "randomx-rs", + "hickory-client", ] base_node_proto = [] benches = ["base_node"] @@ -93,7 +94,7 @@ tiny-keccak = { package = "tari-tiny-keccak", version = "2.0.2", features = [ "keccak", ] } dirs-next = "1.0.2" -hickory-client = { version = "0.25.0-alpha.2", features = ["dns-over-rustls", "dnssec-openssl"] } +hickory-client = { version = "0.25.0-alpha.2", features = ["dns-over-rustls", "dnssec-openssl"], optional = true } anyhow = "1.0.53" [dev-dependencies] From a75e0c6f1b51b61aa1576bf671bd0d74bd45490f Mon Sep 17 00:00:00 2001 From: Hansie Odendaal <39146854+hansieodendaal@users.noreply.github.com> Date: Wed, 27 Nov 2024 13:41:59 +0200 Subject: [PATCH 13/19] feat: fix tari pulse running as fast as possible (#6704) Description --- ~- Solve openssl build issue for non-base nodes by moving the Tari pulse service to the base node application~ - Fixed Tari pulse not adhering to the tick intervals Motivation and Context --- ~- Openssl cause build issues for other platforms~ - Tari puls were running _as fast as possible_, instead of adhering to the tick intervals ``` 2024-11-27 10:31:41.834109900 [c::bn::tari_pulse] INFO Initializing Tari Pulse Service 2024-11-27 10:31:41.834119800 [c::bn::tari_pulse] INFO Tari Pulse Service initialized 2024-11-27 10:31:41.994249400 [c::bn::tari_pulse] INFO Tari Pulse Service initialized with DNS name: checkpoints-nextnet.tari.com 2024-11-27 10:31:41.995570900 [c::bn::tari_pulse] TRACE Interval tick: 1 2024-11-27 10:31:42.093937500 [c::bn::tari_pulse] TRACE Passed checkpoints: true, DNS: (45168, 1e3c56468f464072d9879e29a70891e9916f2206116c8819637c266a8b1d2efa), Local: (45168, 1e3c56468f464072d9879e29a70891e9916f2206116c8819637c266a8b1d2efa) 2024-11-27 10:31:42.099942200 [c::bn::tari_pulse] TRACE Interval tick: 2 2024-11-27 10:31:42.151937500 [c::bn::tari_pulse] TRACE Passed checkpoints: true, DNS: (45168, 1e3c56468f464072d9879e29a70891e9916f2206116c8819637c266a8b1d2efa), Local: (45168, 1e3c56468f464072d9879e29a70891e9916f2206116c8819637c266a8b1d2efa) 2024-11-27 10:31:42.162359500 [c::bn::tari_pulse] TRACE Interval tick: 3 2024-11-27 10:31:42.553671300 [c::bn::tari_pulse] TRACE Passed checkpoints: true, DNS: (45168, 1e3c56468f464072d9879e29a70891e9916f2206116c8819637c266a8b1d2efa), Local: (45168, 1e3c56468f464072d9879e29a70891e9916f2206116c8819637c266a8b1d2efa) 2024-11-27 10:31:42.568889200 [c::bn::tari_pulse] TRACE Interval tick: 4 2024-11-27 10:31:42.622576100 [c::bn::tari_pulse] TRACE Passed checkpoints: true, DNS: (45168, 1e3c56468f464072d9879e29a70891e9916f2206116c8819637c266a8b1d2efa), Local: (45168, 1e3c56468f464072d9879e29a70891e9916f2206116c8819637c266a8b1d2efa) 2024-11-27 10:31:42.627371600 [c::bn::tari_pulse] TRACE Interval tick: 5 2024-11-27 10:31:42.870493900 [c::bn::tari_pulse] TRACE Passed checkpoints: true, DNS: (45168, 1e3c56468f464072d9879e29a70891e9916f2206116c8819637c266a8b1d2efa), Local: (45168, 1e3c56468f464072d9879e29a70891e9916f2206116c8819637c266a8b1d2efa) ``` - This PR: ``` 2024-11-27 11:51:08.123837900 [c::bn::tari_pulse] INFO Initializing Tari Pulse Service 2024-11-27 11:51:08.123852600 [c::bn::tari_pulse] INFO Tari Pulse Service initialized 2024-11-27 11:51:08.278346300 [c::bn::tari_pulse] INFO Tari Pulse Service initialized with DNS name: checkpoints-nextnet.tari.com 2024-11-27 11:51:08.279742100 [c::bn::tari_pulse] TRACE Interval tick: 1 2024-11-27 11:51:08.353759600 [c::bn::tari_pulse] TRACE Passed checkpoints: true, DNS: (45168, 1e3c56468f464072d9879e29a70891e9916f2206116c8819637c266a8b1d2efa), Local: (45168, 1e3c56468f464072d9879e29a70891e9916f2206116c8819637c266a8b1d2efa) 2024-11-27 11:53:08.297138300 [c::bn::tari_pulse] TRACE Interval tick: 2 2024-11-27 11:53:08.700206500 [c::bn::tari_pulse] TRACE Passed checkpoints: true, DNS: (45168, 1e3c56468f464072d9879e29a70891e9916f2206116c8819637c266a8b1d2efa), Local: (45168, 1e3c56468f464072d9879e29a70891e9916f2206116c8819637c266a8b1d2efa) 2024-11-27 11:55:08.303411400 [c::bn::tari_pulse] TRACE Interval tick: 3 2024-11-27 11:55:08.358827400 [c::bn::tari_pulse] TRACE Passed checkpoints: true, DNS: (45168, 1e3c56468f464072d9879e29a70891e9916f2206116c8819637c266a8b1d2efa), Local: (45168, 1e3c56468f464072d9879e29a70891e9916f2206116c8819637c266a8b1d2efa) 2024-11-27 11:57:08.311930500 [c::bn::tari_pulse] TRACE Interval tick: 4 2024-11-27 11:57:08.416916200 [c::bn::tari_pulse] TRACE Passed checkpoints: true, DNS: (45168, 1e3c56468f464072d9879e29a70891e9916f2206116c8819637c266a8b1d2efa), Local: (45168, 1e3c56468f464072d9879e29a70891e9916f2206116c8819637c266a8b1d2efa) ``` How Has This Been Tested? --- System-level testing. ~**Note:** Build tests for other platforms must still be performed.~ What process can a PR reviewer use to test or verify this change? --- Code review. System-level testing. Breaking Changes --- - [x] None - [ ] Requires data directory on base node to be deleted - [ ] Requires hard fork - [ ] Other - Please specify --- .../src/base_node/tari_pulse_service/mod.rs | 59 +++++++++++-------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/base_layer/core/src/base_node/tari_pulse_service/mod.rs b/base_layer/core/src/base_node/tari_pulse_service/mod.rs index 0d7492b686..3ae3f5bfee 100644 --- a/base_layer/core/src/base_node/tari_pulse_service/mod.rs +++ b/base_layer/core/src/base_node/tari_pulse_service/mod.rs @@ -20,7 +20,7 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use std::{str::FromStr, time::Duration}; +use std::{cmp::min, str::FromStr, time::Duration}; use futures::future; use hickory_client::{ @@ -33,13 +33,13 @@ use hickory_client::{ rr::{DNSClass, Name, RData, Record, RecordType}, tcp::TcpClientStream, }; -use log::{error, info, warn}; +use log::{debug, error, info, trace, warn}; use serde::{Deserialize, Serialize}; use tari_p2p::Network; use tari_service_framework::{async_trait, ServiceInitializationError, ServiceInitializer, ServiceInitializerContext}; use tari_shutdown::ShutdownSignal; use tari_utilities::hex::Hex; -use tokio::{net::TcpStream as TokioTcpStream, sync::watch, time}; +use tokio::{net::TcpStream as TokioTcpStream, sync::watch, time, time::MissedTickBehavior}; use super::LocalNodeCommsInterface; use crate::base_node::comms_interface::CommsInterfaceError; @@ -121,31 +121,37 @@ impl TariPulseService { notify_passed_checkpoints: watch::Sender, ) { let mut interval = time::interval(self.config.check_interval); + interval.set_missed_tick_behavior(MissedTickBehavior::Delay); + tokio::pin!(interval); let mut shutdown_signal = self.shutdown_signal.clone(); + let mut count = 0u64; + let mut skip_ticks = 0; + let mut skipped_ticks = 0; loop { tokio::select! { _ = interval.tick() => { - let passed_checkpoints = match self.passed_checkpoints(&mut base_node_service).await { - Ok(passed) => { - interval = time::interval(self.config.check_interval); // reset interval if back to healthy - passed - }, - Err(err) => { - warn!(target: LOG_TARGET, "Failed to check if node has passed checkpoints: {:?}", err); - let old_interval = interval.period().as_secs(); - let new_interval = if old_interval > (60 * 30) { - warn!(target: LOG_TARGET, "Reached maximum retry interval of 30 minutes."); - old_interval - } else { - // increase interval if node repeatedly (up to 30 min) fails to fetch checkpoints - interval = time::interval(Duration::from_secs(old_interval * 2)); - interval.tick().await; - interval.period().as_secs() - }; - warn!(target: LOG_TARGET, "Retrying in {} seconds", new_interval); - continue; - }, + count += 1; + trace!(target: LOG_TARGET, "Interval tick: {}", count); + if skipped_ticks < skip_ticks { + skipped_ticks += 1; + debug!(target: LOG_TARGET, "Skipping {} of {} ticks", skipped_ticks, skip_ticks); + continue; + } + let passed_checkpoints = { + match self.passed_checkpoints(&mut base_node_service).await { + Ok(passed) => { + skip_ticks = 0; + skipped_ticks = 0; + passed + }, + Err(err) => { + warn!(target: LOG_TARGET, "Failed to check if node has passed checkpoints: {:?}", err); + skip_ticks = min(skip_ticks + 1, 30 * 60 / self.config.check_interval.as_secs()); + skipped_ticks = 0; + continue; + }, + } }; notify_passed_checkpoints @@ -174,7 +180,12 @@ impl TariPulseService { .max_by(|a, b| a.0.cmp(&b.0)) .ok_or(CommsInterfaceError::InternalError("No checkpoints found".to_string()))?; let local_checkpoints = self.get_node_block(base_node_service, max_height_block.0).await?; - Ok(local_checkpoints.1 == max_height_block.1) + let passed = local_checkpoints.1 == max_height_block.1; + trace!( + target: LOG_TARGET, "Passed checkpoints: {}, DNS: ({}, {}), Local: ({}, {})", + passed, max_height_block.0, max_height_block.1, local_checkpoints.0, local_checkpoints.1 + ); + Ok(passed) } async fn get_node_block( From 1104d20cccc13fc9a40d3e8f2454ae548bc85729 Mon Sep 17 00:00:00 2001 From: Hansie Odendaal Date: Wed, 27 Nov 2024 16:16:26 +0200 Subject: [PATCH 14/19] Merging dev #6655 --- applications/minotari_node/src/bootstrap.rs | 8 +- .../chain_metadata_service/service.rs | 3 + .../p2p/src/services/liveness/handle.rs | 27 +- base_layer/p2p/src/services/liveness/mock.rs | 12 +- base_layer/p2p/src/services/liveness/mod.rs | 4 +- .../p2p/src/services/liveness/service.rs | 54 ++- base_layer/p2p/src/services/liveness/state.rs | 20 +- base_layer/p2p/src/services/mod.rs | 1 + .../p2p/src/services/monitor_peers/mod.rs | 86 +++++ .../p2p/src/services/monitor_peers/service.rs | 315 ++++++++++++++++++ network/core/src/connection.rs | 6 + network/core/src/event.rs | 2 +- 12 files changed, 502 insertions(+), 36 deletions(-) create mode 100644 base_layer/p2p/src/services/monitor_peers/mod.rs create mode 100644 base_layer/p2p/src/services/monitor_peers/service.rs diff --git a/applications/minotari_node/src/bootstrap.rs b/applications/minotari_node/src/bootstrap.rs index 740e186b5a..d40af2c061 100644 --- a/applications/minotari_node/src/bootstrap.rs +++ b/applications/minotari_node/src/bootstrap.rs @@ -51,7 +51,10 @@ use tari_p2p::{ initialization::P2pInitializer, message::TariNodeMessageSpec, peer_seeds::SeedPeer, - services::liveness::{config::LivenessConfig, LivenessInitializer}, + services::{ + liveness::{config::LivenessConfig, LivenessInitializer}, + monitor_peers::MonitorPeersInitializer, + }, Dispatcher, P2pConfig, }; @@ -142,6 +145,9 @@ where B: BlockchainBackend + 'static }, dispatcher.clone(), )) + .add_initializer(MonitorPeersInitializer::new( + base_node_config.metadata_auto_ping_interval, + )) .add_initializer(ChainMetadataServiceInitializer) .add_initializer(BaseNodeStateMachineInitializer::new( self.db.clone().into(), diff --git a/base_layer/core/src/base_node/chain_metadata_service/service.rs b/base_layer/core/src/base_node/chain_metadata_service/service.rs index 69b2670df3..2a0a6e247f 100644 --- a/base_layer/core/src/base_node/chain_metadata_service/service.rs +++ b/base_layer/core/src/base_node/chain_metadata_service/service.rs @@ -365,6 +365,7 @@ mod test { metadata, peer_id, latency: None, + nonce: 0, }; let sample_event = LivenessEvent::ReceivedPong(Box::new(pong_event)); @@ -387,6 +388,7 @@ mod test { metadata, peer_id: node_id, latency: None, + nonce: 0, }; let sample_event = LivenessEvent::ReceivedPong(Box::new(pong_event)); @@ -405,6 +407,7 @@ mod test { metadata, peer_id: node_id, latency: None, + nonce: 0, }; let sample_event = LivenessEvent::ReceivedPong(Box::new(pong_event)); diff --git a/base_layer/p2p/src/services/liveness/handle.rs b/base_layer/p2p/src/services/liveness/handle.rs index 4ae77eee56..cd52d0e747 100644 --- a/base_layer/p2p/src/services/liveness/handle.rs +++ b/base_layer/p2p/src/services/liveness/handle.rs @@ -35,6 +35,8 @@ use crate::proto::liveness::MetadataKey; pub enum LivenessRequest { /// Send a ping to the given node ID SendPing(PeerId), + /// Ping a list of peers + SendPings(Vec), /// Retrieve the total number of pings received GetPingCount, /// Retrieve the total number of pongs received @@ -55,7 +57,7 @@ pub enum LivenessRequest { #[derive(Debug)] pub enum LivenessResponse { /// Indicates that the request succeeded - Ok, + Ok(Option>), /// Used to return a counter value from `GetPingCount` and `GetPongCount` Count(usize), /// Response for GetAvgLatency and GetNetworkAvgLatency @@ -82,14 +84,17 @@ pub struct PingPongEvent { pub latency: Option, /// Metadata of the corresponding node pub metadata: Metadata, + /// The nonce of the ping/pong message, for clients that want to match pings with pongs + pub nonce: u64, } impl PingPongEvent { - pub fn new(peer_id: PeerId, latency: Option, metadata: Metadata) -> Self { + pub fn new(peer_id: PeerId, latency: Option, metadata: Metadata, nonce: u64) -> Self { Self { peer_id, latency, metadata, + nonce, } } } @@ -120,9 +125,17 @@ impl LivenessHandle { } /// Send a ping to a given node ID - pub async fn send_ping(&mut self, peer_id: PeerId) -> Result<(), LivenessError> { + pub async fn send_ping(&mut self, peer_id: PeerId) -> Result { match self.handle.call(LivenessRequest::SendPing(peer_id)).await?? { - LivenessResponse::Ok => Ok(()), + LivenessResponse::Ok(Some(nonces)) => Ok(nonces[0]), + _ => Err(LivenessError::UnexpectedApiResponse), + } + } + + /// Send pings to a list of peers + pub async fn send_pings(&mut self, node_ids: Vec) -> Result, LivenessError> { + match self.handle.call(LivenessRequest::SendPings(node_ids)).await?? { + LivenessResponse::Ok(Some(nonces)) => Ok(nonces), _ => Err(LivenessError::UnexpectedApiResponse), } } @@ -150,7 +163,7 @@ impl LivenessHandle { .call(LivenessRequest::SetMetadataEntry(key, value)) .await?? { - LivenessResponse::Ok => Ok(()), + LivenessResponse::Ok(_) => Ok(()), _ => Err(LivenessError::UnexpectedApiResponse), } } @@ -158,7 +171,7 @@ impl LivenessHandle { /// Add a monitored peer to the basic config if not present pub async fn check_add_monitored_peer(&mut self, peer_id: PeerId) -> Result<(), LivenessError> { match self.handle.call(LivenessRequest::AddMonitoredPeer(peer_id)).await?? { - LivenessResponse::Ok => Ok(()), + LivenessResponse::Ok(_) => Ok(()), _ => Err(LivenessError::UnexpectedApiResponse), } } @@ -170,7 +183,7 @@ impl LivenessHandle { .call(LivenessRequest::RemoveMonitoredPeer(peer_id)) .await?? { - LivenessResponse::Ok => Ok(()), + LivenessResponse::Ok(_) => Ok(()), _ => Err(LivenessError::UnexpectedApiResponse), } } diff --git a/base_layer/p2p/src/services/liveness/mock.rs b/base_layer/p2p/src/services/liveness/mock.rs index 652531a17f..9b765fe5d3 100644 --- a/base_layer/p2p/src/services/liveness/mock.rs +++ b/base_layer/p2p/src/services/liveness/mock.rs @@ -125,7 +125,11 @@ impl LivenessMock { self.mock_state.add_request_call(req.clone()); match req { SendPing(_) => { - reply.send(Ok(LivenessResponse::Ok)).unwrap(); + reply.send(Ok(LivenessResponse::Ok(Some(vec![0])))).unwrap(); + }, + SendPings(node_ids) => { + let nonces: Vec = (0..node_ids.len() as u64).collect(); + reply.send(Ok(LivenessResponse::Ok(Some(nonces)))).unwrap(); }, GetPingCount => { reply.send(Ok(LivenessResponse::Count(1))).unwrap(); @@ -140,13 +144,13 @@ impl LivenessMock { reply.send(Ok(LivenessResponse::AvgLatency(None))).unwrap(); }, SetMetadataEntry(_, _) => { - reply.send(Ok(LivenessResponse::Ok)).unwrap(); + reply.send(Ok(LivenessResponse::Ok(None))).unwrap(); }, AddMonitoredPeer(_) => { - reply.send(Ok(LivenessResponse::Ok)).unwrap(); + reply.send(Ok(LivenessResponse::Ok(None))).unwrap(); }, RemoveMonitoredPeer(_) => { - reply.send(Ok(LivenessResponse::Ok)).unwrap(); + reply.send(Ok(LivenessResponse::Ok(None))).unwrap(); }, } } diff --git a/base_layer/p2p/src/services/liveness/mod.rs b/base_layer/p2p/src/services/liveness/mod.rs index 0076587f59..d91c0e77d2 100644 --- a/base_layer/p2p/src/services/liveness/mod.rs +++ b/base_layer/p2p/src/services/liveness/mod.rs @@ -45,6 +45,7 @@ pub use handle::{LivenessEvent, LivenessHandle, LivenessRequest, LivenessRespons mod message; mod service; +pub use service::MAX_INFLIGHT_TTL; mod state; pub use state::Metadata; @@ -64,6 +65,7 @@ use tari_service_framework::{ use tokio::sync::{broadcast, mpsc}; use self::service::LivenessService; +pub use crate::proto::liveness::MetadataKey; use crate::{ message::TariNodeMessageSpec, proto::message::TariMessageType, @@ -74,7 +76,7 @@ const LOG_TARGET: &str = "p2p::services::liveness"; /// Initializer for the Liveness service handle and service future. pub struct LivenessInitializer { - config: Option, + pub(crate) config: Option, dispatcher: Dispatcher, } diff --git a/base_layer/p2p/src/services/liveness/service.rs b/base_layer/p2p/src/services/liveness/service.rs index 5d84c4a682..bcabd667f6 100644 --- a/base_layer/p2p/src/services/liveness/service.rs +++ b/base_layer/p2p/src/services/liveness/service.rs @@ -20,7 +20,12 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use std::{collections::HashSet, iter, sync::Arc, time::Instant}; +use std::{ + collections::HashSet, + iter, + sync::Arc, + time::{Duration, Instant}, +}; use futures::{future::Either, pin_mut, stream::StreamExt, Stream}; use log::*; @@ -45,6 +50,8 @@ use crate::{ services::liveness::{handle::LivenessEventSender, LivenessEvent, PingPongEvent}, }; +pub const MAX_INFLIGHT_TTL: Duration = Duration::from_secs(30); + /// Service responsible for testing Liveness of Peers. pub struct LivenessService { config: LivenessConfig, @@ -163,7 +170,8 @@ where TRequestStream: Stream { @@ -188,19 +196,29 @@ where TRequestStream: Stream Result<(), LivenessError> { + async fn send_ping(&mut self, peer_id: PeerId) -> Result { let msg = PingPongMessage::ping_with_metadata(self.state.metadata().clone()); - self.state.add_inflight_ping(msg.nonce, peer_id); + let nonce = msg.nonce; + self.state.add_inflight_ping( + msg.nonce, + peer_id, + self.config.auto_ping_interval.unwrap_or(MAX_INFLIGHT_TTL), + ); debug!(target: LOG_TARGET, "Sending ping to peer '{}'", peer_id); self.outbound_messaging.send_message(peer_id, msg).await?; - Ok(()) + Ok(nonce) } async fn send_pong(&mut self, nonce: u64, dest: PeerId) -> Result<(), LivenessError> { @@ -214,9 +232,17 @@ where TRequestStream: Stream { - self.send_ping(peer_id).await?; + let nonce = self.send_ping(peer_id).await?; self.state.inc_pings_sent(); - Ok(LivenessResponse::Ok) + Ok(LivenessResponse::Ok(Some(vec![nonce]))) + }, + SendPings(peer_ids) => { + let mut nonces = Vec::with_capacity(peer_ids.len()); + for peer_id in peer_ids { + nonces.push(self.send_ping(peer_id).await?); + self.state.inc_pings_sent(); + } + Ok(LivenessResponse::Ok(Some(nonces))) }, GetPingCount => { let ping_count = self.get_ping_count(); @@ -236,15 +262,15 @@ where TRequestStream: Stream { self.state.set_metadata_entry(key, value); - Ok(LivenessResponse::Ok) + Ok(LivenessResponse::Ok(None)) }, AddMonitoredPeer(peer_id) => { self.monitored_peers.insert(peer_id); - Ok(LivenessResponse::Ok) + Ok(LivenessResponse::Ok(None)) }, RemoveMonitoredPeer(peer_id) => { self.monitored_peers.remove(&peer_id); - Ok(LivenessResponse::Ok) + Ok(LivenessResponse::Ok(None)) }, } } @@ -270,7 +296,11 @@ where TRequestStream: Stream, +} + +impl MonitorPeersInitializer { + /// Create a new MonitorPeersInitializer from the inbound message subscriber + pub fn new(auto_ping_interval: Duration) -> Self { + Self { + auto_ping_interval: Some(auto_ping_interval), + } + } +} + +impl Default for MonitorPeersInitializer { + fn default() -> Self { + Self { + auto_ping_interval: Some(MAX_INFLIGHT_TTL), + } + } +} + +#[async_trait] +impl ServiceInitializer for MonitorPeersInitializer { + async fn initialize(&mut self, context: ServiceInitializerContext) -> Result<(), ServiceInitializationError> { + debug!(target: LOG_TARGET, "Initializing Peer Monitoring Service"); + + let auto_ping_interval = max( + self.auto_ping_interval + .take() + .expect("Monitor peers service initialized more than once."), + MAX_INFLIGHT_TTL, + ); + + // Spawn the MonitorPeers service on the executor + context.spawn_when_ready(move |handles| async move { + let liveness = handles.expect_handle::(); + let network = handles.expect_handle::(); + + let service = + MonitorPeersService::new(network, liveness, handles.get_shutdown_signal(), auto_ping_interval); + service.run().await; + debug!(target: LOG_TARGET, "Monitor peers service has shut down"); + }); + + debug!(target: LOG_TARGET, "Monitor peers service initialized"); + Ok(()) + } +} diff --git a/base_layer/p2p/src/services/monitor_peers/service.rs b/base_layer/p2p/src/services/monitor_peers/service.rs new file mode 100644 index 0000000000..67c4a37d28 --- /dev/null +++ b/base_layer/p2p/src/services/monitor_peers/service.rs @@ -0,0 +1,315 @@ +// Copyright 2022, The Tari Project +// +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +// following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +// disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +// following disclaimer in the documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +// products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use std::collections::{HashMap, VecDeque}; + +use futures::pin_mut; +use log::*; +use tari_network::{identity::PeerId, Connection, ConnectionDirection, NetworkHandle, NetworkingService}; +use tari_shutdown::ShutdownSignal; +use tokio::{ + sync::broadcast::error::RecvError, + time::{self, Duration}, +}; + +use crate::services::{ + liveness::{LivenessEvent, LivenessHandle}, + monitor_peers::LOG_TARGET, +}; + +struct PeerLiveness { + vec: VecDeque, +} + +impl PeerLiveness { + pub fn new() -> Self { + Self { + vec: VecDeque::with_capacity(MAX_SIZE), + } + } + + pub fn push_pop(&mut self, item: T) { + if self.vec.len() == MAX_SIZE { + self.vec.pop_front(); + } + self.vec.push_back(item); + } + + pub fn iter(&self) -> std::collections::vec_deque::Iter { + self.vec.iter() + } +} + +struct Stats { + connected: bool, + responsive: bool, + loop_count: u64, +} + +struct PeerPingPong { + expected_nonce: u64, + received_nonce: Option, + node_id: PeerId, +} + +pub struct MonitorPeersService { + network: NetworkHandle, + liveness_handle: LivenessHandle, + shutdown_signal: ShutdownSignal, + auto_ping_interval: Duration, +} + +impl MonitorPeersService { + pub fn new( + network: NetworkHandle, + liveness_handle: LivenessHandle, + shutdown_signal: ShutdownSignal, + auto_ping_interval: Duration, + ) -> Self { + Self { + network, + liveness_handle, + shutdown_signal, + auto_ping_interval, + } + } + + /// Monitor the liveness of outbound peer connections and disconnect those that do not respond to pings + /// consecutively. The intent of the interval timer is to be significantly longer than the rate at which + /// metadata is requested from peers. + #[allow(clippy::too_many_lines)] + pub async fn run(mut self) { + let mut interval_timer = time::interval(self.auto_ping_interval * 10); + let liveness_events = self.liveness_handle.get_event_stream(); + pin_mut!(liveness_events); + + let mut peer_liveness_stats: HashMap> = HashMap::new(); + + let mut loop_count = 0u64; + loop { + loop_count += 1; + tokio::select! { + biased; + _ = self.shutdown_signal.wait() => { + break; + } + + _ = interval_timer.tick() => { + trace!(target: LOG_TARGET, "Starting monitor peers round (iter {})", loop_count); + let active_connections = match self.network.get_active_connections().await { + Ok(val) => val, + Err(e) => { + warn!(target: LOG_TARGET, "Failed to get active connections ({})", e); + continue; + }, + }; + let mut active_peer_connections = active_connections + .iter() + .filter(|p|p.is_node() && p.direction() == ConnectionDirection::Outbound) + .cloned() + .collect::>(); + if active_peer_connections.is_empty() { + trace!(target: LOG_TARGET, "No active connections found"); + continue; + } + let active_peer_node_ids = active_peer_connections + .iter() + .map(|p|*p.peer_id()) + .collect::>(); + + let known_peer_connections = peer_liveness_stats.keys().copied().collect::>(); + for peer_id in &known_peer_connections { + if !active_peer_node_ids.contains(peer_id) { + // Prior connections not connected now are considered inactive and unresponsive + peer_liveness_stats + .entry(*peer_id) + .and_modify(|item| item.push_pop( + Stats {connected: false, responsive: false, loop_count} + )); + } + } + for peer_id in &active_peer_node_ids { + if !known_peer_connections.contains(peer_id) { + // New connections are considered active and responsive + peer_liveness_stats.insert( *peer_id, PeerLiveness::new()); + } + } + + let mut peer_ping_pongs = match self.liveness_handle + .send_pings(active_peer_node_ids.clone()) + .await + { + Ok(nonces) => active_peer_node_ids + .iter() + .zip(nonces.iter()) + .map(|(node_id, &nonce)| PeerPingPong { + expected_nonce: nonce, + received_nonce: None, + node_id: *node_id, + }) + .collect::>(), + Err(e) => { + warn!(target: LOG_TARGET, "Failed to send pings to peers ({})", e); + continue; + }, + }; + + // Only listen for the expected pongs from the peers (ignore any other pongs) + let timeout_timer = time::sleep(self.auto_ping_interval); + tokio::pin!(timeout_timer); + loop { + tokio::select! { + biased; + _ = self.shutdown_signal.wait() => { + break; + } + + event = liveness_events.recv() => { + let event_str = format!("{:?}", event); + match event { + Ok(arc_event) => { + if let LivenessEvent::ReceivedPong(pong) = &*arc_event { + if let Some(ping_pong) = peer_ping_pongs.iter_mut().find(|p| p.expected_nonce == pong.nonce) { + ping_pong.received_nonce = Some(pong.nonce); + } + if peer_ping_pongs.iter().all(|p| p.received_nonce.is_some()) { + break; + } + } + }, + Err(RecvError::Closed) => { + return; + }, + Err(ref e) => { + debug!( + target: LOG_TARGET, + "Liveness event error: {:?} ({})", + event_str, e.to_string() + ); + }, + } + }, + + _ = &mut timeout_timer => { + trace!( + target: LOG_TARGET, + "Timed out waiting for pongs, received {} of {} (iter {})", + peer_ping_pongs.iter().filter(|p| p.received_nonce.is_some()).count(), + peer_ping_pongs.len(), + loop_count + ); + break; + }, + } + } + + // Compare nonces and close connections for peers that did not respond multiple times + self.update_stats_and_cull_unresponsive_connections( + &peer_ping_pongs, + &mut active_peer_connections, + &mut peer_liveness_stats, + loop_count + ).await; + }, + } + } + } + + async fn update_stats_and_cull_unresponsive_connections( + &mut self, + peer_ping_pongs: &[PeerPingPong], + active_peer_connections: &mut [Connection], + peer_liveness_stats: &mut HashMap>, + loop_count: u64, + ) { + let received_nonces_count = peer_ping_pongs.iter().filter(|p| p.received_nonce.is_some()).count(); + if received_nonces_count != peer_ping_pongs.len() { + trace!( + target: LOG_TARGET, + "Found {} of {} outbound base node peer connections that did not respond to pings", + peer_ping_pongs.len().saturating_sub(received_nonces_count), active_peer_connections.len() + ); + } + + let mut disconnect_peers = Vec::new(); + for &mut ref peer in active_peer_connections.iter_mut() { + if let Some(ping_pong) = peer_ping_pongs.iter().find(|p| &p.node_id == peer.peer_id()) { + if ping_pong.received_nonce.is_some() { + peer_liveness_stats.entry(*peer.peer_id()).and_modify(|item| { + item.push_pop(Stats { + connected: true, + responsive: true, + loop_count, + }) + }); + } else { + peer_liveness_stats.entry(*peer.peer_id()).and_modify(|item| { + item.push_pop(Stats { + connected: true, + responsive: false, + loop_count, + }) + }); + if let Some(stats) = peer_liveness_stats.get(peer.peer_id()) { + // Evaluate the last 3 entries in the stats + if stats + .iter() + .rev() + .take(3) + .filter(|s| s.connected && !s.responsive) + .count() >= + 3 + { + disconnect_peers.push(peer.clone()); + } else { + trace!( + target: LOG_TARGET, + "Peer {} stats - (iter, conn, resp) {:?}", + peer.peer_id(), + stats.iter().map(|s|(s.loop_count, s.connected, s.responsive)).collect::>(), + ); + } + } + } + } + } + + for peer in disconnect_peers { + if let Some(stats) = peer_liveness_stats.get(peer.peer_id()) { + debug!( + target: LOG_TARGET, + "Disconnecting {} as the peer is no longer responsive - (iter, conn, resp) {:?}", + peer.peer_id(), + stats.iter().map(|s|(s.loop_count, s.connected, s.responsive)).collect::>(), + ); + if let Err(e) = self.network.disconnect_peer(peer.peer_id).await { + warn!( + target: LOG_TARGET, + "Error while attempting to disconnect peer {}: {}", peer.peer_id(), e + ); + } + peer_liveness_stats.remove(peer.peer_id()); + trace!(target: LOG_TARGET, "Disconnected {} (iter, {})", peer.peer_id(), loop_count); + } + } + } +} diff --git a/network/core/src/connection.rs b/network/core/src/connection.rs index a142f8fdc8..f65f7e56fc 100644 --- a/network/core/src/connection.rs +++ b/network/core/src/connection.rs @@ -53,4 +53,10 @@ impl Connection { pub fn is_wallet_user_agent(&self) -> bool { self.user_agent.as_ref().map_or(false, |x| x.contains("wallet")) } + + pub fn is_node(&self) -> bool { + self.supported_protocols + .iter() + .any(|p| p.as_ref().contains("/tari/mempool")) + } } diff --git a/network/core/src/event.rs b/network/core/src/event.rs index 545138ce42..3b43cb6924 100644 --- a/network/core/src/event.rs +++ b/network/core/src/event.rs @@ -25,7 +25,7 @@ pub enum NetworkEvent { }, } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum ConnectionDirection { Inbound, Outbound, From c21e656700afede61bd5aba6703ad3d6c43808dd Mon Sep 17 00:00:00 2001 From: Hansie Odendaal Date: Thu, 28 Nov 2024 08:35:15 +0200 Subject: [PATCH 15/19] Merge development PRs: #6673, #6672, #6688, #6694 --- .github/workflows/build_binaries.yml | 2 +- .github/workflows/publish_test_results_ci.yml | 2 +- Cargo.lock | 78 +++++++++---------- Cargo.toml | 2 +- README.md | 4 +- applications/minotari_app_grpc/Cargo.toml | 4 +- .../minotari_app_utilities/Cargo.toml | 4 +- .../minotari_console_wallet/Cargo.toml | 6 +- .../minotari_ledger_wallet/common/Cargo.toml | 2 +- .../minotari_ledger_wallet/comms/Cargo.toml | 2 +- .../minotari_ledger_wallet/wallet/Cargo.lock | 4 +- .../minotari_ledger_wallet/wallet/Cargo.toml | 4 +- .../minotari_ledger_wallet/wallet/README.md | 7 +- .../minotari_ledger_wallet/wallet/src/main.rs | 5 +- .../minotari_merge_mining_proxy/Cargo.toml | 4 +- applications/minotari_miner/Cargo.toml | 2 +- applications/minotari_node/Cargo.toml | 6 +- base_layer/chat_ffi/Cargo.toml | 2 +- base_layer/common_types/Cargo.toml | 4 +- base_layer/contacts/Cargo.toml | 18 +++-- .../contacts/src/chat_client/Cargo.toml | 2 +- base_layer/core/Cargo.toml | 30 +++---- base_layer/core/src/blocks/genesis_block.rs | 9 +++ .../core/src/transactions/aggregated_body.rs | 32 ++++++++ base_layer/key_manager/Cargo.toml | 8 +- base_layer/mmr/Cargo.toml | 2 +- base_layer/p2p/Cargo.toml | 14 ++-- base_layer/service_framework/Cargo.toml | 4 +- base_layer/tari_mining_helper_ffi/Cargo.toml | 6 +- base_layer/wallet/Cargo.toml | 24 +++--- base_layer/wallet_ffi/Cargo.toml | 4 +- changelog-development.md | 18 +++++ changelog-nextnet.md | 19 +++++ common/Cargo.toml | 6 +- common/tari_features/Cargo.toml | 2 +- common_sqlite/Cargo.toml | 2 +- comms/core/Cargo.toml | 10 +-- comms/dht/Cargo.toml | 16 ++-- comms/rpc_macros/Cargo.toml | 2 +- hashing/Cargo.toml | 2 +- infrastructure/derive/Cargo.toml | 2 +- infrastructure/libtor/Cargo.toml | 2 +- infrastructure/max_size/Cargo.toml | 2 +- infrastructure/metrics/Cargo.toml | 2 +- infrastructure/shutdown/Cargo.toml | 2 +- infrastructure/storage/Cargo.toml | 2 +- infrastructure/tari_script/Cargo.toml | 2 +- infrastructure/test_utils/Cargo.toml | 5 +- package-lock.json | 2 +- 49 files changed, 244 insertions(+), 151 deletions(-) diff --git a/.github/workflows/build_binaries.yml b/.github/workflows/build_binaries.yml index e479f559bc..e4d0ceff21 100644 --- a/.github/workflows/build_binaries.yml +++ b/.github/workflows/build_binaries.yml @@ -122,7 +122,7 @@ jobs: run: | BRANCH_NAME=$(echo "${GITHUB_REF}" | sed 's|refs/heads/||') if [[ "${BRANCH_NAME}" == "build-bins-nextnet"* ]]; then - source buildtools/multinet_envs.sh "v1.8.0-rc.0" + source buildtools/multinet_envs.sh "v1.9.0-rc.0" else source buildtools/multinet_envs.sh ${{ env.GHA_NETWORK }} fi diff --git a/.github/workflows/publish_test_results_ci.yml b/.github/workflows/publish_test_results_ci.yml index 0ab37a69d5..9eb60d8cef 100644 --- a/.github/workflows/publish_test_results_ci.yml +++ b/.github/workflows/publish_test_results_ci.yml @@ -48,7 +48,7 @@ jobs: files: "artifacts/**/*.xml" - name: Publish Test Report 2 - uses: mikepenz/action-junit-report@v4 + uses: mikepenz/action-junit-report@v5 if: always() with: report_paths: "artifacts/**/*.xml" diff --git a/Cargo.lock b/Cargo.lock index 2e2a6318a1..a09ded8bf7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3903,7 +3903,7 @@ dependencies = [ [[package]] name = "libp2p-messaging" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "async-trait", "futures-bounded", @@ -4060,7 +4060,7 @@ dependencies = [ [[package]] name = "libp2p-substream" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "libp2p", "smallvec 1.13.2", @@ -4469,7 +4469,7 @@ dependencies = [ [[package]] name = "minotari_app_grpc" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "argon2", "base64 0.13.1", @@ -4498,7 +4498,7 @@ dependencies = [ [[package]] name = "minotari_app_utilities" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "clap 3.2.25", "dialoguer 0.10.4", @@ -4518,7 +4518,7 @@ dependencies = [ [[package]] name = "minotari_console_wallet" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "blake2", "chrono", @@ -4572,14 +4572,14 @@ dependencies = [ [[package]] name = "minotari_ledger_wallet_common" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "bs58 0.5.1", ] [[package]] name = "minotari_ledger_wallet_comms" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "borsh", "dialoguer 0.11.0", @@ -4601,7 +4601,7 @@ dependencies = [ [[package]] name = "minotari_merge_mining_proxy" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "anyhow", "bincode", @@ -4643,7 +4643,7 @@ dependencies = [ [[package]] name = "minotari_miner" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "base64 0.13.1", "borsh", @@ -4680,7 +4680,7 @@ dependencies = [ [[package]] name = "minotari_mining_helper_ffi" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "borsh", "cbindgen", @@ -4698,7 +4698,7 @@ dependencies = [ [[package]] name = "minotari_node" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "anyhow", "async-trait", @@ -4754,7 +4754,7 @@ dependencies = [ [[package]] name = "minotari_wallet" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "argon2", "async-trait", @@ -4806,7 +4806,7 @@ dependencies = [ [[package]] name = "minotari_wallet_ffi" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "borsh", "cbindgen", @@ -6221,7 +6221,7 @@ dependencies = [ [[package]] name = "proto_builder" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "prost-build 0.13.3", "sha2 0.10.8", @@ -7686,7 +7686,7 @@ dependencies = [ [[package]] name = "tari_common" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "anyhow", "config", @@ -7712,7 +7712,7 @@ dependencies = [ [[package]] name = "tari_common_sqlite" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "diesel", "diesel_migrations", @@ -7726,7 +7726,7 @@ dependencies = [ [[package]] name = "tari_common_types" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "base64 0.21.5", "bitflags 2.6.0", @@ -7751,7 +7751,7 @@ dependencies = [ [[package]] name = "tari_comms" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "anyhow", "async-trait", @@ -7801,7 +7801,7 @@ dependencies = [ [[package]] name = "tari_comms_dht" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "anyhow", "bitflags 2.6.0", @@ -7845,7 +7845,7 @@ dependencies = [ [[package]] name = "tari_comms_rpc_macros" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "futures 0.3.30", "proc-macro2", @@ -7860,7 +7860,7 @@ dependencies = [ [[package]] name = "tari_contacts" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "chrono", "diesel", @@ -7895,7 +7895,7 @@ dependencies = [ [[package]] name = "tari_core" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "async-trait", "bincode", @@ -7997,11 +7997,11 @@ dependencies = [ [[package]] name = "tari_features" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" [[package]] name = "tari_hashing" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "blake2", "borsh", @@ -8057,7 +8057,7 @@ dependencies = [ [[package]] name = "tari_key_manager" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "argon2", "async-trait", @@ -8092,7 +8092,7 @@ dependencies = [ [[package]] name = "tari_libtor" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "derivative", "libtor", @@ -8105,7 +8105,7 @@ dependencies = [ [[package]] name = "tari_max_size" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "borsh", "serde", @@ -8115,7 +8115,7 @@ dependencies = [ [[package]] name = "tari_metrics" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "anyhow", "futures 0.3.30", @@ -8130,7 +8130,7 @@ dependencies = [ [[package]] name = "tari_mmr" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "bincode", "blake2", @@ -8148,7 +8148,7 @@ dependencies = [ [[package]] name = "tari_network" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "anyhow", "humantime 2.1.0", @@ -8165,7 +8165,7 @@ dependencies = [ [[package]] name = "tari_p2p" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "anyhow", "clap 3.2.25", @@ -8202,7 +8202,7 @@ dependencies = [ [[package]] name = "tari_rpc_framework" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "async-trait", "bitflags 2.6.0", @@ -8227,7 +8227,7 @@ dependencies = [ [[package]] name = "tari_rpc_macros" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "proc-macro2", "quote", @@ -8236,7 +8236,7 @@ dependencies = [ [[package]] name = "tari_script" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "blake2", "borsh", @@ -8254,7 +8254,7 @@ dependencies = [ [[package]] name = "tari_service_framework" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "anyhow", "async-trait", @@ -8271,7 +8271,7 @@ dependencies = [ [[package]] name = "tari_shutdown" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "futures 0.3.30", "tokio", @@ -8279,7 +8279,7 @@ dependencies = [ [[package]] name = "tari_storage" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "bincode", "lmdb-zero", @@ -8292,7 +8292,7 @@ dependencies = [ [[package]] name = "tari_swarm" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "libp2p", "libp2p-messaging", @@ -8303,7 +8303,7 @@ dependencies = [ [[package]] name = "tari_test_utils" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "futures 0.3.30", "futures-test", diff --git a/Cargo.toml b/Cargo.toml index 986ce712b2..27696686c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ authors = ["The Tari Development Community"] repository = "https://github.com/tari-project/tari" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2021" [workspace] diff --git a/README.md b/README.md index 6c4f93c83b..df55d32d82 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,8 @@ The recommended running versions of each network are: | Network | Version | |-----------|----------------| | Stagenet | 1.0.0-alpha.0a | -| Nextnet | 1.8.0-rc.0 | -| Esmeralda | 1.8.0-pre.0 | +| Nextnet | 1.9.0-rc.0 | +| Esmeralda | 1.9.0-pre.0 | For more detail about versioning, see [Release Ideology](https://github.com/tari-project/tari/blob/development/docs/src/branching_releases.md). diff --git a/applications/minotari_app_grpc/Cargo.toml b/applications/minotari_app_grpc/Cargo.toml index 61783c52f6..70b784f60d 100644 --- a/applications/minotari_app_grpc/Cargo.toml +++ b/applications/minotari_app_grpc/Cargo.toml @@ -4,7 +4,7 @@ authors = ["The Tari Development Community"] description = "This crate is to provide a single source for all cross application grpc files and conversions to and from tari::core" repository = "https://github.com/tari-project/tari" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2021" [dependencies] @@ -32,7 +32,7 @@ tonic = { version = "0.12.3", features = ["tls"] } zeroize = "1" [build-dependencies] -tari_features = { path = "../../common/tari_features", version = "1.8.0-pre.0" } +tari_features = { path = "../../common/tari_features", version = "1.9.0-pre.0" } tonic-build = "0.12.3" [package.metadata.cargo-machete] diff --git a/applications/minotari_app_utilities/Cargo.toml b/applications/minotari_app_utilities/Cargo.toml index 300a8150a4..b1bc43ad6d 100644 --- a/applications/minotari_app_utilities/Cargo.toml +++ b/applications/minotari_app_utilities/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minotari_app_utilities" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" authors = ["The Tari Development Community"] edition = "2018" license = "BSD-3-Clause" @@ -26,7 +26,7 @@ tari_common = { path = "../../common", features = [ "build", "static-application-info", ] } -tari_features = { path = "../../common/tari_features", version = "1.8.0-pre.0" } +tari_features = { path = "../../common/tari_features", version = "1.9.0-pre.0" } [features] miner_input = ["minotari_app_grpc"] diff --git a/applications/minotari_console_wallet/Cargo.toml b/applications/minotari_console_wallet/Cargo.toml index 2535a971d0..fa64928743 100644 --- a/applications/minotari_console_wallet/Cargo.toml +++ b/applications/minotari_console_wallet/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minotari_console_wallet" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" authors = ["The Tari Development Community"] edition = "2018" license = "BSD-3-Clause" @@ -9,7 +9,7 @@ license = "BSD-3-Clause" tari_network = { workspace = true } minotari_app_grpc = { path = "../minotari_app_grpc" } minotari_app_utilities = { path = "../minotari_app_utilities" } -minotari_ledger_wallet_comms = { path = "../../applications/minotari_ledger_wallet/comms", version = "1.8.0-pre.0", optional = true } +minotari_ledger_wallet_comms = { path = "../../applications/minotari_ledger_wallet/comms", version = "1.9.0-pre.0", optional = true } tari_common = { path = "../../common" } tari_common_types = { path = "../../base_layer/common_types" } tari_contacts = { path = "../../base_layer/contacts" } @@ -82,7 +82,7 @@ default-features = false features = ["crossterm"] [build-dependencies] -tari_features = { path = "../../common/tari_features", version = "1.8.0-pre.0" } +tari_features = { path = "../../common/tari_features", version = "1.9.0-pre.0" } [features] default = ["ledger"] diff --git a/applications/minotari_ledger_wallet/common/Cargo.toml b/applications/minotari_ledger_wallet/common/Cargo.toml index f56716b331..fb3a371c7d 100644 --- a/applications/minotari_ledger_wallet/common/Cargo.toml +++ b/applications/minotari_ledger_wallet/common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minotari_ledger_wallet_common" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" authors = ["The Tari Development Community"] license = "BSD-3-Clause" edition = "2021" diff --git a/applications/minotari_ledger_wallet/comms/Cargo.toml b/applications/minotari_ledger_wallet/comms/Cargo.toml index 5da4718c90..3b710a1011 100644 --- a/applications/minotari_ledger_wallet/comms/Cargo.toml +++ b/applications/minotari_ledger_wallet/comms/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minotari_ledger_wallet_comms" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" authors = ["The Tari Development Community"] license = "BSD-3-Clause" edition = "2021" diff --git a/applications/minotari_ledger_wallet/wallet/Cargo.lock b/applications/minotari_ledger_wallet/wallet/Cargo.lock index 90dbf6694a..b46bcd7b55 100644 --- a/applications/minotari_ledger_wallet/wallet/Cargo.lock +++ b/applications/minotari_ledger_wallet/wallet/Cargo.lock @@ -432,7 +432,7 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "minotari_ledger_wallet" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "blake2", "borsh", @@ -735,7 +735,7 @@ dependencies = [ [[package]] name = "tari_hashing" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" dependencies = [ "borsh", "digest", diff --git a/applications/minotari_ledger_wallet/wallet/Cargo.toml b/applications/minotari_ledger_wallet/wallet/Cargo.toml index 3853bca4fa..f1374485cc 100644 --- a/applications/minotari_ledger_wallet/wallet/Cargo.toml +++ b/applications/minotari_ledger_wallet/wallet/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minotari_ledger_wallet" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" authors = ["The Tari Development Community"] license = "BSD-3-Clause" edition = "2021" @@ -9,7 +9,7 @@ edition = "2021" tari_crypto = { version = "0.21.0", default-features = false, features = [ "borsh", ] } -tari_hashing = { path = "../../../hashing", version = "1.8.0-pre.0" } +tari_hashing = { path = "../../../hashing", version = "1.9.0-pre.0" } minotari_ledger_wallet_common = { path = "../common" } diff --git a/applications/minotari_ledger_wallet/wallet/README.md b/applications/minotari_ledger_wallet/wallet/README.md index aa28371822..8df303142a 100644 --- a/applications/minotari_ledger_wallet/wallet/README.md +++ b/applications/minotari_ledger_wallet/wallet/README.md @@ -72,13 +72,18 @@ For more information see [LedgerCTL](https://github.com/LedgerHQ/ledgerctl). It is recommended to build the Ledger application via the official `ledger-app-builder` Docker image, as the Docker image is properly setup, supported and always kept up to date. +**Note:** Before proceeding, manually delete any ledger docker images from Docker Desktop as those will not be updated +automatically: +- Select he _Images_ tab/menu item +- Select the checkbox next to _ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder_ and then press _Delete_. + ### Option 1: Using Docker Ensure Docker Desktop is installed and running on your machine. The following command has to be run from the root of the Tari repository. -Replace ```{TARGET}``` with the appropriate value (e.g., `nanosplus`, `nanos`, etc.). +Replace ```{TARGET}``` with the appropriate value (e.g., `nanosplus`, `stax`, etc.). Compiled resources will be found in `applications/minotari_ledger_wallet/wallet/target/{TARGET}/release` diff --git a/applications/minotari_ledger_wallet/wallet/src/main.rs b/applications/minotari_ledger_wallet/wallet/src/main.rs index fece1eccd1..d58d130126 100644 --- a/applications/minotari_ledger_wallet/wallet/src/main.rs +++ b/applications/minotari_ledger_wallet/wallet/src/main.rs @@ -229,7 +229,7 @@ extern "C" fn sample_main() { continue; }; - let status = match handle_apdu(&mut comm, ins, &mut offset_ctx) { + let _status = match handle_apdu(&mut comm, ins, &mut offset_ctx) { Ok(()) => { comm.reply_ok(); AppSW::Ok @@ -239,8 +239,9 @@ extern "C" fn sample_main() { sw }, }; + #[cfg(any(target_os = "stax", target_os = "flex"))] - show_status_and_home_if_needed(&ins, &status, &mut offset_ctx, &mut home); + show_status_and_home_if_needed(&ins, &_status, &mut offset_ctx, &mut home); } } diff --git a/applications/minotari_merge_mining_proxy/Cargo.toml b/applications/minotari_merge_mining_proxy/Cargo.toml index 8a8fad2943..792c774ec4 100644 --- a/applications/minotari_merge_mining_proxy/Cargo.toml +++ b/applications/minotari_merge_mining_proxy/Cargo.toml @@ -4,7 +4,7 @@ authors = ["The Tari Development Community"] description = "The Tari merge mining proxy for xmrig" repository = "https://github.com/tari-project/tari" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [features] @@ -55,7 +55,7 @@ url = "2.1.1" scraper = "0.19.0" [build-dependencies] -tari_features = { path = "../../common/tari_features", version = "1.8.0-pre.0" } +tari_features = { path = "../../common/tari_features", version = "1.9.0-pre.0" } [dev-dependencies] hyper = { version ="0.14.12", features = ["full"] } diff --git a/applications/minotari_miner/Cargo.toml b/applications/minotari_miner/Cargo.toml index 3a06d95961..17a41b8cb9 100644 --- a/applications/minotari_miner/Cargo.toml +++ b/applications/minotari_miner/Cargo.toml @@ -4,7 +4,7 @@ authors = ["The Tari Development Community"] description = "The tari miner implementation" repository = "https://github.com/tari-project/tari" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [dependencies] diff --git a/applications/minotari_node/Cargo.toml b/applications/minotari_node/Cargo.toml index 6db1c37c68..d7cd535c3d 100644 --- a/applications/minotari_node/Cargo.toml +++ b/applications/minotari_node/Cargo.toml @@ -4,7 +4,7 @@ authors = ["The Tari Development Community"] description = "The tari full base node implementation" repository = "https://github.com/tari-project/tari" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [dependencies] @@ -25,7 +25,7 @@ tari_shutdown = { path = "../../infrastructure/shutdown" } tari_utilities = { version = "0.8" } tari_key_manager = { path = "../../base_layer/key_manager", features = [ "key_manager_service", -], version = "1.8.0-pre.0" } +], version = "1.9.0-pre.0" } anyhow = "1.0.53" async-trait = "0.1.52" @@ -75,7 +75,7 @@ metrics = ["tari_metrics"] safe = [] [build-dependencies] -tari_features = { path = "../../common/tari_features", version = "1.8.0-pre.0" } +tari_features = { path = "../../common/tari_features", version = "1.9.0-pre.0" } [package.metadata.cargo-machete] ignored = [ diff --git a/base_layer/chat_ffi/Cargo.toml b/base_layer/chat_ffi/Cargo.toml index 14c14dea2e..3ba31ca33b 100644 --- a/base_layer/chat_ffi/Cargo.toml +++ b/base_layer/chat_ffi/Cargo.toml @@ -3,7 +3,7 @@ name = "minotari_chat_ffi" authors = ["The Tari Development Community"] description = "Tari cryptocurrency chat C FFI bindings" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [dependencies] diff --git a/base_layer/common_types/Cargo.toml b/base_layer/common_types/Cargo.toml index 081e797312..b72b988011 100644 --- a/base_layer/common_types/Cargo.toml +++ b/base_layer/common_types/Cargo.toml @@ -3,13 +3,13 @@ name = "tari_common_types" authors = ["The Tari Development Community"] description = "Tari cryptocurrency common types" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [dependencies] tari_crypto = { version = "0.21.0" } tari_utilities = { version = "0.8" } -tari_common = { path = "../../common", version = "1.8.0-pre.0" } +tari_common = { path = "../../common", version = "1.9.0-pre.0" } minotari_ledger_wallet_common = { path = "../../applications/minotari_ledger_wallet/common" } chacha20poly1305 = "0.10.1" bitflags = { version = "2.4", features = ["serde"] } diff --git a/base_layer/contacts/Cargo.toml b/base_layer/contacts/Cargo.toml index b2d0743027..680b484817 100644 --- a/base_layer/contacts/Cargo.toml +++ b/base_layer/contacts/Cargo.toml @@ -3,21 +3,22 @@ name = "tari_contacts" authors = ["The Tari Development Community"] description = "Tari contacts library" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [dependencies] +tari_common = { path = "../../common", version = "1.9.0-pre.0" } +tari_common_sqlite = { path = "../../common_sqlite", version = "1.9.0-pre.0" } +tari_common_types = { path = "../../base_layer/common_types", version = "1.9.0-pre.0" } tari_network = { workspace = true } -tari_common = { path = "../../common", version = "1.8.0-pre.0" } -tari_common_sqlite = { path = "../../common_sqlite", version = "1.8.0-pre.0" } -tari_common_types = { path = "../../base_layer/common_types", version = "1.8.0-pre.0" } + tari_crypto = { version = "0.21.0" } tari_max_size = { path = "../../infrastructure/max_size" } tari_p2p = { path = "../p2p", features = [ "auto-update", -], version = "1.8.0-pre.0" } -tari_service_framework = { path = "../service_framework", version = "1.8.0-pre.0" } -tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.8.0-pre.0" } +], version = "1.9.0-pre.0" } +tari_service_framework = { path = "../service_framework", version = "1.9.0-pre.0" } +tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.9.0-pre.0" } tari_utilities = { version = "0.8" } chrono = { version = "0.4.19", default-features = false, features = ["serde"] } @@ -47,6 +48,9 @@ tari_comms_dht = { path = "../../comms/dht", features = ["test-mocks"] } tari_test_utils = { path = "../../infrastructure/test_utils" } tempfile = "3.1.0" +[build-dependencies] +tari_common = { path = "../../common", version = "1.9.0-pre.0" } + [package.metadata.cargo-machete] ignored = [ "prost", diff --git a/base_layer/contacts/src/chat_client/Cargo.toml b/base_layer/contacts/src/chat_client/Cargo.toml index aa29467f23..643bbad9f7 100644 --- a/base_layer/contacts/src/chat_client/Cargo.toml +++ b/base_layer/contacts/src/chat_client/Cargo.toml @@ -3,7 +3,7 @@ name = "tari_chat_client" authors = ["The Tari Development Community"] description = "Tari cucumber chat client" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" diff --git a/base_layer/core/Cargo.toml b/base_layer/core/Cargo.toml index 79c37dd0ff..b6fde6b493 100644 --- a/base_layer/core/Cargo.toml +++ b/base_layer/core/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/tari-project/tari" homepage = "https://tari.com" readme = "README.md" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2021" [features] @@ -27,27 +27,28 @@ ledger = ["minotari_ledger_wallet_comms"] metrics = ["tari_metrics"] [dependencies] -minotari_ledger_wallet_comms = { path = "../../applications/minotari_ledger_wallet/comms", version = "1.8.0-pre.0", optional = true } -tari_common = { path = "../../common", version = "1.8.0-pre.0" } -tari_common_types = { path = "../../base_layer/common_types", version = "1.8.0-pre.0" } +minotari_ledger_wallet_comms = { path = "../../applications/minotari_ledger_wallet/comms", version = "1.9.0-pre.0", optional = true } +tari_common = { path = "../../common", version = "1.9.0-pre.0" } +tari_common_types = { path = "../../base_layer/common_types", version = "1.9.0-pre.0" } + libp2p-substream = { workspace = true } tari_network = { workspace = true } tari_rpc_framework = { workspace = true } tari_rpc_macros = { workspace = true } tari_crypto = { version = "0.21.0", features = ["borsh"] } tari_max_size = { path = "../../infrastructure/max_size" } -tari_metrics = { path = "../../infrastructure/metrics", optional = true, version = "1.8.0-pre.0" } -tari_mmr = { path = "../../base_layer/mmr", optional = true, version = "1.8.0-pre.0" } -tari_p2p = { path = "../../base_layer/p2p", version = "1.8.0-pre.0" } -tari_script = { path = "../../infrastructure/tari_script", version = "1.8.0-pre.0" } -tari_service_framework = { path = "../service_framework", version = "1.8.0-pre.0" } -tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.8.0-pre.0" } -tari_storage = { path = "../../infrastructure/storage", version = "1.8.0-pre.0" } -tari_test_utils = { path = "../../infrastructure/test_utils", version = "1.8.0-pre.0" } +tari_metrics = { path = "../../infrastructure/metrics", optional = true, version = "1.9.0-pre.0" } +tari_mmr = { path = "../../base_layer/mmr", optional = true, version = "1.9.0-pre.0" } +tari_p2p = { path = "../../base_layer/p2p", version = "1.9.0-pre.0" } +tari_script = { path = "../../infrastructure/tari_script", version = "1.9.0-pre.0" } +tari_service_framework = { path = "../service_framework", version = "1.9.0-pre.0" } +tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.9.0-pre.0" } +tari_storage = { path = "../../infrastructure/storage", version = "1.9.0-pre.0" } +tari_test_utils = { path = "../../infrastructure/test_utils", version = "1.9.0-pre.0" } tari_utilities = { version = "0.8", features = ["borsh"] } tari_key_manager = { path = "../key_manager", features = [ "key_manager_service", -], version = "1.8.0-pre.0" } +], version = "1.9.0-pre.0" } tari_common_sqlite = { path = "../../common_sqlite" } tari_hashing = { path = "../../hashing" } @@ -110,7 +111,8 @@ quickcheck = "1.0" serial_test = "0.5" [build-dependencies] -tari_features = { path = "../../common/tari_features", version = "1.8.0-pre.0" } +tari_features = { path = "../../common/tari_features", version = "1.9.0-pre.0" } + [[bench]] name = "mempool" diff --git a/base_layer/core/src/blocks/genesis_block.rs b/base_layer/core/src/blocks/genesis_block.rs index 8818206ca2..a75767e192 100644 --- a/base_layer/core/src/blocks/genesis_block.rs +++ b/base_layer/core/src/blocks/genesis_block.rs @@ -751,6 +751,15 @@ mod test { block.header().block_output_mr.to_vec().to_hex(), ); } else { + let coinbases = block.block().body.get_coinbase_outputs().into_iter().cloned().collect(); + let normal_output_mr = block.block().body.calculate_header_normal_output_mr().unwrap(); + assert_eq!( + AggregateBody::calculate_header_block_output_mr(normal_output_mr, &coinbases) + .unwrap() + .to_vec() + .to_hex(), + block.header().block_output_mr.to_vec().to_hex(), + ); assert_eq!( block_output_mr_hash_from_pruned_mmr(&block_output_mmr) .unwrap() diff --git a/base_layer/core/src/transactions/aggregated_body.rs b/base_layer/core/src/transactions/aggregated_body.rs index ecdafcde2c..9e092063ea 100644 --- a/base_layer/core/src/transactions/aggregated_body.rs +++ b/base_layer/core/src/transactions/aggregated_body.rs @@ -23,12 +23,18 @@ use std::{ cmp::max, fmt::{Display, Error, Formatter}, }; +#[cfg(feature = "base_node")] +use std::convert::TryFrom; use borsh::{BorshDeserialize, BorshSerialize}; use log::*; use serde::{Deserialize, Serialize}; use tari_common_types::types::{ComAndPubSignature, Commitment, PrivateKey}; +#[cfg(feature = "base_node")] +use tari_common_types::types::FixedHash; use tari_crypto::commitment::HomomorphicCommitmentFactory; +#[cfg(feature = "base_node")] +use tari_mmr::pruned_hashset::PrunedHashSet; use tari_utilities::hex::Hex; use crate::transactions::{ @@ -45,6 +51,8 @@ use crate::transactions::{ }, weight::TransactionWeight, }; +#[cfg(feature = "base_node")] +use crate::{block_output_mr_hash_from_pruned_mmr, MrHashError, PrunedOutputMmr}; pub const LOG_TARGET: &str = "c::tx::aggregated_body"; @@ -446,6 +454,30 @@ impl AggregateBody { .iter() .any(|k| k.features.output_type == OutputType::Coinbase) } + + #[cfg(feature = "base_node")] + pub fn calculate_header_block_output_mr( + normal_output_mr: FixedHash, + coinbases: &Vec, + ) -> Result { + let mut block_output_mmr = PrunedOutputMmr::new(PrunedHashSet::default()); + for o in coinbases { + block_output_mmr.push(o.hash().to_vec())?; + } + block_output_mmr.push(normal_output_mr.to_vec())?; + block_output_mr_hash_from_pruned_mmr(&block_output_mmr) + } + + #[cfg(feature = "base_node")] + pub fn calculate_header_normal_output_mr(&self) -> Result { + let mut normal_output_mmr = PrunedOutputMmr::new(PrunedHashSet::default()); + for o in self.outputs() { + if !o.features.is_coinbase() { + normal_output_mmr.push(o.hash().to_vec())?; + } + } + Ok(FixedHash::try_from(normal_output_mmr.get_merkle_root()?)?) + } } impl PartialEq for AggregateBody { diff --git a/base_layer/key_manager/Cargo.toml b/base_layer/key_manager/Cargo.toml index 99c6298579..b8bef7c8b3 100644 --- a/base_layer/key_manager/Cargo.toml +++ b/base_layer/key_manager/Cargo.toml @@ -4,7 +4,7 @@ authors = ["The Tari Development Community"] description = "Tari cryptocurrency wallet key management" repository = "https://github.com/tari-project/tari" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2021" [lib] @@ -13,9 +13,9 @@ crate-type = ["lib", "cdylib"] [dependencies] tari_crypto = { version = "0.21.0" } tari_utilities = { version = "0.8" } -tari_common_sqlite = { path = "../../common_sqlite", version = "1.8.0-pre.0" } -tari_common_types = { path = "../../base_layer/common_types", version = "1.8.0-pre.0" } -tari_service_framework = { path = "../service_framework", version = "1.8.0-pre.0" } +tari_common_sqlite = { path = "../../common_sqlite", version = "1.9.0-pre.0" } +tari_common_types = { path = "../../base_layer/common_types", version = "1.9.0-pre.0" } +tari_service_framework = { path = "../service_framework", version = "1.9.0-pre.0" } async-trait = { version = "0.1.50" } chrono = { version = "0.4.19", default-features = false, features = ["serde"] } diff --git a/base_layer/mmr/Cargo.toml b/base_layer/mmr/Cargo.toml index 6159052eab..27c32cb817 100644 --- a/base_layer/mmr/Cargo.toml +++ b/base_layer/mmr/Cargo.toml @@ -4,7 +4,7 @@ authors = ["The Tari Development Community"] description = "A Merkle Mountain Range implementation" repository = "https://github.com/tari-project/tari" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [features] diff --git a/base_layer/p2p/Cargo.toml b/base_layer/p2p/Cargo.toml index 1cfd4c53b7..fcc8e868a7 100644 --- a/base_layer/p2p/Cargo.toml +++ b/base_layer/p2p/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tari_p2p" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" authors = ["The Tari Development community"] description = "Tari base layer-specific peer-to-peer communication features" repository = "https://github.com/tari-project/tari" @@ -10,12 +10,14 @@ license = "BSD-3-Clause" edition = "2021" [dependencies] +tari_common = { path = "../../common", version = "1.9.0-pre.0" } tari_network = { workspace = true } -tari_common = { path = "../../common", version = "1.8.0-pre.0" } -tari_common_types = { path = "../common_types", version = "1.8.0-pre.0" } + +tari_common_types = { path = "../common_types", version = "1.9.0-pre.0" } tari_crypto = { version = "0.21.0" } -tari_service_framework = { path = "../service_framework", version = "1.8.0-pre.0" } -tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.8.0-pre.0" } +tari_service_framework = { path = "../service_framework", version = "1.9.0-pre.0" } +tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.9.0-pre.0" } + tari_utilities = { version = "0.8" } anyhow = "1.0.53" @@ -49,7 +51,7 @@ tempfile = "3.1.0" [build-dependencies] tari_common = { path = "../../common", features = [ "build", -], version = "1.8.0-pre.0" } +], version = "1.9.0-pre.0" } [features] test-mocks = [] diff --git a/base_layer/service_framework/Cargo.toml b/base_layer/service_framework/Cargo.toml index 21a8a95409..25a364c2d9 100644 --- a/base_layer/service_framework/Cargo.toml +++ b/base_layer/service_framework/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tari_service_framework" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" authors = ["The Tari Development Community"] description = "The Tari communication stack service framework" repository = "https://github.com/tari-project/tari" @@ -10,7 +10,7 @@ license = "BSD-3-Clause" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.8.0-pre.0" } +tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.9.0-pre.0" } anyhow = "1.0.53" async-trait = "0.1.50" diff --git a/base_layer/tari_mining_helper_ffi/Cargo.toml b/base_layer/tari_mining_helper_ffi/Cargo.toml index 87dc9a5077..ccf8a5ea8f 100644 --- a/base_layer/tari_mining_helper_ffi/Cargo.toml +++ b/base_layer/tari_mining_helper_ffi/Cargo.toml @@ -3,7 +3,7 @@ name = "minotari_mining_helper_ffi" authors = ["The Tari Development Community"] description = "Tari cryptocurrency miningcore C FFI bindings" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [dependencies] @@ -14,7 +14,7 @@ tari_core = { path = "../core", default-features = false, features = [ "base_node_proto", "base_node", ] } -tari_common_types = { path = "../../base_layer/common_types", version = "1.8.0-pre.0" } +tari_common_types = { path = "../../base_layer/common_types", version = "1.9.0-pre.0" } tari_utilities = { version = "0.8" } libc = "0.2.65" thiserror = "1.0.26" @@ -26,7 +26,7 @@ tari_core = { path = "../core", features = ["transactions", "base_node"] } rand = "0.8" [build-dependencies] -tari_features = { path = "../../common/tari_features", version = "1.8.0-pre.0" } +tari_features = { path = "../../common/tari_features", version = "1.9.0-pre.0" } cbindgen = "0.24.3" tari_common = { path = "../../common", features = [ "build", diff --git a/base_layer/wallet/Cargo.toml b/base_layer/wallet/Cargo.toml index 413f16556f..95625e36b4 100644 --- a/base_layer/wallet/Cargo.toml +++ b/base_layer/wallet/Cargo.toml @@ -3,32 +3,32 @@ name = "minotari_wallet" authors = ["The Tari Development Community"] description = "Tari cryptocurrency wallet library" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [dependencies] +tari_common = { path = "../../common", version = "1.9.0-pre.0" } +tari_common_sqlite = { path = "../../common_sqlite", version = "1.9.0-pre.0" } +tari_common_types = { path = "../../base_layer/common_types", version = "1.9.0-pre.0" } +tari_contacts = { path = "../../base_layer/contacts", version = "1.9.0-pre.0" } tari_network = { workspace = true } tari_rpc_framework = { workspace = true } -tari_common = { path = "../../common", version = "1.8.0-pre.0" } -tari_common_sqlite = { path = "../../common_sqlite", version = "1.8.0-pre.0" } -tari_common_types = { path = "../../base_layer/common_types", version = "1.8.0-pre.0" } -tari_contacts = { path = "../../base_layer/contacts", version = "1.8.0-pre.0" } tari_core = { path = "../../base_layer/core", default-features = false, features = [ "transactions", "mempool_proto", "base_node_proto", -], version = "1.8.0-pre.0" } +], version = "1.9.0-pre.0" } tari_crypto = { version = "0.21.0" } tari_max_size = { path = "../../infrastructure/max_size" } tari_key_manager = { path = "../key_manager", features = [ "key_manager_service", -], version = "1.8.0-pre.0" } +], version = "1.9.0-pre.0" } tari_p2p = { path = "../p2p", features = [ "auto-update", -], version = "1.8.0-pre.0" } -tari_script = { path = "../../infrastructure/tari_script", version = "1.8.0-pre.0" } -tari_service_framework = { path = "../service_framework", version = "1.8.0-pre.0" } -tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.8.0-pre.0" } +], version = "1.9.0-pre.0" } +tari_script = { path = "../../infrastructure/tari_script", version = "1.9.0-pre.0" } +tari_service_framework = { path = "../service_framework", version = "1.9.0-pre.0" } +tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.9.0-pre.0" } tari_utilities = { version = "0.8" } # Uncomment for tokio tracing via tokio-console (needs "tracing" features) @@ -74,7 +74,7 @@ zeroize = "1" tari_common = { path = "../../common", features = [ "build", "static-application-info", -], version = "1.8.0-pre.0" } +], version = "1.9.0-pre.0" } [dev-dependencies] tari_p2p = { path = "../p2p", features = ["test-mocks"] } diff --git a/base_layer/wallet_ffi/Cargo.toml b/base_layer/wallet_ffi/Cargo.toml index c742ea3770..ad02920f9d 100644 --- a/base_layer/wallet_ffi/Cargo.toml +++ b/base_layer/wallet_ffi/Cargo.toml @@ -3,7 +3,7 @@ name = "minotari_wallet_ffi" authors = ["The Tari Development Community"] description = "Tari cryptocurrency wallet C FFI bindings" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2021" [dependencies] @@ -64,7 +64,7 @@ tari_common = { path = "../../common", features = [ "build", "static-application-info", ] } -tari_features = { path = "../../common/tari_features", version = "1.8.0-pre.0" } +tari_features = { path = "../../common/tari_features", version = "1.9.0-pre.0" } [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = [ diff --git a/changelog-development.md b/changelog-development.md index 204b451d90..8714dfafe9 100644 --- a/changelog-development.md +++ b/changelog-development.md @@ -2,6 +2,24 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [1.9.0-pre.0](https://github.com/tari-project/tari/compare/v1.8.0-pre.0...v1.9.0-pre.0) (2024-11-14) + + +### ⚠ BREAKING CHANGES + +* add new header field (#6686) + +### Features + +* add new header field ([#6686](https://github.com/tari-project/tari/issues/6686)) ([69a5872](https://github.com/tari-project/tari/commit/69a5872e52d8332e0b46e50614b2105bed0d22c9)) +* update ledger instructions ([#6673](https://github.com/tari-project/tari/issues/6673)) ([06f7a68](https://github.com/tari-project/tari/commit/06f7a6830661ffdc88cd0b90cf4e139123786225)) +* verify active base node peer connections and disconnect if stale ([#6655](https://github.com/tari-project/tari/issues/6655)) ([e61b5e2](https://github.com/tari-project/tari/commit/e61b5e2d172f782e953f351a81723713b150c57d)) + + +### Bug Fixes + +* **comms:** ensure that inbound messaging terminates on disconnect ([#6653](https://github.com/tari-project/tari/issues/6653)) ([47b4877](https://github.com/tari-project/tari/commit/47b48770f84e05c3dce1926d0a8d21eee4ccfe21)) + ## [1.8.0-pre.0](https://github.com/tari-project/tari/compare/v1.7.0-pre.4...v1.8.0-pre.0) (2024-10-28) diff --git a/changelog-nextnet.md b/changelog-nextnet.md index 7080c61cd2..0265a5aca2 100644 --- a/changelog-nextnet.md +++ b/changelog-nextnet.md @@ -2,6 +2,25 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. # Changelog +## [1.9.0-rc.0](https://github.com/tari-project/tari/compare/v1.8.0-rc.0...v1.9.0-rc.0) (2024-11-14) + + +### ⚠ BREAKING CHANGES + +* add new header field (#6686) + +### Features + +* add new header field ([#6686](https://github.com/tari-project/tari/issues/6686)) ([69a5872](https://github.com/tari-project/tari/commit/69a5872e52d8332e0b46e50614b2105bed0d22c9)) +* update ledger instructions ([#6673](https://github.com/tari-project/tari/issues/6673)) ([06f7a68](https://github.com/tari-project/tari/commit/06f7a6830661ffdc88cd0b90cf4e139123786225)) +* verify active base node peer connections and disconnect if stale ([#6655](https://github.com/tari-project/tari/issues/6655)) ([e61b5e2](https://github.com/tari-project/tari/commit/e61b5e2d172f782e953f351a81723713b150c57d)) + + +### Bug Fixes + +* **comms:** ensure that inbound messaging terminates on disconnect ([#6653](https://github.com/tari-project/tari/issues/6653)) ([47b4877](https://github.com/tari-project/tari/commit/47b48770f84e05c3dce1926d0a8d21eee4ccfe21)) + + ## [1.8.0-rc.0](https://github.com/tari-project/tari/compare/v1.7.0-rc.4...v1.8.0-rc.0) (2024-10-28) diff --git a/common/Cargo.toml b/common/Cargo.toml index 5f5a1c52b8..91e99c0290 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/tari-project/tari" homepage = "https://tari.com" readme = "README.md" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [features] @@ -14,7 +14,7 @@ build = ["toml", "prost-build"] static-application-info = ["git2"] [dependencies] -tari_features = { path = "./tari_features", version = "1.8.0-pre.0" } +tari_features = { path = "./tari_features", version = "1.9.0-pre.0" } anyhow = "1.0.53" config = { version = "0.14.0", default-features = false, features = ["toml"] } @@ -44,7 +44,7 @@ multiaddr = { workspace = true } toml = "0.5.8" [build-dependencies] -tari_features = { path = "./tari_features", version = "1.8.0-pre.0" } +tari_features = { path = "./tari_features", version = "1.9.0-pre.0" } [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = [ diff --git a/common/tari_features/Cargo.toml b/common/tari_features/Cargo.toml index 6f5a9067aa..85348bff94 100644 --- a/common/tari_features/Cargo.toml +++ b/common/tari_features/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/tari-project/tari" homepage = "https://tari.com" readme = "README.md" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common_sqlite/Cargo.toml b/common_sqlite/Cargo.toml index 07d56792fe..674e35b7f5 100644 --- a/common_sqlite/Cargo.toml +++ b/common_sqlite/Cargo.toml @@ -3,7 +3,7 @@ name = "tari_common_sqlite" authors = ["The Tari Development Community"] description = "Tari cryptocurrency wallet library" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/comms/core/Cargo.toml b/comms/core/Cargo.toml index d6acc263df..1ffd46f5fa 100644 --- a/comms/core/Cargo.toml +++ b/comms/core/Cargo.toml @@ -6,14 +6,14 @@ repository = "https://github.com/tari-project/tari" homepage = "https://tari.com" readme = "README.md" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2021" [dependencies] tari_crypto = { version = "0.21.0" } -tari_metrics = { path = "../../infrastructure/metrics", optional = true, version = "1.8.0-pre.0" } -tari_storage = { path = "../../infrastructure/storage", version = "1.8.0-pre.0" } -tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.8.0-pre.0" } +tari_metrics = { path = "../../infrastructure/metrics", optional = true, version = "1.9.0-pre.0" } +tari_storage = { path = "../../infrastructure/storage", version = "1.9.0-pre.0" } +tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.9.0-pre.0" } tari_utilities = { version = "0.8" } anyhow = "1.0.53" @@ -72,7 +72,7 @@ tempfile = "3.1.0" [build-dependencies] tari_common = { path = "../../common", features = [ "build", -], version = "1.8.0-pre.0" } +], version = "1.9.0-pre.0" } [features] c_integration = [] diff --git a/comms/dht/Cargo.toml b/comms/dht/Cargo.toml index 39afe03046..00652fe569 100644 --- a/comms/dht/Cargo.toml +++ b/comms/dht/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tari_comms_dht" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" authors = ["The Tari Development Community"] description = "Tari comms DHT module" repository = "https://github.com/tari-project/tari" @@ -10,14 +10,14 @@ license = "BSD-3-Clause" edition = "2021" [dependencies] -tari_comms = { path = "../core", features = ["rpc"], version = "1.8.0-pre.0" } -tari_common = { path = "../../common", version = "1.8.0-pre.0" } -tari_comms_rpc_macros = { path = "../rpc_macros", version = "1.8.0-pre.0" } +tari_comms = { path = "../core", features = ["rpc"], version = "1.9.0-pre.0" } +tari_common = { path = "../../common", version = "1.9.0-pre.0" } +tari_comms_rpc_macros = { path = "../rpc_macros", version = "1.9.0-pre.0" } tari_crypto = { version = "0.21.0" } tari_utilities = { version = "0.8" } -tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.8.0-pre.0" } -tari_storage = { path = "../../infrastructure/storage", version = "1.8.0-pre.0" } -tari_common_sqlite = { path = "../../common_sqlite", version = "1.8.0-pre.0" } +tari_shutdown = { path = "../../infrastructure/shutdown", version = "1.9.0-pre.0" } +tari_storage = { path = "../../infrastructure/storage", version = "1.9.0-pre.0" } +tari_common_sqlite = { path = "../../common_sqlite", version = "1.9.0-pre.0" } anyhow = "1.0.53" bitflags = { version = "2.4", features = ["serde"] } @@ -67,7 +67,7 @@ clap = "3.2" [build-dependencies] -tari_common = { path = "../../common", version = "1.8.0-pre.0" } +tari_common = { path = "../../common", version = "1.9.0-pre.0" } [features] test-mocks = [] diff --git a/comms/rpc_macros/Cargo.toml b/comms/rpc_macros/Cargo.toml index 4f76705cef..01ef8c59f5 100644 --- a/comms/rpc_macros/Cargo.toml +++ b/comms/rpc_macros/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/tari-project/tari" homepage = "https://tari.com" readme = "README.md" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [lib] diff --git a/hashing/Cargo.toml b/hashing/Cargo.toml index bf0a983902..bc9d7a870d 100644 --- a/hashing/Cargo.toml +++ b/hashing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tari_hashing" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2021" description = "Tari hash domains" authors = ["The Tari Development Community"] diff --git a/infrastructure/derive/Cargo.toml b/infrastructure/derive/Cargo.toml index 5b81e08ca6..750558581c 100644 --- a/infrastructure/derive/Cargo.toml +++ b/infrastructure/derive/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/tari-project/tari" homepage = "https://tari.com" readme = "README.md" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [lib] diff --git a/infrastructure/libtor/Cargo.toml b/infrastructure/libtor/Cargo.toml index 1eda1897a8..88ec9867dc 100644 --- a/infrastructure/libtor/Cargo.toml +++ b/infrastructure/libtor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tari_libtor" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2021" license = "BSD-3-Clause" diff --git a/infrastructure/max_size/Cargo.toml b/infrastructure/max_size/Cargo.toml index d93e32e569..f7283bbb4a 100644 --- a/infrastructure/max_size/Cargo.toml +++ b/infrastructure/max_size/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tari_max_size" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2021" description = "Tari max size library" authors = ["The Tari Development Community"] diff --git a/infrastructure/metrics/Cargo.toml b/infrastructure/metrics/Cargo.toml index c863312103..224cdd43cb 100644 --- a/infrastructure/metrics/Cargo.toml +++ b/infrastructure/metrics/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "tari_metrics" description = "Tari metrics" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2021" authors = ["The Tari Development Community"] repository = "https://github.com/tari-project/tari" diff --git a/infrastructure/shutdown/Cargo.toml b/infrastructure/shutdown/Cargo.toml index eafee3ffe2..a276842240 100644 --- a/infrastructure/shutdown/Cargo.toml +++ b/infrastructure/shutdown/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/tari-project/tari" homepage = "https://tari.com" readme = "README.md" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/infrastructure/storage/Cargo.toml b/infrastructure/storage/Cargo.toml index 4d827f9dc3..ebe0d50a62 100644 --- a/infrastructure/storage/Cargo.toml +++ b/infrastructure/storage/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/tari-project/tari" homepage = "https://tari.com" readme = "README.md" license = "BSD-3-Clause" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2018" [dependencies] diff --git a/infrastructure/tari_script/Cargo.toml b/infrastructure/tari_script/Cargo.toml index ccbf4c6d43..a1e1830397 100644 --- a/infrastructure/tari_script/Cargo.toml +++ b/infrastructure/tari_script/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tari_script" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" edition = "2021" description = "Tari script library" authors = ["The Tari Development Community"] diff --git a/infrastructure/test_utils/Cargo.toml b/infrastructure/test_utils/Cargo.toml index c14ae50057..32a25f0a1e 100644 --- a/infrastructure/test_utils/Cargo.toml +++ b/infrastructure/test_utils/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "tari_test_utils" description = "Utility functions used in Tari test functions" -version = "1.8.0-pre.0" +version = "1.9.0-pre.0" authors = ["The Tari Development Community"] edition = "2018" license = "BSD-3-Clause" @@ -9,7 +9,8 @@ license = "BSD-3-Clause" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -tari_shutdown = { path = "../shutdown", version = "1.8.0-pre.0" } +tari_shutdown = { path = "../shutdown", version = "1.9.0-pre.0" } + futures = { version = "^0.3.1" } rand = "0.8" diff --git a/package-lock.json b/package-lock.json index 3223905177..2b54c97572 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "tari", - "version": "1.8.0-pre.0", + "version": "1.9.0-pre.0", "lockfileVersion": 2, "requires": true, "packages": {} From 8e3a9ae33e0dec8889317f739c5a31b8eda00060 Mon Sep 17 00:00:00 2001 From: Hansie Odendaal Date: Thu, 28 Nov 2024 08:53:00 +0200 Subject: [PATCH 16/19] Merge development PRs: #6658, #6697, #6696 --- .license.ignore | 2 + Cargo.lock | 3 + .../minotari_app_grpc/proto/base_node.proto | 1 + applications/minotari_node/src/bootstrap.rs | 10 +- applications/minotari_node/src/builder.rs | 11 +- .../minotari_node/src/commands/cli_loop.rs | 29 +- .../minotari_node/src/commands/command/mod.rs | 6 + applications/minotari_node/src/config.rs | 4 + .../src/grpc/base_node_grpc_server.rs | 5 + base_layer/core/Cargo.toml | 2 + base_layer/core/src/base_node/mod.rs | 3 + .../base_node/tari_pulse_service/20326.rsa | 1 + .../base_node/tari_pulse_service/38696.rsa | 1 + .../src/base_node/tari_pulse_service/mod.rs | 274 ++++++++++++++++++ .../core/src/transactions/aggregated_body.rs | 6 +- common/config/presets/c_base_node_c.toml | 3 + common/src/exit_codes.rs | 2 + 17 files changed, 352 insertions(+), 11 deletions(-) create mode 100644 base_layer/core/src/base_node/tari_pulse_service/20326.rsa create mode 100644 base_layer/core/src/base_node/tari_pulse_service/38696.rsa create mode 100644 base_layer/core/src/base_node/tari_pulse_service/mod.rs diff --git a/.license.ignore b/.license.ignore index 9af3bb095f..5df15eb5ef 100644 --- a/.license.ignore +++ b/.license.ignore @@ -2,6 +2,8 @@ ./applications/minotari_node/assets/tari_logo.rs ./applications/minotari_node/osx-pkg/entitlements.xml ./base_layer/contacts/src/schema.rs +./base_layer/core/src/base_node/tari_pulse_service/20326.rsa +./base_layer/core/src/base_node/tari_pulse_service/38696.rsa ./base_layer/key_manager/src/schema.rs ./base_layer/wallet/src/schema.rs ./docs/src/theme/book.js diff --git a/Cargo.lock b/Cargo.lock index a09ded8bf7..cebac1eea3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2879,6 +2879,7 @@ dependencies = [ "idna 0.5.0", "ipnet", "once_cell", + "openssl", "rand", "ring 0.17.8", "rustls", @@ -7897,6 +7898,7 @@ dependencies = [ name = "tari_core" version = "1.9.0-pre.0" dependencies = [ + "anyhow", "async-trait", "bincode", "bitflags 2.6.0", @@ -7916,6 +7918,7 @@ dependencies = [ "futures 0.3.30", "futures-bounded", "hex", + "hickory-client", "integer-encoding", "libp2p-substream", "libsqlite3-sys", diff --git a/applications/minotari_app_grpc/proto/base_node.proto b/applications/minotari_app_grpc/proto/base_node.proto index 846d89b73b..885df7a361 100644 --- a/applications/minotari_app_grpc/proto/base_node.proto +++ b/applications/minotari_app_grpc/proto/base_node.proto @@ -158,6 +158,7 @@ message TipInfoResponse { MetaData metadata = 1; bool initial_sync_achieved = 2; BaseNodeState base_node_state = 3; + bool failed_checkpoints = 4; } enum BaseNodeState{ diff --git a/applications/minotari_node/src/bootstrap.rs b/applications/minotari_node/src/bootstrap.rs index d40af2c061..b78d29bf1f 100644 --- a/applications/minotari_node/src/bootstrap.rs +++ b/applications/minotari_node/src/bootstrap.rs @@ -29,18 +29,18 @@ use tari_common::{ exit_codes::{ExitCode, ExitError}, }; use tari_core::{ - base_node, base_node::{ + self, chain_metadata_service::ChainMetadataServiceInitializer, service::BaseNodeServiceInitializer, state_machine_service::initializer::BaseNodeStateMachineInitializer, + tari_pulse_service::TariPulseServiceInitializer, LocalNodeCommsInterface, StateMachineHandle, }, chain_storage::{async_db::AsyncBlockchainDb, BlockchainBackend, BlockchainDatabase}, consensus::ConsensusManager, - mempool, - mempool::{service::MempoolHandle, Mempool, MempoolServiceInitializer, MempoolSyncInitializer}, + mempool::{self, service::MempoolHandle, Mempool, MempoolServiceInitializer, MempoolSyncInitializer}, proof_of_work::randomx_factory::RandomXFactory, transactions::CryptoFactories, }; @@ -157,6 +157,10 @@ where B: BlockchainBackend + 'static self.randomx_factory, self.app_config.base_node.bypass_range_proof_verification, )) + .add_initializer(TariPulseServiceInitializer::new( + base_node_config.tari_pulse_interval, + base_node_config.network, + )) .build() .await?; diff --git a/applications/minotari_node/src/builder.rs b/applications/minotari_node/src/builder.rs index 86b28e4e83..a961ec888e 100644 --- a/applications/minotari_node/src/builder.rs +++ b/applications/minotari_node/src/builder.rs @@ -28,7 +28,12 @@ use tari_common::{ exit_codes::{ExitCode, ExitError}, }; use tari_core::{ - base_node::{state_machine_service::states::StatusInfo, LocalNodeCommsInterface, StateMachineHandle}, + base_node::{ + state_machine_service::states::StatusInfo, + tari_pulse_service::TariPulseHandle, + LocalNodeCommsInterface, + StateMachineHandle, + }, chain_storage::{create_lmdb_database, BlockchainDatabase, ChainStorageError, LMDBDatabase, Validators}, consensus::ConsensusManager, mempool::{service::LocalMempoolService, Mempool}, @@ -112,6 +117,10 @@ impl BaseNodeContext { self.base_node_handles.expect_handle() } + pub fn tari_pulse(&self) -> TariPulseHandle { + self.base_node_handles.expect_handle() + } + /// Returns a handle to the comms RPC server pub fn rpc_server(&self) -> RpcServerHandle { self.base_node_handles.expect_handle() diff --git a/applications/minotari_node/src/commands/cli_loop.rs b/applications/minotari_node/src/commands/cli_loop.rs index 34c382c93f..01752571a1 100644 --- a/applications/minotari_node/src/commands/cli_loop.rs +++ b/applications/minotari_node/src/commands/cli_loop.rs @@ -18,7 +18,7 @@ use tokio::{signal, task::JoinError, time}; use crate::{ commands::{ cli, - command::{CommandContext, WatchCommand}, + command::{Args, CommandContext, WatchCommand}, parser::Parser, reader::CommandReader, }, @@ -89,7 +89,9 @@ impl CliLoop { } else { while !self.done { self.watch_loop().await; - self.execute_command().await; + if !self.done { + self.execute_command().await; + } } } } @@ -144,12 +146,19 @@ impl CliLoop { println!("Wrong command to watch `{}`. Failed with: {}", line, err); } else { let mut events = EventStream::new(); - loop { + while !self.done { let interval = time::sleep(interval); tokio::select! { _ = interval => { if let Err(err) = self.context.handle_command_str(line).await { println!("Watched command `{}` failed: {}", line, err); + } else { + let args: Result = line.parse(); + if let Ok(command) = args { + if command.is_quit() { + self.done = true; + } + } } continue; }, @@ -177,7 +186,9 @@ impl CliLoop { } } } - crossterm::execute!(io::stdout(), cursor::MoveToNextLine(1)).ok(); + if !self.done { + crossterm::execute!(io::stdout(), cursor::MoveToNextLine(1)).ok(); + } } terminal::disable_raw_mode().ok(); } @@ -202,6 +213,13 @@ impl CliLoop { _ = interval => { if let Err(err) = self.context.handle_command_str(line).await { println!("Watched command `{}` failed: {}", line, err); + } else { + let args: Result = line.parse(); + if let Ok(command) = args { + if command.is_quit() { + self.done = true; + } + } } continue; }, @@ -261,6 +279,9 @@ impl CliLoop { } else { self.done = true; } + if self.done && !self.shutdown_signal.is_triggered() { + self.context.shutdown.trigger(); + } }, _ = self.shutdown_signal.wait() => { self.done = true; diff --git a/applications/minotari_node/src/commands/command/mod.rs b/applications/minotari_node/src/commands/command/mod.rs index 1686fb0c5f..04385b0da6 100644 --- a/applications/minotari_node/src/commands/command/mod.rs +++ b/applications/minotari_node/src/commands/command/mod.rs @@ -91,6 +91,12 @@ pub struct Args { pub command: Command, } +impl Args { + pub fn is_quit(&self) -> bool { + matches!(self.command, Command::Quit(_) | Command::Exit(_)) + } +} + #[derive(Debug, Subcommand, EnumVariantNames)] #[strum(serialize_all = "kebab-case")] pub enum Command { diff --git a/applications/minotari_node/src/config.rs b/applications/minotari_node/src/config.rs index a3e8a34515..977f71099a 100644 --- a/applications/minotari_node/src/config.rs +++ b/applications/minotari_node/src/config.rs @@ -140,6 +140,9 @@ pub struct BaseNodeConfig { pub state_machine: BaseNodeStateMachineConfig, /// Obscure GRPC error responses pub report_grpc_error: bool, + // Interval to check if the base node is still in sync with the network + #[serde(with = "serializers::seconds")] + pub tari_pulse_interval: Duration, } impl Default for BaseNodeConfig { @@ -182,6 +185,7 @@ impl Default for BaseNodeConfig { metadata_auto_ping_interval: Duration::from_secs(30), state_machine: Default::default(), report_grpc_error: false, + tari_pulse_interval: Duration::from_secs(120), } } } diff --git a/applications/minotari_node/src/grpc/base_node_grpc_server.rs b/applications/minotari_node/src/grpc/base_node_grpc_server.rs index 6811c2877e..7cf11f66ef 100644 --- a/applications/minotari_node/src/grpc/base_node_grpc_server.rs +++ b/applications/minotari_node/src/grpc/base_node_grpc_server.rs @@ -44,6 +44,7 @@ use tari_core::{ base_node::{ comms_interface::CommsInterfaceError, state_machine_service::states::StateInfo, + tari_pulse_service::TariPulseHandle, LocalNodeCommsInterface, StateMachineHandle, }, @@ -114,6 +115,7 @@ pub struct BaseNodeGrpcServer { network: NetworkHandle, liveness: LivenessHandle, report_grpc_error: bool, + tari_pulse: TariPulseHandle, config: BaseNodeConfig, } @@ -129,6 +131,7 @@ impl BaseNodeGrpcServer { network: ctx.network().clone(), liveness: ctx.liveness(), report_grpc_error: ctx.get_report_grpc_error(), + tari_pulse: ctx.tari_pulse(), config, } } @@ -1603,6 +1606,7 @@ impl tari_rpc::base_node_server::BaseNode for BaseNodeGrpcServer { trace!(target: LOG_TARGET, "Incoming GRPC request for BN tip data"); let mut handler = self.node_service.clone(); + let failed_checkpoints = *self.tari_pulse.get_failed_checkpoints_notifier(); let meta = handler .get_metadata() @@ -1616,6 +1620,7 @@ impl tari_rpc::base_node_server::BaseNode for BaseNodeGrpcServer { metadata: Some(meta.into()), initial_sync_achieved: status_watch.borrow().bootstrapped, base_node_state: state.into(), + failed_checkpoints, }; trace!(target: LOG_TARGET, "Sending MetaData response to client"); diff --git a/base_layer/core/Cargo.toml b/base_layer/core/Cargo.toml index b6fde6b493..143a5dcdc9 100644 --- a/base_layer/core/Cargo.toml +++ b/base_layer/core/Cargo.toml @@ -96,6 +96,8 @@ tiny-keccak = { package = "tari-tiny-keccak", version = "2.0.2", features = [ "keccak", ] } dirs-next = "1.0.2" +hickory-client = { version = "0.25.0-alpha.2", features = ["dns-over-rustls", "dnssec-openssl"] } +anyhow = "1.0.53" [dev-dependencies] criterion = { version = "0.4.0" } diff --git a/base_layer/core/src/base_node/mod.rs b/base_layer/core/src/base_node/mod.rs index d7e5830249..f16e942475 100644 --- a/base_layer/core/src/base_node/mod.rs +++ b/base_layer/core/src/base_node/mod.rs @@ -69,5 +69,8 @@ pub mod proto; #[cfg(any(feature = "base_node", feature = "base_node_proto"))] pub mod rpc; +#[cfg(feature = "base_node")] +pub mod tari_pulse_service; + pub const BAN_DURATION_LONG: Duration = Duration::from_secs(2 * 60 * 60); pub const BAN_DURATION_SHORT: Duration = Duration::from_secs(2 * 60); diff --git a/base_layer/core/src/base_node/tari_pulse_service/20326.rsa b/base_layer/core/src/base_node/tari_pulse_service/20326.rsa new file mode 100644 index 0000000000..acd48e8bd6 --- /dev/null +++ b/base_layer/core/src/base_node/tari_pulse_service/20326.rsa @@ -0,0 +1 @@ +AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3+/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kvArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+eoZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfdRUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwNR1AkUTV74bU= \ No newline at end of file diff --git a/base_layer/core/src/base_node/tari_pulse_service/38696.rsa b/base_layer/core/src/base_node/tari_pulse_service/38696.rsa new file mode 100644 index 0000000000..7948d28a47 --- /dev/null +++ b/base_layer/core/src/base_node/tari_pulse_service/38696.rsa @@ -0,0 +1 @@ +AwEAAa96jeuknZlaeSrvyAJj6ZHv28hhOKkx3rLGXVaC6rXTsDc449/cidltpkyGwCJNnOAlFNKF2jBosZBU5eeHspaQWOmOElZsjICMQMC3aeHbGiShvZsx4wMYSjH8e7Vrhbu6irwCzVBApESjbUdpWWmEnhathWu1jo+siFUiRAAxm9qyJNg/wOZqqzL/dL/q8PkcRU5oUKEpUge71M3ej2/7CPqpdVwuMoTvoB+ZOT4YeGyxMvHmbrxlFzGOHOijtzN+u1TQNatX2XBuzZNQ1K+s2CXkPIZo7s6JgZyvaBevYtxPvYLw4z9mR7K2vaF18UYH9Z9GNUUeayffKC73PYc= \ No newline at end of file diff --git a/base_layer/core/src/base_node/tari_pulse_service/mod.rs b/base_layer/core/src/base_node/tari_pulse_service/mod.rs new file mode 100644 index 0000000000..0d7492b686 --- /dev/null +++ b/base_layer/core/src/base_node/tari_pulse_service/mod.rs @@ -0,0 +1,274 @@ +// Copyright 2024. The Tari Project +// +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +// following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +// disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +// following disclaimer in the documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +// products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use std::{str::FromStr, time::Duration}; + +use futures::future; +use hickory_client::{ + client::{AsyncDnssecClient, ClientHandle}, + proto::{ + iocompat::AsyncIoTokioAsStd, + rr::dnssec::{public_key::Rsa, SigSigner, TrustAnchor}, + xfer::DnsMultiplexer, + }, + rr::{DNSClass, Name, RData, Record, RecordType}, + tcp::TcpClientStream, +}; +use log::{error, info, warn}; +use serde::{Deserialize, Serialize}; +use tari_p2p::Network; +use tari_service_framework::{async_trait, ServiceInitializationError, ServiceInitializer, ServiceInitializerContext}; +use tari_shutdown::ShutdownSignal; +use tari_utilities::hex::Hex; +use tokio::{net::TcpStream as TokioTcpStream, sync::watch, time}; + +use super::LocalNodeCommsInterface; +use crate::base_node::comms_interface::CommsInterfaceError; + +const LOG_TARGET: &str = "c::bn::tari_pulse"; +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct TariPulseConfig { + pub check_interval: Duration, + pub network: Network, +} + +impl Default for TariPulseConfig { + fn default() -> Self { + Self { + check_interval: Duration::from_secs(120), + network: Network::default(), + } + } +} + +fn get_network_dns_name(network: Network) -> Name { + match network { + Network::NextNet => Name::from_str("checkpoints-nextnet.tari.com").expect("infallible"), + Network::MainNet => Name::from_str("checkpoints-mainnet.tari.com").expect("infallible"), + Network::Esmeralda => Name::from_str("checkpoints-esmeralda.tari.com").expect("infallible"), + Network::StageNet => Name::from_str("checkpoints-stagenet.tari.com").expect("infallible"), + Network::Igor => Name::from_str("checkpoints-igor.tari.com").expect("infallible"), + Network::LocalNet => Name::from_str("checkpoints-localnet.tari.com").expect("infallible"), + } +} + +pub struct TariPulseService { + dns_name: Name, + config: TariPulseConfig, + shutdown_signal: ShutdownSignal, +} + +impl TariPulseService { + pub async fn new(config: TariPulseConfig, shutdown_signal: ShutdownSignal) -> Result { + let dns_name: Name = get_network_dns_name(config.clone().network); + info!(target: LOG_TARGET, "Tari Pulse Service initialized with DNS name: {}", dns_name); + Ok(Self { + dns_name, + config, + shutdown_signal, + }) + } + + pub fn default_trust_anchor() -> TrustAnchor { + const ROOT_ANCHOR_ORIG: &[u8] = include_bytes!("20326.rsa"); + const ROOT_ANCHOR_CURRENT: &[u8] = include_bytes!("38696.rsa"); + + let mut anchor = TrustAnchor::new(); + anchor.insert_trust_anchor(&Rsa::from_public_bytes(ROOT_ANCHOR_ORIG).expect("Invalid ROOT_ANCHOR_ORIG")); + anchor.insert_trust_anchor(&Rsa::from_public_bytes(ROOT_ANCHOR_CURRENT).expect("Invalid ROOT_ANCHOR_CURRENT")); + anchor + } + + async fn get_dns_client(&self) -> Result { + let timeout: Duration = Duration::from_secs(5); + let trust_anchor = Self::default_trust_anchor(); + + let (stream, handle) = TcpClientStream::>::new(([1, 1, 1, 1], 53).into()); + let dns_muxer = DnsMultiplexer::<_, SigSigner>::with_timeout(stream, handle, timeout, None); + let (client, bg) = AsyncDnssecClient::builder(dns_muxer) + .trust_anchor(trust_anchor) + .build() + .await?; + + tokio::spawn(bg); + + Ok(client) + } + + pub async fn run( + &mut self, + mut base_node_service: LocalNodeCommsInterface, + notify_passed_checkpoints: watch::Sender, + ) { + let mut interval = time::interval(self.config.check_interval); + let mut shutdown_signal = self.shutdown_signal.clone(); + + loop { + tokio::select! { + _ = interval.tick() => { + let passed_checkpoints = match self.passed_checkpoints(&mut base_node_service).await { + Ok(passed) => { + interval = time::interval(self.config.check_interval); // reset interval if back to healthy + passed + }, + Err(err) => { + warn!(target: LOG_TARGET, "Failed to check if node has passed checkpoints: {:?}", err); + let old_interval = interval.period().as_secs(); + let new_interval = if old_interval > (60 * 30) { + warn!(target: LOG_TARGET, "Reached maximum retry interval of 30 minutes."); + old_interval + } else { + // increase interval if node repeatedly (up to 30 min) fails to fetch checkpoints + interval = time::interval(Duration::from_secs(old_interval * 2)); + interval.tick().await; + interval.period().as_secs() + }; + warn!(target: LOG_TARGET, "Retrying in {} seconds", new_interval); + continue; + }, + }; + + notify_passed_checkpoints + .send(!passed_checkpoints) + .expect("Channel should be open"); + }, + _ = shutdown_signal.wait() => { + info!( + target: LOG_TARGET, + "Tari Pulse shutting down because the shutdown signal was received" + ); + break; + }, + } + } + } + + async fn passed_checkpoints( + &mut self, + base_node_service: &mut LocalNodeCommsInterface, + ) -> Result { + let dns_checkpoints = self.fetch_checkpoints().await?; + + let max_height_block = dns_checkpoints + .iter() + .max_by(|a, b| a.0.cmp(&b.0)) + .ok_or(CommsInterfaceError::InternalError("No checkpoints found".to_string()))?; + let local_checkpoints = self.get_node_block(base_node_service, max_height_block.0).await?; + Ok(local_checkpoints.1 == max_height_block.1) + } + + async fn get_node_block( + &mut self, + base_node_service: &mut LocalNodeCommsInterface, + block_height: u64, + ) -> Result<(u64, String), anyhow::Error> { + let historical_block = base_node_service + .get_header(block_height) + .await + .and_then(|header| match header { + Some(header) => Ok((header.height(), header.hash().to_hex())), + None => { + error!(target: LOG_TARGET, "Header not found for height: {}", block_height); + Err(CommsInterfaceError::InternalError("Header not found".to_string())) + }, + })?; + + Ok(historical_block) + } + + async fn fetch_checkpoints(&mut self) -> Result, anyhow::Error> { + let mut client = self.get_dns_client().await?; + let query = client.query(self.dns_name.clone(), DNSClass::IN, RecordType::TXT); + let response = query.await?; + let answers: &[Record] = response.answers(); + let checkpoints: Vec<(u64, String)> = answers + .iter() + .filter_map(|record| { + if let RData::TXT(txt) = record.data() { + let ascii_txt = txt.txt_data().iter().fold(String::new(), |mut acc, bytes| { + acc.push_str(&String::from_utf8_lossy(bytes)); + acc + }); + let (height, hash) = ascii_txt.split_once(':')?; + return Some((height.parse().ok()?, hash.to_string())); + } + None + }) + .collect(); + + Ok(checkpoints) + } +} + +#[derive(Clone)] +pub struct TariPulseHandle { + pub shutdown_signal: ShutdownSignal, + pub failed_checkpoints_notifier: watch::Receiver, +} + +impl TariPulseHandle { + pub fn get_failed_checkpoints_notifier(&self) -> watch::Ref<'_, bool> { + self.failed_checkpoints_notifier.borrow() + } +} + +pub struct TariPulseServiceInitializer { + interval: Duration, + network: Network, +} + +impl TariPulseServiceInitializer { + pub fn new(interval: Duration, network: Network) -> Self { + Self { interval, network } + } +} + +#[async_trait] +impl ServiceInitializer for TariPulseServiceInitializer { + async fn initialize(&mut self, context: ServiceInitializerContext) -> Result<(), ServiceInitializationError> { + info!(target: LOG_TARGET, "Initializing Tari Pulse Service"); + let shutdown_signal = context.get_shutdown_signal(); + let (sender, receiver) = watch::channel(false); + context.register_handle(TariPulseHandle { + shutdown_signal: shutdown_signal.clone(), + failed_checkpoints_notifier: receiver, + }); + let config = TariPulseConfig { + check_interval: self.interval, + network: self.network, + }; + + context.spawn_when_ready(move |handles| async move { + let base_node_service = handles.expect_handle::(); + let mut tari_pulse_service = TariPulseService::new(config, shutdown_signal.clone()) + .await + .expect("Should be able to get the service"); + let tari_pulse_service = tari_pulse_service.run(base_node_service, sender); + futures::pin_mut!(tari_pulse_service); + future::select(tari_pulse_service, shutdown_signal).await; + info!(target: LOG_TARGET, "Tari Pulse Service shutdown"); + }); + info!(target: LOG_TARGET, "Tari Pulse Service initialized"); + Ok(()) + } +} diff --git a/base_layer/core/src/transactions/aggregated_body.rs b/base_layer/core/src/transactions/aggregated_body.rs index 9e092063ea..7fa873e578 100644 --- a/base_layer/core/src/transactions/aggregated_body.rs +++ b/base_layer/core/src/transactions/aggregated_body.rs @@ -19,19 +19,19 @@ // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#[cfg(feature = "base_node")] +use std::convert::TryFrom; use std::{ cmp::max, fmt::{Display, Error, Formatter}, }; -#[cfg(feature = "base_node")] -use std::convert::TryFrom; use borsh::{BorshDeserialize, BorshSerialize}; use log::*; use serde::{Deserialize, Serialize}; -use tari_common_types::types::{ComAndPubSignature, Commitment, PrivateKey}; #[cfg(feature = "base_node")] use tari_common_types::types::FixedHash; +use tari_common_types::types::{ComAndPubSignature, Commitment, PrivateKey}; use tari_crypto::commitment::HomomorphicCommitmentFactory; #[cfg(feature = "base_node")] use tari_mmr::pruned_hashset::PrunedHashSet; diff --git a/common/config/presets/c_base_node_c.toml b/common/config/presets/c_base_node_c.toml index 1458fdd251..949652b1c3 100644 --- a/common/config/presets/c_base_node_c.toml +++ b/common/config/presets/c_base_node_c.toml @@ -45,6 +45,9 @@ # Obscure GRPC error responses (default = false) #report_grpc_error = false +# Interval between each request to the dns server for hte checkpoints to compare it with the local blockchain (default = 120 s) +# tari_pulse_interval = 120 + [base_node.lmdb] #init_size_bytes = 16_777_216 # 16 *1024 * 1024 #grow_size_bytes = 16_777_216 # 16 *1024 * 1024 diff --git a/common/src/exit_codes.rs b/common/src/exit_codes.rs index 1df1200a90..8c043a6610 100644 --- a/common/src/exit_codes.rs +++ b/common/src/exit_codes.rs @@ -131,6 +131,8 @@ pub enum ExitCode { WalletPaymentAddress = 123, #[error("Unable to configure TLS")] TlsConfigurationError = 124, + #[error("Unable to setup tari pulse")] + TariPulseError = 125, } impl From for ExitError { From 3beaa5f6e6777b9d8500c79b655e713b11550ff0 Mon Sep 17 00:00:00 2001 From: Hansie Odendaal Date: Thu, 28 Nov 2024 09:47:54 +0200 Subject: [PATCH 17/19] Merge development PRs: #6703, #6701, #6705, #6704 --- .github/workflows/build_binaries.yml | 18 +- Cargo.lock | 4 +- base_layer/core/Cargo.toml | 3 +- .../src/base_node/tari_pulse_service/mod.rs | 59 ++- .../wallet/src/connectivity_service/error.rs | 2 + .../src/connectivity_service/service.rs | 32 +- buildtools/windows-dev-environment-notes.md | 418 ++++++++++++++++++ 7 files changed, 491 insertions(+), 45 deletions(-) create mode 100644 buildtools/windows-dev-environment-notes.md diff --git a/.github/workflows/build_binaries.yml b/.github/workflows/build_binaries.yml index e4d0ceff21..ca835e2a11 100644 --- a/.github/workflows/build_binaries.yml +++ b/.github/workflows/build_binaries.yml @@ -223,14 +223,8 @@ jobs: - name: Install Windows dependencies if: startsWith(runner.os,'Windows') run: | - vcpkg.exe install sqlite3:x64-windows zlib:x64-windows # Bug in choco - need to install each package individually - choco upgrade llvm -y - # psutils is out of date - # choco upgrade psutils -y - choco upgrade openssl -y - # Should already be installed - # choco upgrade strawberryperl -y + vcpkg install openssl:x64-windows-static choco upgrade protoc -y rustup target add ${{ matrix.builds.target }} @@ -282,10 +276,8 @@ jobs: echo "SHELL_EXT=.bat" >> $GITHUB_ENV echo "TS_DIST=\dist" >> $GITHUB_ENV echo "PLATFORM_SPECIFIC_DIR=windows" >> $GITHUB_ENV - echo "SQLITE3_LIB_DIR=C:\vcpkg\installed\x64-windows\lib" >> $GITHUB_ENV - echo "OPENSSL_DIR=C:\Program Files\OpenSSL-Win64" >> $GITHUB_ENV - echo "LIBCLANG_PATH=C:\Program Files\LLVM\bin" >> $GITHUB_ENV - echo "C:\Strawberry\perl\bin" >> $GITHUB_PATH + echo "VCPKG_ROOT=C:\vcpkg" >> $GITHUB_ENV + echo "OPENSSL_DIR=C:\vcpkg\packages\openssl_x64-windows-static" >> $GITHUB_ENV - name: Cache cargo files and outputs if: ${{ ( ! startsWith(github.ref, 'refs/tags/v') ) && ( ! matrix.builds.cross ) && ( env.CARGO_CACHE ) }} @@ -325,6 +317,10 @@ jobs: echo "cargo options is: ${{ env.CARGO_OPTIONS }}" echo "cross flag: ${{ matrix.builds.cross }}" + - name: Debug environment variables - Windows + if: startsWith(runner.os,'Windows') + run: printenv + - name: Build release binaries shell: bash run: | diff --git a/Cargo.lock b/Cargo.lock index cebac1eea3..4bf8ff35f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6427,9 +6427,9 @@ dependencies = [ [[package]] name = "randomx-rs" -version = "1.3.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9abb8f2aa3432700c2b64a67406ac0da4956d78991f50559509cecc2b6abf249" +checksum = "09c347596479c4796192e68aec20e62e31655b57753586f2b1ec320b779ef14c" dependencies = [ "bitflags 1.3.2", "libc", diff --git a/base_layer/core/Cargo.toml b/base_layer/core/Cargo.toml index 143a5dcdc9..4d1d4cd49e 100644 --- a/base_layer/core/Cargo.toml +++ b/base_layer/core/Cargo.toml @@ -20,6 +20,7 @@ base_node = [ "base_node_proto", "monero", "randomx-rs", + "hickory-client", ] base_node_proto = [] benches = ["base_node"] @@ -96,7 +97,7 @@ tiny-keccak = { package = "tari-tiny-keccak", version = "2.0.2", features = [ "keccak", ] } dirs-next = "1.0.2" -hickory-client = { version = "0.25.0-alpha.2", features = ["dns-over-rustls", "dnssec-openssl"] } +hickory-client = { version = "0.25.0-alpha.2", features = ["dns-over-rustls", "dnssec-openssl"], optional = true } anyhow = "1.0.53" [dev-dependencies] diff --git a/base_layer/core/src/base_node/tari_pulse_service/mod.rs b/base_layer/core/src/base_node/tari_pulse_service/mod.rs index 0d7492b686..3ae3f5bfee 100644 --- a/base_layer/core/src/base_node/tari_pulse_service/mod.rs +++ b/base_layer/core/src/base_node/tari_pulse_service/mod.rs @@ -20,7 +20,7 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use std::{str::FromStr, time::Duration}; +use std::{cmp::min, str::FromStr, time::Duration}; use futures::future; use hickory_client::{ @@ -33,13 +33,13 @@ use hickory_client::{ rr::{DNSClass, Name, RData, Record, RecordType}, tcp::TcpClientStream, }; -use log::{error, info, warn}; +use log::{debug, error, info, trace, warn}; use serde::{Deserialize, Serialize}; use tari_p2p::Network; use tari_service_framework::{async_trait, ServiceInitializationError, ServiceInitializer, ServiceInitializerContext}; use tari_shutdown::ShutdownSignal; use tari_utilities::hex::Hex; -use tokio::{net::TcpStream as TokioTcpStream, sync::watch, time}; +use tokio::{net::TcpStream as TokioTcpStream, sync::watch, time, time::MissedTickBehavior}; use super::LocalNodeCommsInterface; use crate::base_node::comms_interface::CommsInterfaceError; @@ -121,31 +121,37 @@ impl TariPulseService { notify_passed_checkpoints: watch::Sender, ) { let mut interval = time::interval(self.config.check_interval); + interval.set_missed_tick_behavior(MissedTickBehavior::Delay); + tokio::pin!(interval); let mut shutdown_signal = self.shutdown_signal.clone(); + let mut count = 0u64; + let mut skip_ticks = 0; + let mut skipped_ticks = 0; loop { tokio::select! { _ = interval.tick() => { - let passed_checkpoints = match self.passed_checkpoints(&mut base_node_service).await { - Ok(passed) => { - interval = time::interval(self.config.check_interval); // reset interval if back to healthy - passed - }, - Err(err) => { - warn!(target: LOG_TARGET, "Failed to check if node has passed checkpoints: {:?}", err); - let old_interval = interval.period().as_secs(); - let new_interval = if old_interval > (60 * 30) { - warn!(target: LOG_TARGET, "Reached maximum retry interval of 30 minutes."); - old_interval - } else { - // increase interval if node repeatedly (up to 30 min) fails to fetch checkpoints - interval = time::interval(Duration::from_secs(old_interval * 2)); - interval.tick().await; - interval.period().as_secs() - }; - warn!(target: LOG_TARGET, "Retrying in {} seconds", new_interval); - continue; - }, + count += 1; + trace!(target: LOG_TARGET, "Interval tick: {}", count); + if skipped_ticks < skip_ticks { + skipped_ticks += 1; + debug!(target: LOG_TARGET, "Skipping {} of {} ticks", skipped_ticks, skip_ticks); + continue; + } + let passed_checkpoints = { + match self.passed_checkpoints(&mut base_node_service).await { + Ok(passed) => { + skip_ticks = 0; + skipped_ticks = 0; + passed + }, + Err(err) => { + warn!(target: LOG_TARGET, "Failed to check if node has passed checkpoints: {:?}", err); + skip_ticks = min(skip_ticks + 1, 30 * 60 / self.config.check_interval.as_secs()); + skipped_ticks = 0; + continue; + }, + } }; notify_passed_checkpoints @@ -174,7 +180,12 @@ impl TariPulseService { .max_by(|a, b| a.0.cmp(&b.0)) .ok_or(CommsInterfaceError::InternalError("No checkpoints found".to_string()))?; let local_checkpoints = self.get_node_block(base_node_service, max_height_block.0).await?; - Ok(local_checkpoints.1 == max_height_block.1) + let passed = local_checkpoints.1 == max_height_block.1; + trace!( + target: LOG_TARGET, "Passed checkpoints: {}, DNS: ({}, {}), Local: ({}, {})", + passed, max_height_block.0, max_height_block.1, local_checkpoints.0, local_checkpoints.1 + ); + Ok(passed) } async fn get_node_block( diff --git a/base_layer/wallet/src/connectivity_service/error.rs b/base_layer/wallet/src/connectivity_service/error.rs index 77d32b301b..d4a9d621da 100644 --- a/base_layer/wallet/src/connectivity_service/error.rs +++ b/base_layer/wallet/src/connectivity_service/error.rs @@ -40,6 +40,8 @@ pub enum WalletConnectivityError { PeerIndexOutOfBounds(String), #[error("Rpc client pool error: {0}")] RpcClientPoolError(#[from] RpcClientPoolError), + #[error("Client cancelled: '{0}'")] + ClientCancelled(String), } impl From for WalletConnectivityError { diff --git a/base_layer/wallet/src/connectivity_service/service.rs b/base_layer/wallet/src/connectivity_service/service.rs index 342248e8a0..5b9036cd61 100644 --- a/base_layer/wallet/src/connectivity_service/service.rs +++ b/base_layer/wallet/src/connectivity_service/service.rs @@ -20,7 +20,12 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use std::{mem, pin::pin, time::Duration}; +use std::{ + cmp::{max, min}, + mem, + pin::pin, + time::Duration, +}; use futures::{future, future::Either}; use log::*; @@ -41,7 +46,7 @@ use tari_rpc_framework::{ use tokio::{ sync::{mpsc, oneshot}, time, - time::MissedTickBehavior, + time::{timeout, Duration as TokioDuration, MissedTickBehavior}, }; use crate::{ @@ -305,9 +310,12 @@ impl WalletConnectivityService { peer_manager.get_current_peer().clone() }; + let mut loop_count = 0; + let number_of_seeds = peer_manager.get_state().1.len(); loop { + loop_count += 1; self.set_online_status(OnlineStatus::Connecting); - match self.try_setup_rpc_pool(&peer).await { + match self.try_setup_rpc_pool(&peer, loop_count / number_of_seeds + 1).await { Ok(true) => { self.base_node_watch.send(Some(peer_manager.clone())); self.notify_pending_requests().await; @@ -360,7 +368,7 @@ impl WalletConnectivityService { self.online_status_watch.send(status); } - async fn try_setup_rpc_pool(&mut self, peer: &Peer) -> Result { + async fn try_setup_rpc_pool(&mut self, peer: &Peer, dial_cycle: usize) -> Result { self.last_attempted_peer = Some(peer.peer_id()); let peer_id = peer.peer_id(); let dial_wait = self @@ -385,10 +393,20 @@ impl WalletConnectivityService { // Create the first RPC session to ensure that we can connect. { + // dial_timeout: 1 = 1s, 2 = 10s, 3 = 20s, 4 = 30s, 5 = 40s, 6 = 50s, 7 = 60s, 8 = 70s, 9 = 80s, 10 = 90s + let dial_timeout = TokioDuration::from_secs(min((max(1, 10 * (dial_cycle.saturating_sub(1)))) as u64, 90)); + trace!(target: LOG_TARGET, "Attempt dial with client timeout {:?}", dial_timeout); + let mut bn_changed_fut = pin!(self.base_node_watch.changed()); - match future::select(dial_wait, &mut bn_changed_fut).await { - Either::Left((result, _)) => result?, - Either::Right(_) => return Ok(false), + match timeout(dial_timeout, future::select(dial_wait, &mut bn_changed_fut)).await { + Ok(Either::Left((result, _))) => result?, + Ok(Either::Right(_)) => return Ok(false), + Err(_) => { + return Err(WalletConnectivityError::ClientCancelled(format!( + "Could not connect to '{}' in {:?}", + peer_id, dial_timeout + ))) + }, }; debug!(target: LOG_TARGET, "Dial succeeded for {peer_id}"); let connect_fut = pin!(container.base_node_wallet_rpc_client.get()); diff --git a/buildtools/windows-dev-environment-notes.md b/buildtools/windows-dev-environment-notes.md new file mode 100644 index 0000000000..70a6951281 --- /dev/null +++ b/buildtools/windows-dev-environment-notes.md @@ -0,0 +1,418 @@ + +# Basic build environment setup guide for Windows using winget for quick developer package testing - neither definitive nor exhaustive + +Lots of info collected from - https://github.com/KhronosGroup/OpenCL-Guide/blob/main/chapters/getting_started_windows.md + +and ```needed for developing Tauri apps.``` - https://v1.tauri.app/v1/guides/getting-started/prerequisites + +Need to have ```winget``` installed and working, which requires ```App Installer```, not only installed, but updated to the latest version. + +Using Microsoft Edge, open the following URL: + +https://www.microsoft.com/p/app-installer/9nblggh4nns1#activetab=pivot:overviewtab + +then click the ```App Installer``` install button. + +Found that after installing and rebooting Windows and checking for ```App Installer``` updates and appling any outstanding updates. + +Check that ```winget``` is working, run in PowerShell. +```PowerShell +winget list +``` +sample of output without ```App Installer``` installed +``` +PS C:\Users\leet> winget list + | +PS C:\Users\leet> +``` + +sample output where ```winget``` has not be run yet: +```PowerShell +PS C:\Users\leet> winget list +Failed in attempting to update the source: winget +The `msstore` source requires that you view the following agreements before using. +Terms of Transaction: https://aka.ms/microsoft-store-terms-of-transaction +The source requires the current machine's 2-letter geographic region to be sent to the backend service to function properly (ex. "US"). + +Do you agree to all the source agreements terms? +[Y] Yes [N] No: y +Failed when searching source; results will not be included: winget +Name Id Version +----------------------------------------------------------------------------------------------------------------------- +Clipchamp Clipchamp.Clipchamp_yxz26nhyzhsrt 2.2.8.0 +Microsoft Edge Microsoft Edge 130.0.2849.80 +Microsoft Edge WebView2 Runtime Microsoft EdgeWebView 130.0.2849.80 +``` +please notice ```Failed when searching source; results will not be included: winget```, normally means that ```App Installer``` needs to be updated. + +sample output where ```App Installer``` is installed, but not updated to the latest: +``` +PS C:\Users\leet> winget list +Failed in attempting to update the source: winget +Failed when searching source; results will not be included: winget +``` + +sample of output where ```winget``` is ready to be used for installing tools: +``` +PS C:\Users\leet> winget list +Name Id Version Available Source +----------------------------------------------------------------------------------------------------------------------- +Microsoft Visual Studio Installer ARP\Machine\X64\{6F320B93-EE3C-4826-85E… 3.11.2180.21897 +Tari Universe (Beta) ARP\Machine\X64\{A2500DE1-1C20-4E7E-9C5… 0.5.60.41105 +Visual Studio Build Tools 2022 Microsoft.VisualStudio.2022.BuildTools 17.11.5 winget +Microsoft Edge Microsoft.Edge 130.0.2849.68 winget +Microsoft Edge Update ARP\Machine\X86\Microsoft Edge Update 1.3.195.31 +Microsoft Edge WebView2 Runtime Microsoft.EdgeWebView2Runtime 130.0.2849.56 winget +Microsoft Visual C++ 2015-2022 Redistr… Microsoft.VCRedist.2015+.x64 14.40.33810.0 14.40.33816.0 winget +Microsoft OneDrive Microsoft.OneDrive 24.201.1006.0005 winget +Clipchamp MSIX\Clipchamp.Clipchamp_2.2.8.0_neutra… 2.2.8.0 +``` + +Then we can start installing components that will be needed in Compiling ```The Tari protocol tools``` locally + +# Install Visual Studio BuildTools 2022 +```PowerShell +winget install "Visual Studio BuildTools 2022" +``` +sample output would look something like: +``` +PS C:\Users\leet> winget install "Visual Studio BuildTools 2022" +Found Visual Studio BuildTools 2022 [Microsoft.VisualStudio.2022.BuildTools] Version 17.11.5 +This application is licensed to you by its owner. +Microsoft is not responsible for, nor does it grant any licenses to, third-party packages. +Downloading https://download.visualstudio.microsoft.com/download/pr/69e24482-3b48-44d3-af65-51f866a08313/471c9a89fa8ba27d356748ae0cf25eb1f362184992dc0bb6e9ccf10178c43c27/vs_BuildTools.exe + β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 4.22 MB / 4.22 MB +Successfully verified installer hash +Starting package install... +Successfully installed +``` + +# Install Visual Studio components for Windows 11 +```PowerShell +& "C:\Program Files (x86)\Microsoft Visual Studio\Installer\setup.exe" install --passive --norestart --productId Microsoft.VisualStudio.Product.BuildTools --channelId VisualStudio.17.Release --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.VisualStudio.Component.VC.Redist.14.Latest --add Microsoft.VisualStudio.Component.Windows11SDK.26100 --add Microsoft.VisualStudio.Component.VC.CMake.Project --add Microsoft.VisualStudio.Component.VC.CoreBuildTools --add Microsoft.VisualStudio.Component.VC.CoreIde --add Microsoft.VisualStudio.Component.VC.Redist.14.Latest --add Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core +```` +sample of the begining of output: +``` +PS C:\Users\leet> & "C:\Program Files (x86)\Microsoft Visual Studio\Installer\setup.exe" install --passive --norestart --productId Microsoft.VisualStudio.Product.BuildTools --channelId VisualStudio.17.Release --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.VisualStudio.Component.VC.Redist.14.Latest --add Microsoft.VisualStudio.Component.Windows11SDK.22000 +PS C:\Users\leet> [1d44:0001][2024-11-05T02:37:56] Saving the current locale (en-US) to user.json. +[1d44:0001][2024-11-05T02:37:56] Setting the telemetry services +[1d44:0005][2024-11-05T02:37:56] Creating a new telemetry service. +[1d44:0001][2024-11-05T02:37:56] Visual Studio Installer Version: 3.11.2180 +[1d44:0001][2024-11-05T02:37:56] Raw Command line: "C:\Program Files (x86)\Microsoft Visual Studio\Installer\setup.exe" install --passive --norestart --productId Microsoft.VisualStudio.Product.BuildTools --channelId VisualStudio.17.Release --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.VisualStudio.Component.VC.Redist.14.Latest --add Microsoft.VisualStudio.Component.Windows11SDK.22000 +[1d44:0001][2024-11-05T02:37:56] Parsed command line options: install --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 Microsoft.VisualStudio.Component.VC.Redist.14.Latest Microsoft.VisualStudio.Component.Windows11SDK.22000 --channelId VisualStudio.17.Release --norestart --passive --productId Microsoft.VisualStudio.Product.BuildTools +[1d44:0005][2024-11-05T02:37:56] Telemetry session ID: 8c0666e6-122f-43a2-8400-3c9a47d5d8d1 +[1d44:0004][2024-11-05T02:37:56] Creating new ExperimentationService +``` +Visual Studio Installer should download and install components requested. + +# Install git - https://git-scm.com/downloads/win +```PowerShell +winget install --id Git.Git -e --source winget +``` +sample output: +``` +PS C:\Users\leet> winget install --id Git.Git -e --source winget +>> +Found Git [Git.Git] Version 2.47.0.2 +This application is licensed to you by its owner. +Microsoft is not responsible for, nor does it grant any licenses to, third-party packages. +Downloading https://github.com/git-for-windows/git/releases/download/v2.47.0.windows.2/Git-2.47.0.2-64-bit.exe + β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 65.5 MB / 65.5 MB +Successfully verified installer hash +Starting package install... +Successfully installed +``` + +# Install Windows chocolatey package manager, helps with easy installation of additional components (protobuf) +```PowerShell +winget install --id chocolatey.chocolatey +``` +sample output: +``` +PS C:\Users\leet> winget install --id chocolatey.chocolatey +Found Chocolatey [Chocolatey.Chocolatey] Version 2.3.0.0 +This application is licensed to you by its owner. +Microsoft is not responsible for, nor does it grant any licenses to, third-party packages. +Downloading https://github.com/chocolatey/choco/releases/download/2.3.0/chocolatey-2.3.0.0.msi + β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 6.03 MB / 6.03 MB +Successfully verified installer hash +Starting package install... +Successfully installed +Notes: The Chocolatey CLI MSI is intended for installation only! If upgrading from 5.x of Licensed Extension, or 1.x of other Chocolatey products, see the upgrade guide at https://ch0.co/upv2v6 before continuing. Otherwise, run `choco upgrade chocolatey`. +``` + +# Install Protobuf with chocolatey +Use a new PowerShell console, as choco will not be in the current console path and seem broken. +```PowerShell +choco upgrade protoc -y +``` +sample output: +``` +PS C:\Users\leet> choco upgrade protoc -y +Chocolatey v2.3.0 +Upgrading the following packages: +protoc +By upgrading, you accept licenses for the packages. +protoc is not installed. Installing... +Downloading package from source 'https://community.chocolatey.org/api/v2/' +Progress: Downloading chocolatey-compatibility.extension 1.0.0... 100% + +chocolatey-compatibility.extension v1.0.0 [Approved] +chocolatey-compatibility.extension package files upgrade completed. Performing other installation steps. + Installed/updated chocolatey-compatibility extensions. + The upgrade of chocolatey-compatibility.extension was successful. + Deployed to 'C:\ProgramData\chocolatey\extensions\chocolatey-compatibility' +Downloading package from source 'https://community.chocolatey.org/api/v2/' +Progress: Downloading chocolatey-core.extension 1.4.0... 100% + +chocolatey-core.extension v1.4.0 [Approved] +chocolatey-core.extension package files upgrade completed. Performing other installation steps. + Installed/updated chocolatey-core extensions. + The upgrade of chocolatey-core.extension was successful. + Deployed to 'C:\ProgramData\chocolatey\extensions\chocolatey-core' +Downloading package from source 'https://community.chocolatey.org/api/v2/' +Progress: Downloading protoc 28.3.0... 100% + +protoc v28.3.0 [Approved] +protoc package files upgrade completed. Performing other installation steps. +Extracting 64-bit C:\ProgramData\chocolatey\lib\protoc\tools\protoc-28.3-win64.zip to C:\ProgramData\chocolatey\lib\protoc\tools... +C:\ProgramData\chocolatey\lib\protoc\tools + ShimGen has successfully created a shim for protoc.exe + The upgrade of protoc was successful. + Deployed to 'C:\ProgramData\chocolatey\lib\protoc\tools' + +Chocolatey upgraded 3/3 packages. + See the log for details (C:\ProgramData\chocolatey\logs\chocolatey.log). +``` + +# Install Windows vcpkg package manager, helps with easy installation of additional components (openssl) +```PowerShell +git clone https://github.com/microsoft/vcpkg.git \vcpkg +cd \vcpkg +.\bootstrap-vcpkg.bat +``` +sample output: +``` +PS C:\Users\leet> git clone https://github.com/microsoft/vcpkg.git C:\ +>> +fatal: destination path 'C:' already exists and is not an empty directory. +PS C:\Users\leet> git clone https://github.com/microsoft/vcpkg.git \vcpkg\ +>> +Cloning into '\vcpkg'... +remote: Enumerating objects: 254680, done. +remote: Counting objects: 100% (17338/17338), done. +remote: Compressing objects: 100% (686/686), done. +remote: Total 254680 (delta 17021), reused 16753 (delta 16652), pack-reused 237342 (from 1) +Receiving objects: 100% (254680/254680), 78.44 MiB | 6.35 MiB/s, done. +Resolving deltas: 100% (168180/168180), done. +Updating files: 100% (11832/11832), done. +PS C:\Users\leet> cd \vcpkg\ +PS C:\vcpkg> .\bootstrap-vcpkg.bat +Downloading https://github.com/microsoft/vcpkg-tool/releases/download/2024-11-12/vcpkg.exe -> C:\vcpkg\vcpkg.exe... done. +Validating signature... done. + +vcpkg package management program version 2024-11-12-eb492805e92a2c14a230f5c3deb3e89f6771c321 + +See LICENSE.txt for license information. +Telemetry +--------- +vcpkg collects usage data in order to help us improve your experience. +The data collected by Microsoft is anonymous. +You can opt-out of telemetry by re-running the bootstrap-vcpkg script with -disableMetrics, +passing --disable-metrics to vcpkg on the command line, +or by setting the VCPKG_DISABLE_METRICS environment variable. + +Read more about vcpkg telemetry at docs/about/privacy.md +``` + +# Install Openssl with vcpkg +```PowerShell +$Env:Path += ';C:\vcpkg' +vcpkg install openssl:x64-windows-static +``` +sample output: +``` +PS C:\Users\leet> $Env:Path += ';C:\vcpkg' +>> +PS C:\Users\leet> vcpkg install openssl:x64-windows-static +>> +Computing installation plan... +Computing installation plan... +A suitable version of cmake was not found (required v3.30.1). +Downloading cmake-3.30.1-windows-i386.zip +Successfully downloaded cmake-3.30.1-windows-i386.zip. +Extracting cmake... +A suitable version of 7zip was not found (required v24.8.0). +Downloading 7z2408-extra.7z +Successfully downloaded 7z2408-extra.7z. +Extracting 7zip... +A suitable version of 7zr was not found (required v24.8.0). +Downloading 424196f2-7zr.exe +Successfully downloaded 424196f2-7zr.exe. +The following packages will be built and installed: + openssl:x64-windows-static@3.4.0 + * vcpkg-cmake:x64-windows@2024-04-23 + * vcpkg-cmake-config:x64-windows@2024-05-23 + * vcpkg-cmake-get-vars:x64-windows@2024-09-22 +Additional packages (*) will be modified to complete this operation. +Detecting compiler hash for triplet x64-windows... +A suitable version of powershell-core was not found (required v7.2.24). +Downloading PowerShell-7.2.24-win-x64.zip +Successfully downloaded PowerShell-7.2.24-win-x64.zip. +Extracting powershell-core... +Compiler found: C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Tools/MSVC/14.42.34433/bin/Hostx64/x64/cl.exe +Detecting compiler hash for triplet x64-windows-static... +Compiler found: C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Tools/MSVC/14.42.34433/bin/Hostx64/x64/cl.exe +Restored 0 package(s) from C:\Users\leet\AppData\Local\vcpkg\archives in 523 us. Use --debug to see more details. +Installing 1/4 vcpkg-cmake:x64-windows@2024-04-23... +Building vcpkg-cmake:x64-windows@2024-04-23... +-- Installing: C:/vcpkg/packages/vcpkg-cmake_x64-windows/share/vcpkg-cmake/vcpkg_cmake_configure.cmake +-- Installing: C:/vcpkg/packages/vcpkg-cmake_x64-windows/share/vcpkg-cmake/vcpkg_cmake_build.cmake +-- Installing: C:/vcpkg/packages/vcpkg-cmake_x64-windows/share/vcpkg-cmake/vcpkg_cmake_install.cmake +-- Installing: C:/vcpkg/packages/vcpkg-cmake_x64-windows/share/vcpkg-cmake/vcpkg-port-config.cmake +-- Installing: C:/vcpkg/packages/vcpkg-cmake_x64-windows/share/vcpkg-cmake/copyright +-- Performing post-build validation +Stored binaries in 1 destinations in 123 ms. +Elapsed time to handle vcpkg-cmake:x64-windows: 428 ms +vcpkg-cmake:x64-windows package ABI: 1c9cd6d15b6bd6353941d2a7172da60b44407b254c8a998e11ac63a691d88c8c +Installing 2/4 vcpkg-cmake-config:x64-windows@2024-05-23... +Building vcpkg-cmake-config:x64-windows@2024-05-23... +-- Installing: C:/vcpkg/packages/vcpkg-cmake-config_x64-windows/share/vcpkg-cmake-config/vcpkg_cmake_config_fixup.cmake +-- Installing: C:/vcpkg/packages/vcpkg-cmake-config_x64-windows/share/vcpkg-cmake-config/vcpkg-port-config.cmake +-- Installing: C:/vcpkg/packages/vcpkg-cmake-config_x64-windows/share/vcpkg-cmake-config/copyright +-- Skipping post-build validation due to VCPKG_POLICY_EMPTY_PACKAGE +Stored binaries in 1 destinations in 139 ms. +Elapsed time to handle vcpkg-cmake-config:x64-windows: 371 ms +vcpkg-cmake-config:x64-windows package ABI: 3d79309c04958a43ccac3d839dceb8b3bf77fe6483ba5d7139e011f522841777 +Installing 3/4 vcpkg-cmake-get-vars:x64-windows@2024-09-22... +Building vcpkg-cmake-get-vars:x64-windows@2024-09-22... +-- Installing: C:/vcpkg/packages/vcpkg-cmake-get-vars_x64-windows/share/vcpkg-cmake-get-vars/vcpkg_cmake_get_vars.cmake +-- Installing: C:/vcpkg/packages/vcpkg-cmake-get-vars_x64-windows/share/vcpkg-cmake-get-vars/cmake_get_vars +-- Installing: C:/vcpkg/packages/vcpkg-cmake-get-vars_x64-windows/share/vcpkg-cmake-get-vars/cmake_get_vars/CMakeLists.txt +-- Installing: C:/vcpkg/packages/vcpkg-cmake-get-vars_x64-windows/share/vcpkg-cmake-get-vars/vcpkg-port-config.cmake +-- Installing: C:/vcpkg/packages/vcpkg-cmake-get-vars_x64-windows/share/vcpkg-cmake-get-vars/copyright +-- Performing post-build validation +Stored binaries in 1 destinations in 144 ms. +Elapsed time to handle vcpkg-cmake-get-vars:x64-windows: 375 ms +vcpkg-cmake-get-vars:x64-windows package ABI: 06e4bf7043f81750b3aaa7aa31a68dec84d1b064d55b6130ffea76f8ce300ffe +Installing 4/4 openssl:x64-windows-static@3.4.0... +Building openssl:x64-windows-static@3.4.0... +Downloading openssl-openssl-openssl-3.4.0.tar.gz +Successfully downloaded openssl-openssl-openssl-3.4.0.tar.gz. +-- Extracting source C:/vcpkg/downloads/openssl-openssl-openssl-3.4.0.tar.gz +-- Applying patch cmake-config.patch +-- Applying patch command-line-length.patch +-- Applying patch script-prefix.patch +-- Applying patch asm-armcap.patch +-- Applying patch windows/install-layout.patch +-- Applying patch windows/install-pdbs.patch +-- Applying patch unix/android-cc.patch +-- Applying patch unix/move-openssldir.patch +-- Applying patch unix/no-empty-dirs.patch +-- Applying patch unix/no-static-libs-for-shared.patch +-- Using source at C:/vcpkg/buildtrees/openssl/src/nssl-3.4.0-821e8e5bdc.clean +Downloading strawberry-perl-5.40.0.1-64bit-portable.zip +Successfully downloaded strawberry-perl-5.40.0.1-64bit-portable.zip. +-- Found external ninja('1.12.1'). +-- Getting CMake variables for x64-windows-static +Downloading nasm-2.16.01-win64.zip +Successfully downloaded nasm-2.16.01-win64.zip. +-- Getting CMake variables for x64-windows-static +Downloading jom_1_1_4.zip +Successfully downloaded jom_1_1_4.zip. +-- Prerunning x64-windows-static-dbg +-- Building x64-windows-static-dbg +-- Prerunning x64-windows-static-rel +-- Building x64-windows-static-rel +-- Fixing pkgconfig file: C:/vcpkg/packages/openssl_x64-windows-static/lib/pkgconfig/libcrypto.pc +-- Fixing pkgconfig file: C:/vcpkg/packages/openssl_x64-windows-static/lib/pkgconfig/libssl.pc +-- Fixing pkgconfig file: C:/vcpkg/packages/openssl_x64-windows-static/lib/pkgconfig/openssl.pc +Downloading msys2-mingw-w64-x86_64-pkgconf-1~2.3.0-1-any.pkg.tar.zst +Successfully downloaded msys2-mingw-w64-x86_64-pkgconf-1~2.3.0-1-any.pkg.tar.zst. +Downloading msys2-msys2-runtime-3.5.4-2-x86_64.pkg.tar.zst +Successfully downloaded msys2-msys2-runtime-3.5.4-2-x86_64.pkg.tar.zst. +-- Using msys root at C:/vcpkg/downloads/tools/msys2/21caed2f81ec917b +-- Fixing pkgconfig file: C:/vcpkg/packages/openssl_x64-windows-static/debug/lib/pkgconfig/libcrypto.pc +-- Fixing pkgconfig file: C:/vcpkg/packages/openssl_x64-windows-static/debug/lib/pkgconfig/libssl.pc +-- Fixing pkgconfig file: C:/vcpkg/packages/openssl_x64-windows-static/debug/lib/pkgconfig/openssl.pc +-- Installing: C:/vcpkg/packages/openssl_x64-windows-static/share/openssl/usage +-- Installing: C:/vcpkg/packages/openssl_x64-windows-static/share/openssl/copyright +-- Performing post-build validation +Stored binaries in 1 destinations in 13 s. +Elapsed time to handle openssl:x64-windows-static: 12 min +openssl:x64-windows-static package ABI: 746f9866315ce83ce1152f628b0dc320c6c36af665378d4a042c3385da77ce43 +Total install time: 12 min +openssl is compatible with built-in CMake targets: + + find_package(OpenSSL REQUIRED) + target_link_libraries(main PRIVATE OpenSSL::SSL) + target_link_libraries(main PRIVATE OpenSSL::Crypto) +``` + +# Install rust +```PowerShell +winget install --id Rustlang.Rustup +``` +sample ouput: +``` +PS C:\Users\leet\src\vcpkg> winget install --id Rustlang.Rustup +Found Rustup: the Rust toolchain installer [Rustlang.Rustup] Version 1.27.1 +This application is licensed to you by its owner. +Microsoft is not responsible for, nor does it grant any licenses to, third-party packages. +Downloading https://static.rust-lang.org/rustup/archive/1.27.1/x86_64-pc-windows-msvc/rustup-init.exe + β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 8.53 MB / 8.53 MB +Successfully verified installer hash +Starting package install... +Successfully installed +``` + +# Get the Tari code base +```PowerShell +cd src +git clone https://github.com/tari-project/tari.git +cd tari +``` +sample output: +``` +PS C:\Users\leet\src> git clone https://github.com/tari-project/tari.git +>> +Cloning into 'tari'... +remote: Enumerating objects: 133401, done. +remote: Counting objects: 100% (7577/7577), done. +remote: Compressing objects: 100% (3635/3635), done. +remote: Total 133401 (delta 4830), reused 6216 (delta 3900), pack-reused 125824 (from 1) +Receiving objects: 100% (133401/133401), 144.04 MiB | 5.98 MiB/s, done. +Resolving deltas: 100% (99974/99974), done. +Updating files: 100% (1786/1786), done. +``` + +# Build Tari Tools +```PowerShell +$Env:VCPKG_ROOT = 'C:\vcpkg' +$Env:OPENSSL_DIR = 'C:\vcpkg\packages\openssl_x64-windows-static' +cargo build --release --bin minotari_miner +``` +sample output: +``` +PS C:\Users\leet> cd src\tari +PS C:\Users\leet\src\tari> cargo build --release --bin minotari_miner +info: syncing channel updates for 'nightly-2024-07-07-x86_64-pc-windows-msvc' +info: latest update on 2024-07-07, rust version 1.81.0-nightly (ed7e35f34 2024-07-06) +info: downloading component 'cargo' +info: downloading component 'clippy' +info: downloading component 'rust-docs' +info: downloading component 'rust-std' +info: downloading component 'rustc' +info: downloading component 'rustfmt' +info: installing component 'cargo' +info: installing component 'clippy' +info: installing component 'rust-docs' +info: installing component 'rust-std' +info: installing component 'rustc' +info: installing component 'rustfmt' + Updating git repository `https://github.com/tari-project/lmdb-rs` + Updating git submodule `https://github.com/LMDB/lmdb.git` + Updating crates.io index + Updating git repository `https://github.com/Zondax/ledger-rs` + Downloading 516 crates +``` From a2253334580cde4074b743c20d0b42688603fd1d Mon Sep 17 00:00:00 2001 From: Hansie Odendaal Date: Thu, 28 Nov 2024 10:02:51 +0200 Subject: [PATCH 18/19] merge conflicts --- base_layer/core/src/proto/block.proto | 114 -------------------------- comms/core/src/connectivity/error.rs | 2 - 2 files changed, 116 deletions(-) delete mode 100644 base_layer/core/src/proto/block.proto diff --git a/base_layer/core/src/proto/block.proto b/base_layer/core/src/proto/block.proto deleted file mode 100644 index 184a8d3c53..0000000000 --- a/base_layer/core/src/proto/block.proto +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2022 The Tari Project -// SPDX-License-Identifier: BSD-3-Clause - -syntax = "proto3"; - -import "google/protobuf/wrappers.proto"; -import "transaction.proto"; -import "types.proto"; - -package tari.core; - -// The proof of work data structure that is included in the block header. -message ProofOfWork { - // The algorithm used to mine this block - // 0 = Monero - // 1 = Sha3X - uint64 pow_algo = 1; - // Supplemental proof of work data. For example for Sha3x, this would be empty (only the block header is - // required), but for Monero merge mining we need the Monero block header and RandomX seed hash. - bytes pow_data = 4; -} - -// The BlockHeader contains all the metadata for the block, including proof of work, a link to the previous block -// and the transaction kernels. -message BlockHeader { - // Version of the block - uint32 version = 1; - // Height of this block since the genesis block (height 0) - uint64 height = 2; - // Hash of the block previous to this in the chain. - bytes prev_hash = 4; - // Timestamp at which the block was built. - uint64 timestamp = 5; - // This is the UTXO merkle root of the outputs in the blockchain - bytes output_mr = 6; - // This is the merkle root of all outputs in this block - bytes block_output_mr = 7; - // This is the MMR root of the kernels - bytes kernel_mr = 8; - // This is the Merkle root of the inputs in this block - bytes input_mr = 9; - // Total accumulated sum of kernel offsets since genesis block. We can derive the kernel offset sum for *this* - // block from the total kernel offset of the previous block header. - bytes total_kernel_offset = 10; - // Nonce increment used to mine this block. - uint64 nonce = 11; - // Proof of work metadata - ProofOfWork pow = 12; - // The size of the kernel MMR - uint64 kernel_mmr_size = 13; - // The size of the output MMR - uint64 output_mmr_size = 14; - // Sum of script offsets for all kernels in this block. - bytes total_script_offset = 15; - // Merkle root of validator nodes - bytes validator_node_merkle_root = 16; - // Validator size - uint64 validator_node_size = 17; -} - -// A Tari block. Blocks are linked together into a blockchain. -message Block { - // The BlockHeader contains all the metadata for the block, including proof of work, a link to the previous block - // and the transaction kernels. - BlockHeader header = 1; - // The components of the block or transaction. The same struct can be used for either, since in Mimblewimble, - // blocks consist of inputs, outputs and kernels, rather than transactions. - tari.types.AggregateBody body = 2; -} - -// A new block message. This is the message that is propagated around the network. It contains the -// minimal information required to identify and optionally request the full block. -message NewBlock { - // The block header. - BlockHeader header = 1; - // Coinbase kernel of the block. - repeated tari.types.TransactionKernel coinbase_kernels = 2; - // Coinbase output of the block. - repeated tari.types.TransactionOutput coinbase_outputs = 3; - // The scalar `s` component of the kernel excess signatures of the transactions contained in the block. - repeated bytes kernel_excess_sigs = 4; -} - -// The representation of a historical block in the blockchain. It is essentially identical to a protocol-defined -// block but contains some extra metadata that clients such as Block Explorers will find interesting. -message HistoricalBlock { - // The number of blocks that have been mined since this block, including this one. The current tip will have one - // confirmation. - uint64 confirmations = 1; - // The underlying block - Block block = 3; - // Accumulated and other pertinent data in the block header acting as a "condensed blockchain snapshot" for the block - BlockHeaderAccumulatedData accumulated_data = 4; -} - -// Accumulated and other pertinent data in the block header acting as a "condensed blockchain snapshot" for the block -message BlockHeaderAccumulatedData { - // The achieved difficulty for solving the current block using the specified proof of work algorithm. - uint64 achieved_difficulty = 1; - // The total accumulated difficulty for RandomX proof of work for all blocks since Genesis, - // but not including this block, tracked separately. - bytes accumulated_randomx_difficulty = 2; - // The total accumulated difficulty for SHA3 proof of work for all blocks since Genesis, - // but not including this block, tracked separately. - bytes accumulated_sha3x_difficulty = 3; - // The target difficulty for solving the current block using the specified proof of work algorithm. - uint64 target_difficulty = 4; - // The total accumulated offset for all kernels in the block. - bytes total_kernel_offset = 5; - // The block hash - bytes hash = 6; - // The total accumulated difficulty for all blocks since Genesis, but not including this block, tracked separately. - bytes total_accumulated_difficulty = 7; -} diff --git a/comms/core/src/connectivity/error.rs b/comms/core/src/connectivity/error.rs index 5dbfe2849d..acb554ac79 100644 --- a/comms/core/src/connectivity/error.rs +++ b/comms/core/src/connectivity/error.rs @@ -43,8 +43,6 @@ pub enum ConnectivityError { OnlineWaitTimeout(usize), #[error("Pending dial was cancelled")] DialCancelled, - #[error("Client cancelled: '{0}'")] - ClientCancelled(String), } impl From for ConnectivityError { From f883507c4811e5b884a6a42f9f21b887b237f311 Mon Sep 17 00:00:00 2001 From: Hansie Odendaal Date: Thu, 28 Nov 2024 15:39:06 +0200 Subject: [PATCH 19/19] openssl -> vendored feature --- Cargo.lock | 3 +++ applications/minotari_console_wallet/Cargo.toml | 2 +- applications/minotari_miner/Cargo.toml | 2 +- base_layer/core/Cargo.toml | 12 +++++++++++- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4bf8ff35f9..01676a7f39 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2878,6 +2878,7 @@ dependencies = [ "futures-util", "idna 0.5.0", "ipnet", + "native-tls", "once_cell", "openssl", "rand", @@ -2888,6 +2889,7 @@ dependencies = [ "time", "tinyvec", "tokio", + "tokio-native-tls", "tokio-rustls", "tracing", "url", @@ -7932,6 +7934,7 @@ dependencies = [ "num-format", "num-traits", "once_cell", + "openssl", "primitive-types", "prost 0.13.3", "quickcheck", diff --git a/applications/minotari_console_wallet/Cargo.toml b/applications/minotari_console_wallet/Cargo.toml index fa64928743..6b221eefe9 100644 --- a/applications/minotari_console_wallet/Cargo.toml +++ b/applications/minotari_console_wallet/Cargo.toml @@ -56,7 +56,7 @@ log4rs = { version = "1.3.0", default-features = false, features = [ qrcode = { version = "0.12" } rand = "0.8" regex = "1.5.4" -reqwest = "0.11.18" +reqwest = { version = "0.11.18", features = ["native-tls-vendored"] } rpassword = "5.0" rustyline = "9.0" serde = "1.0.136" diff --git a/applications/minotari_miner/Cargo.toml b/applications/minotari_miner/Cargo.toml index 17a41b8cb9..397d980d88 100644 --- a/applications/minotari_miner/Cargo.toml +++ b/applications/minotari_miner/Cargo.toml @@ -41,7 +41,7 @@ log4rs = { version = "1.3.0", default-features = false, features = [ "size_trigger", "fixed_window_roller", ] } -native-tls = "0.2" +native-tls = { version = "0.2", features = ["vendored"] } num_cpus = "1.13" rand = "0.8" serde = { version = "1.0", default-features = false, features = ["derive"] } diff --git a/base_layer/core/Cargo.toml b/base_layer/core/Cargo.toml index 4d1d4cd49e..243d273ad3 100644 --- a/base_layer/core/Cargo.toml +++ b/base_layer/core/Cargo.toml @@ -97,7 +97,11 @@ tiny-keccak = { package = "tari-tiny-keccak", version = "2.0.2", features = [ "keccak", ] } dirs-next = "1.0.2" -hickory-client = { version = "0.25.0-alpha.2", features = ["dns-over-rustls", "dnssec-openssl"], optional = true } +hickory-client = { version = "0.25.0-alpha.2", features = [ + "dns-over-native-tls", + "dnssec-openssl" +], optional = true } +openssl = { version = "0.10.66", features = ["vendored"] } anyhow = "1.0.53" [dev-dependencies] @@ -127,3 +131,9 @@ unexpected_cfgs = { level = "warn", check-cfg = [ 'cfg(tari_target_network_nextnet)', 'cfg(tari_target_network_testnet)', ] } + +[package.metadata.cargo-machete] +openssl = [ + # We need to specify extra features for openssl even though it is not used directly in this crate + "openssl", +]