gadget-sdk 0.6.2

SDK for building Blueprints and gadget on Tangle Network
Documentation
#![allow(unused_results)]

use crate::network::gossip::{GossipMessage, NetworkService};

use crate::{error, trace};
use libp2p::gossipsub::TopicHash;
use libp2p::{gossipsub, PeerId};
use std::sync::atomic::AtomicU32;
use std::sync::Arc;

impl NetworkService<'_> {
    #[tracing::instrument(skip(self, event))]
    pub(crate) async fn handle_gossip(&mut self, event: gossipsub::Event) {
        use gossipsub::Event::{GossipsubNotSupported, Message, Subscribed, Unsubscribed};
        let with_connected_peers = |topic: &TopicHash, f: fn(&Arc<AtomicU32>)| {
            let maybe_mapping = self
                .inbound_mapping
                .iter()
                .find(|r| r.0.to_string() == topic.to_string());
            match maybe_mapping {
                Some((_, _, connected_peers)) => {
                    f(connected_peers);
                    true
                }
                None => false,
            }
        };
        match event {
            Message {
                propagation_source,
                message_id,
                message,
            } => {
                self.handle_gossip_message(propagation_source, message_id, message)
                    .await;
            }
            Subscribed { peer_id, topic } => {
                let added = with_connected_peers(&topic, |connected_peers| {
                    connected_peers.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
                });
                if added {
                    trace!("{peer_id} subscribed to {topic}");
                } else {
                    error!("{peer_id} subscribed to unknown topic: {topic}");
                }
            }
            Unsubscribed { peer_id, topic } => {
                let removed = with_connected_peers(&topic, |connected_peers| {
                    connected_peers.fetch_sub(1, std::sync::atomic::Ordering::Relaxed);
                });
                if removed {
                    trace!("{peer_id} unsubscribed from {topic}");
                } else {
                    error!("{peer_id} unsubscribed from unknown topic: {topic}");
                }
            }
            GossipsubNotSupported { peer_id } => {
                trace!("{peer_id} does not support gossipsub!");
            }
        }
    }

    #[tracing::instrument(
    skip(self, message),
    fields(
    %_message_id,
    %_propagation_source,
    source = ?message.source
    )
    )]
    async fn handle_gossip_message(
        &mut self,
        _propagation_source: PeerId,
        _message_id: gossipsub::MessageId,
        message: gossipsub::Message,
    ) {
        let Some(origin) = message.source else {
            error!("Got message from unknown peer");
            return;
        };

        // Reject messages from self
        if origin == self.my_id {
            return;
        }

        trace!("Got message from peer: {origin}");
        match bincode::deserialize::<GossipMessage>(&message.data) {
            Ok(GossipMessage { topic, raw_payload }) => {
                if let Some((_, tx, _)) = self
                    .inbound_mapping
                    .iter()
                    .find(|r| r.0.to_string() == topic)
                {
                    if let Err(e) = tx.send(raw_payload) {
                        error!("Failed to send message to worker: {e}");
                    }
                } else {
                    error!("No registered worker for topic: {topic}!");
                }
            }
            Err(e) => {
                error!("Failed to deserialize message: {e}");
            }
        }
    }
}