From 0f1fedaa3be1db9ca68bb299994031bec0b5aee2 Mon Sep 17 00:00:00 2001 From: Yuki Kishimoto Date: Mon, 18 Sep 2023 14:57:29 +0200 Subject: [PATCH] nostr: add `NEG-ERR` relay message --- crates/nostr/src/message/relay.rs | 91 ++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/crates/nostr/src/message/relay.rs b/crates/nostr/src/message/relay.rs index 744f4b3e1..f4f9b4057 100644 --- a/crates/nostr/src/message/relay.rs +++ b/crates/nostr/src/message/relay.rs @@ -6,9 +6,9 @@ use alloc::boxed::Box; use alloc::string::{String, ToString}; +use core::fmt; use bitcoin::secp256k1::{Secp256k1, Verification}; -#[cfg(feature = "std")] use serde::{Deserialize, Deserializer}; use serde::{Serialize, Serializer}; use serde_json::{json, Value}; @@ -18,6 +18,70 @@ use super::MessageHandleError; use crate::SECP256K1; use crate::{Event, EventId, SubscriptionId}; +/// Negentropy error code +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum NegentropyErrorCode { + /// Results too big + ResultsTooBig, + /// Because the NEG-OPEN queries are stateful, relays may choose to time-out inactive queries to recover memory resources + Closed, + /// If an event ID is used as the filter, this error will be returned if the relay does not have this event. + /// The client should retry with the full filter, or upload the event to the relay. + FilterNotFound, + /// The event's content was not valid JSON, or the filter was invalid for some other reason. + FilterInvalid, + /// Other + Other(String), +} + +impl fmt::Display for NegentropyErrorCode { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::ResultsTooBig => write!(f, "RESULTS_TOO_BIG"), + Self::Closed => write!(f, "CLOSED"), + Self::FilterNotFound => write!(f, "FILTER_NOT_FOUND"), + Self::FilterInvalid => write!(f, "FILTER_INVALID"), + Self::Other(e) => write!(f, "{e}"), + } + } +} + +impl From for NegentropyErrorCode +where + S: Into, +{ + fn from(code: S) -> Self { + let code: String = code.into(); + match code.as_str() { + "RESULTS_TOO_BIG" => Self::ResultsTooBig, + "CLOSED" => Self::Closed, + "FILTER_NOT_FOUND" => Self::FilterNotFound, + "FILTER_INVALID" => Self::FilterInvalid, + o => Self::Other(o.to_string()), + } + } +} + +impl Serialize for NegentropyErrorCode { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&self.to_string()) + } +} + +impl<'de> Deserialize<'de> for NegentropyErrorCode { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let value = Value::deserialize(deserializer)?; + let alphaber: String = serde_json::from_value(value).map_err(serde::de::Error::custom)?; + Ok(Self::from(alphaber)) + } +} + /// Messages sent by relays, received by clients #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum RelayMessage { @@ -63,6 +127,13 @@ pub enum RelayMessage { /// Message message: String, }, + /// Negentropy Error + NegErr { + /// Subscription ID + subscription_id: SubscriptionId, + /// Error code + code: NegentropyErrorCode, + }, } impl Serialize for RelayMessage { @@ -164,6 +235,10 @@ impl RelayMessage { subscription_id, message, } => json!(["NEG-MSG", subscription_id, message]), + Self::NegErr { + subscription_id, + code, + } => json!(["NEG-ERR", subscription_id, code]), } } @@ -291,6 +366,20 @@ impl RelayMessage { }); } + // Negentropy Error + // ["NEG-ERR", , ] + if v[0] == "NEG-ERR" { + if v_len != 3 { + return Err(MessageHandleError::InvalidMessageFormat); + } + let subscription_id: SubscriptionId = SubscriptionId::new(v[1].to_string()); + let code: NegentropyErrorCode = NegentropyErrorCode::from(v[2].to_string()); + return Ok(Self::NegErr { + subscription_id, + code, + }); + } + Err(MessageHandleError::InvalidMessageFormat) }