use async_trait::async_trait;
use libp2p::gossipsub::IdentTopic;
use pchain_types::cryptography::PublicAddress;
use crate::conversions;
pub type Message = Vec<u8>;
#[derive(Clone)]
pub struct Envelope {
pub origin: PublicAddress,
pub message: Message,
}
#[async_trait]
pub trait MessageGate: Send + Sync + 'static {
async fn can_proceed(&self, topic_hash: &NetworkTopicHash) -> bool;
async fn proceed(&self, envelope: Envelope) -> bool;
}
#[derive(Default)]
pub struct MessageGateChain {
gates: Vec<Box<dyn MessageGate>>,
}
impl MessageGateChain {
pub fn new() -> Self {
Self { gates: Vec::new() }
}
pub fn chain(mut self, gate: impl MessageGate) -> Self {
self.gates.push(Box::new(gate));
self
}
pub(crate) async fn message_in(&self, topic_hash: &NetworkTopicHash, envelope: Envelope) {
for gate in &self.gates {
if gate.can_proceed(topic_hash).await && gate.proceed(envelope.clone()).await {
break;
}
}
}
}
#[derive(Debug)]
pub struct NetworkTopic(IdentTopic);
pub type NetworkTopicHash = libp2p::gossipsub::TopicHash;
impl From<NetworkTopic> for IdentTopic {
fn from(topic: NetworkTopic) -> Self {
topic.0
}
}
impl From<PublicAddress> for NetworkTopic {
fn from(address: PublicAddress) -> Self {
Self(IdentTopic::new(conversions::base64_string(address)))
}
}
impl NetworkTopic {
pub fn new(topic: String) -> Self {
NetworkTopic(IdentTopic::new(topic))
}
pub fn hash(&self) -> libp2p::gossipsub::TopicHash {
self.0.hash()
}
}
#[cfg(test)]
mod test {
use super::*;
use libp2p::identity::Keypair;
#[test]
fn test_network_topic() {
let network_topic = NetworkTopic::new(String::from("new topic!"));
let topic_hash = network_topic.0.hash();
let ident_topic = IdentTopic::from(network_topic);
assert_eq!(ident_topic.hash(), topic_hash);
let test_public_address =
conversions::public_address(&Keypair::generate_ed25519().public()).unwrap();
let network_topic_from_address = NetworkTopic::from(test_public_address);
let network_topic = NetworkTopic::new(String::from(base64url::encode(test_public_address)));
assert_eq!(network_topic_from_address.hash(), network_topic.hash());
}
}