diff --git a/radicle-cli/examples/rad-patch-pull-update.md b/radicle-cli/examples/rad-patch-pull-update.md index a0c89785..7d95fc82 100644 --- a/radicle-cli/examples/rad-patch-pull-update.md +++ b/radicle-cli/examples/rad-patch-pull-update.md @@ -38,7 +38,8 @@ Run `cd ./heartwood` to go to the project directory. We wait for Alice to sync our fork. ``` ~bob -$ rad node events -n 1 --timeout 1 +$ rad node events -n 2 --timeout 1 +{"type":"refsAnnounced","nid":"z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi","rid":"rad:zhbMU4DUXrzB8xT6qAJh6yZ7bFMK","refs":[{"remote":"z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk","at":"161b775a3509c8098de67f57f750972bba015b31"}],"timestamp":[..]} {"type":"refsSynced","remote":"z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi","rid":"rad:zhbMU4DUXrzB8xT6qAJh6yZ7bFMK"} ``` diff --git a/radicle-node/src/service.rs b/radicle-node/src/service.rs index 7f07c11c..89feb277 100644 --- a/radicle-node/src/service.rs +++ b/radicle-node/src/service.rs @@ -919,7 +919,7 @@ where } = announcement; // Ignore our own announcements, in case the relayer sent one by mistake. - if *announcer == self.node_id() { + if announcer == self.nid() { return Ok(false); } let now = self.clock; @@ -969,7 +969,13 @@ where } match message { + // Process a peer inventory update announcement by (maybe) fetching. AnnouncementMessage::Inventory(message) => { + self.emitter.emit(Event::InventoryAnnounced { + nid: *announcer, + inventory: message.inventory.to_vec(), + timestamp: message.timestamp, + }); match self.sync_routing(&message.inventory, *announcer, message.timestamp) { Ok(synced) => { if synced.is_empty() { @@ -1018,8 +1024,13 @@ where return Ok(relay); } - // Process a peer inventory update announcement by (maybe) fetching. AnnouncementMessage::Refs(message) => { + self.emitter.emit(Event::RefsAnnounced { + nid: *announcer, + rid: message.rid, + refs: message.refs.to_vec(), + timestamp: message.timestamp, + }); // We update inventories when receiving ref announcements, as these could come // from a new repository being initialized. if let Ok(result) = @@ -1094,6 +1105,13 @@ where .. }, ) => { + self.emitter.emit(Event::NodeAnnounced { + nid: *announcer, + alias: ann.alias.clone(), + timestamp: ann.timestamp, + features: *features, + addresses: addresses.to_vec(), + }); // If this node isn't a seed, we're not interested in adding it // to our address book, but other nodes may be, so we relay the message anyway. if !features.has(Features::SEED) { diff --git a/radicle/src/node.rs b/radicle/src/node.rs index 6d1b426e..d8c29b5c 100644 --- a/radicle/src/node.rs +++ b/radicle/src/node.rs @@ -554,7 +554,7 @@ pub enum AnnounceEvent { Announced, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] #[serde(tag = "status", rename_all = "camelCase")] pub enum FetchResult { Success { diff --git a/radicle/src/node/events.rs b/radicle/src/node/events.rs index b75853ef..7f05c8f7 100644 --- a/radicle/src/node/events.rs +++ b/radicle/src/node/events.rs @@ -3,8 +3,9 @@ use std::time; use crossbeam_channel as chan; +use crate::node; use crate::prelude::*; -use crate::storage::RefUpdate; +use crate::storage::{refs, RefUpdate}; /// A service event. #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] @@ -34,6 +35,24 @@ pub enum Event { nid: NodeId, reason: String, }, + InventoryAnnounced { + nid: NodeId, + inventory: Vec, + timestamp: Timestamp, + }, + RefsAnnounced { + nid: NodeId, + rid: Id, + refs: Vec, + timestamp: Timestamp, + }, + NodeAnnounced { + nid: NodeId, + alias: Alias, + timestamp: Timestamp, + features: node::Features, + addresses: Vec, + }, } /// Events feed. diff --git a/radicle/src/node/features.rs b/radicle/src/node/features.rs index 9633e905..aa0e43ad 100644 --- a/radicle/src/node/features.rs +++ b/radicle/src/node/features.rs @@ -1,8 +1,10 @@ //! Node features advertized on the network. +use serde::{Deserialize, Serialize}; use std::{fmt, ops}; /// Advertized node features. Signals what services the node supports. -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +#[serde(transparent)] pub struct Features(u64); impl Features { diff --git a/radicle/src/storage/refs.rs b/radicle/src/storage/refs.rs index 92e12e15..8d235661 100644 --- a/radicle/src/storage/refs.rs +++ b/radicle/src/storage/refs.rs @@ -8,7 +8,7 @@ use std::path::Path; use std::str::FromStr; use crypto::{PublicKey, Signature, Signer, SignerError, Unverified, Verified}; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use thiserror::Error; use crate::git; @@ -369,7 +369,8 @@ impl Deref for SignedRefs { /// /// It can also be used for communicating announcements of updates /// references to other nodes. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct RefsAt { /// The remote namespace of the `rad/sigrefs`. pub remote: RemoteId,