Skip to content

Commit

Permalink
nostr: remove event verification from deserialization constructors
Browse files Browse the repository at this point in the history
  • Loading branch information
yukibtc committed Sep 29, 2023
1 parent 1371314 commit 4542282
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 120 deletions.
11 changes: 3 additions & 8 deletions crates/nostr/src/event/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -876,9 +876,8 @@ mod tests {
#[cfg(feature = "std")]
use core::str::FromStr;

use bitcoin::secp256k1::Secp256k1;
#[cfg(feature = "std")]
use bitcoin::secp256k1::SecretKey;
use bitcoin::secp256k1::{Secp256k1, SecretKey};

use super::*;

Expand Down Expand Up @@ -935,14 +934,12 @@ mod tests {

#[test]
fn test_zap_event_builder() {
let secp = Secp256k1::new();

let bolt11 = String::from("lnbc10u1p3unwfusp5t9r3yymhpfqculx78u027lxspgxcr2n2987mx2j55nnfs95nxnzqpp5jmrh92pfld78spqs78v9euf2385t83uvpwk9ldrlvf6ch7tpascqhp5zvkrmemgth3tufcvflmzjzfvjt023nazlhljz2n9hattj4f8jq8qxqyjw5qcqpjrzjqtc4fc44feggv7065fqe5m4ytjarg3repr5j9el35xhmtfexc42yczarjuqqfzqqqqqqqqlgqqqqqqgq9q9qxpqysgq079nkq507a5tw7xgttmj4u990j7wfggtrasah5gd4ywfr2pjcn29383tphp4t48gquelz9z78p4cq7ml3nrrphw5w6eckhjwmhezhnqpy6gyf0");
let preimage = Some(String::from(
"5d006d2cf1e73c7148e7519a4c68adc81642ce0e25a432b2434c99f97344c15f",
));
let zap_request_json = String::from("{\"pubkey\":\"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245\",\"content\":\"\",\"id\":\"d9cc14d50fcb8c27539aacf776882942c1a11ea4472f8cdec1dea82fab66279d\",\"created_at\":1674164539,\"sig\":\"77127f636577e9029276be060332ea565deaf89ff215a494ccff16ae3f757065e2bc59b2e8c113dd407917a010b3abd36c8d7ad84c0e3ab7dab3a0b0caa9835d\",\"kind\":9734,\"tags\":[[\"e\",\"3624762a1274dd9636e0c552b53086d70bc88c165bc4dc0f9e836a1eaf86c3b8\"],[\"p\",\"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245\"],[\"relays\",\"wss://relay.damus.io\",\"wss://nostr-relay.wlvs.space\",\"wss://nostr.fmt.wiz.biz\",\"wss://relay.nostr.bg\",\"wss://nostr.oxtr.dev\",\"wss://nostr.v0l.io\",\"wss://brb.io\",\"wss://nostr.bitcoiner.social\",\"ws://monad.jb55.com:8080\",\"wss://relay.snort.social\"]]}");
let zap_request_event: Event = Event::from_json_with_ctx(&secp, zap_request_json).unwrap();
let zap_request_event: Event = Event::from_json(zap_request_json).unwrap();
let event_builder = EventBuilder::new_zap_receipt(bolt11, preimage, zap_request_event);

assert_eq!(5, event_builder.tags.len());
Expand All @@ -959,12 +956,10 @@ mod tests {

#[test]
fn test_zap_event_builder_without_preimage() {
let secp = Secp256k1::new();

let bolt11 = String::from("lnbc10u1p3unwfusp5t9r3yymhpfqculx78u027lxspgxcr2n2987mx2j55nnfs95nxnzqpp5jmrh92pfld78spqs78v9euf2385t83uvpwk9ldrlvf6ch7tpascqhp5zvkrmemgth3tufcvflmzjzfvjt023nazlhljz2n9hattj4f8jq8qxqyjw5qcqpjrzjqtc4fc44feggv7065fqe5m4ytjarg3repr5j9el35xhmtfexc42yczarjuqqfzqqqqqqqqlgqqqqqqgq9q9qxpqysgq079nkq507a5tw7xgttmj4u990j7wfggtrasah5gd4ywfr2pjcn29383tphp4t48gquelz9z78p4cq7ml3nrrphw5w6eckhjwmhezhnqpy6gyf0");
let preimage = None;
let zap_request_json = String::from("{\"pubkey\":\"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245\",\"content\":\"\",\"id\":\"d9cc14d50fcb8c27539aacf776882942c1a11ea4472f8cdec1dea82fab66279d\",\"created_at\":1674164539,\"sig\":\"77127f636577e9029276be060332ea565deaf89ff215a494ccff16ae3f757065e2bc59b2e8c113dd407917a010b3abd36c8d7ad84c0e3ab7dab3a0b0caa9835d\",\"kind\":9734,\"tags\":[[\"e\",\"3624762a1274dd9636e0c552b53086d70bc88c165bc4dc0f9e836a1eaf86c3b8\"],[\"p\",\"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245\"],[\"relays\",\"wss://relay.damus.io\",\"wss://nostr-relay.wlvs.space\",\"wss://nostr.fmt.wiz.biz\",\"wss://relay.nostr.bg\",\"wss://nostr.oxtr.dev\",\"wss://nostr.v0l.io\",\"wss://brb.io\",\"wss://nostr.bitcoiner.social\",\"ws://monad.jb55.com:8080\",\"wss://relay.snort.social\"]]}");
let zap_request_event = Event::from_json_with_ctx(&secp, zap_request_json).unwrap();
let zap_request_event = Event::from_json(zap_request_json).unwrap();
let event_builder = EventBuilder::new_zap_receipt(bolt11, preimage, zap_request_event);

assert_eq!(4, event_builder.tags.len());
Expand Down
73 changes: 26 additions & 47 deletions crates/nostr/src/event/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,18 +115,40 @@ pub struct Event {
}

impl Event {
/// Verify event
/// Deserialize [`Event`] from [`Value`]
///
/// **This method NOT verify the signature!**
pub fn from_value(value: Value) -> Result<Self, Error> {
Ok(serde_json::from_value(value)?)
}

/// Deserialize [`Event`] from JSON
///
/// **This method NOT verify the signature!**
pub fn from_json<S>(json: S) -> Result<Self, Error>
where
S: Into<String>,
{
Ok(serde_json::from_str(&json.into())?)
}

/// Serialize [`Event`] as JSON
pub fn as_json(&self) -> String {
serde_json::json!(self).to_string()
}

/// Verify [`EventId`] and [`Signature`]
#[cfg(feature = "std")]
pub fn verify(&self) -> Result<(), Error> {
self.verify_with_ctx(&SECP256K1)
}

/// Verify event
/// Verify [`EventId`] and [`Signature`]
pub fn verify_with_ctx<C>(&self, secp: &Secp256k1<C>) -> Result<(), Error>
where
C: Verification,
{
let id = EventId::new(
let id: EventId = EventId::new(
&self.pubkey,
self.created_at,
&self.kind,
Expand All @@ -142,47 +164,6 @@ impl Event {
}
}

/// New event from [`Value`]
#[cfg(feature = "std")]
pub fn from_value(value: Value) -> Result<Self, Error> {
Self::from_value_with_ctx(&SECP256K1, value)
}

/// New event from [`Value`]
pub fn from_value_with_ctx<C>(secp: &Secp256k1<C>, value: Value) -> Result<Self, Error>
where
C: Verification,
{
let event: Self = serde_json::from_value(value)?;
event.verify_with_ctx(secp)?;
Ok(event)
}

/// New event from json string
#[cfg(feature = "std")]
pub fn from_json<S>(json: S) -> Result<Self, Error>
where
S: Into<String>,
{
Self::from_json_with_ctx(&SECP256K1, json)
}

/// New event from json string
pub fn from_json_with_ctx<C, S>(secp: &Secp256k1<C>, json: S) -> Result<Self, Error>
where
C: Verification,
S: Into<String>,
{
let event: Self = serde_json::from_str(&json.into())?;
event.verify_with_ctx(secp)?;
Ok(event)
}

/// Get event as json string
pub fn as_json(&self) -> String {
serde_json::json!(self).to_string()
}

/// Returns `true` if the event has an expiration tag that is expired.
/// If an event has no `Expiration` tag, then it will return `false`.
#[cfg(feature = "std")]
Expand Down Expand Up @@ -283,11 +264,9 @@ mod tests {

#[test]
fn test_tags_deser_without_recommended_relay() {
let secp = Secp256k1::new();

//The TAG array has dynamic length because the third element(Recommended relay url) is optional
let sample_event = r#"{"content":"uRuvYr585B80L6rSJiHocw==?iv=oh6LVqdsYYol3JfFnXTbPA==","created_at":1640839235,"id":"2be17aa3031bdcb006f0fce80c146dea9c1c0268b0af2398bb673365c6444d45","kind":4,"pubkey":"f86c44a2de95d9149b51c6a29afeabba264c18e2fa7c49de93424a0c56947785","sig":"a5d9290ef9659083c490b303eb7ee41356d8778ff19f2f91776c8dc4443388a64ffcf336e61af4c25c05ac3ae952d1ced889ed655b67790891222aaa15b99fdd","tags":[["p","13adc511de7e1cfcf1c6b7f6365fb5a03442d7bcacf565ea57fa7770912c023d"]]}"#;
let ev_ser = Event::from_json_with_ctx(&secp, sample_event).unwrap();
let ev_ser = Event::from_json(sample_event).unwrap();
assert_eq!(ev_ser.as_json(), sample_event);
}

Expand Down
4 changes: 1 addition & 3 deletions crates/nostr/src/event/tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1304,11 +1304,9 @@ mod tests {

#[test]
fn test_deserialize_tag_from_event() {
let secp = Secp256k1::new();

// Got this fresh off the wire
let event: &str = r#"{"id":"2be17aa3031bdcb006f0fce80c146dea9c1c0268b0af2398bb673365c6444d45","pubkey":"f86c44a2de95d9149b51c6a29afeabba264c18e2fa7c49de93424a0c56947785","created_at":1640839235,"kind":4,"tags":[["p","13adc511de7e1cfcf1c6b7f6365fb5a03442d7bcacf565ea57fa7770912c023d"]],"content":"uRuvYr585B80L6rSJiHocw==?iv=oh6LVqdsYYol3JfFnXTbPA==","sig":"a5d9290ef9659083c490b303eb7ee41356d8778ff19f2f91776c8dc4443388a64ffcf336e61af4c25c05ac3ae952d1ced889ed655b67790891222aaa15b99fdd"}"#;
let event = Event::from_json_with_ctx(&secp, event).unwrap();
let event = Event::from_json(event).unwrap();
let tag = event.tags.first().unwrap();

assert_eq!(
Expand Down
41 changes: 8 additions & 33 deletions crates/nostr/src/message/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,13 @@ use alloc::boxed::Box;
use alloc::string::{String, ToString};
use alloc::vec::Vec;

use bitcoin::secp256k1::{Secp256k1, Verification};
use negentropy::{Bytes, Negentropy};
#[cfg(feature = "std")]
use serde::{Deserialize, Deserializer};
use serde::{Serialize, Serializer};
use serde_json::{json, Value};

use super::{Filter, MessageHandleError, SubscriptionId};
use crate::Event;
#[cfg(feature = "std")]
use crate::SECP256K1;

/// Messages sent by clients, received by relays
#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -80,7 +76,6 @@ impl Serialize for ClientMessage {
}
}

#[cfg(feature = "std")]
impl<'de> Deserialize<'de> for ClientMessage {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
Expand Down Expand Up @@ -217,19 +212,9 @@ impl ClientMessage {
}

/// Deserialize from [`Value`]
#[cfg(feature = "std")]
///
/// **This method NOT verify the event signature!**
pub fn from_value(msg: Value) -> Result<Self, MessageHandleError> {
Self::from_value_with_ctx(&SECP256K1, msg)
}

/// Deserialize from [`Value`]
pub fn from_value_with_ctx<C>(
secp: &Secp256k1<C>,
msg: Value,
) -> Result<Self, MessageHandleError>
where
C: Verification,
{
let v = msg
.as_array()
.ok_or(MessageHandleError::InvalidMessageFormat)?;
Expand All @@ -246,7 +231,7 @@ impl ClientMessage {
if v_len != 2 {
return Err(MessageHandleError::InvalidMessageFormat);
}
let event = Event::from_json_with_ctx(secp, v[1].to_string())?;
let event = Event::from_value(v[1].clone())?;
return Ok(Self::new_event(event));
}

Expand Down Expand Up @@ -297,7 +282,7 @@ impl ClientMessage {
if v_len != 2 {
return Err(MessageHandleError::InvalidMessageFormat);
}
let event = Event::from_json_with_ctx(secp, v[1].to_string())?;
let event = Event::from_value(v[1].clone())?;
return Ok(Self::new_auth(event));
}

Expand Down Expand Up @@ -349,19 +334,11 @@ impl ClientMessage {
}

/// Deserialize [`ClientMessage`] from JSON string
#[cfg(feature = "std")]
///
/// **This method NOT verify the event signature!**
pub fn from_json<S>(msg: S) -> Result<Self, MessageHandleError>
where
S: Into<String>,
{
Self::from_json_with_ctx(&SECP256K1, msg)
}

/// Deserialize [`ClientMessage`] from JSON string
pub fn from_json_with_ctx<C, S>(secp: &Secp256k1<C>, msg: S) -> Result<Self, MessageHandleError>
where
C: Verification,
S: Into<String>,
{
let msg: &str = &msg.into();
tracing::trace!("{}", msg);
Expand All @@ -371,7 +348,7 @@ impl ClientMessage {
}

let value: Value = serde_json::from_str(msg)?;
Self::from_value_with_ctx(secp, value)
Self::from_value(value)
}
}

Expand Down Expand Up @@ -423,8 +400,6 @@ mod tests {

#[test]
fn test_negative_timestamp() {
let secp = Secp256k1::new();

let req = json!([
"REQ",
"some_id",
Expand All @@ -441,7 +416,7 @@ mod tests {
}
]);

let msg = ClientMessage::from_value_with_ctx(&secp, req.clone()).unwrap();
let msg = ClientMessage::from_value(req.clone()).unwrap();

assert_eq!(msg.as_value(), req)
}
Expand Down
32 changes: 3 additions & 29 deletions crates/nostr/src/message/relay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,11 @@ use alloc::boxed::Box;
use alloc::string::{String, ToString};
use core::fmt;

use bitcoin::secp256k1::{Secp256k1, Verification};
use serde::{Deserialize, Deserializer};
use serde::{Serialize, Serializer};
use serde_json::{json, Value};

use super::MessageHandleError;
#[cfg(feature = "std")]
use crate::SECP256K1;
use crate::{Event, EventId, SubscriptionId};

/// Negentropy error code
Expand Down Expand Up @@ -146,7 +143,6 @@ impl Serialize for RelayMessage {
}
}

#[cfg(feature = "std")]
impl<'de> Deserialize<'de> for RelayMessage {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
Expand Down Expand Up @@ -248,19 +244,7 @@ impl RelayMessage {
}

/// Deserialize [`RelayMessage`] from [`Value`]
#[cfg(feature = "std")]
fn from_value(msg: Value) -> Result<Self, MessageHandleError> {
Self::from_value_with_ctx(&SECP256K1, msg)
}

/// Deserialize [`RelayMessage`] from [`Value`]
pub fn from_value_with_ctx<C>(
secp: &Secp256k1<C>,
msg: Value,
) -> Result<Self, MessageHandleError>
where
C: Verification,
{
pub fn from_value(msg: Value) -> Result<Self, MessageHandleError> {
let v = msg
.as_array()
.ok_or(MessageHandleError::InvalidMessageFormat)?;
Expand Down Expand Up @@ -289,7 +273,7 @@ impl RelayMessage {
}

let subscription_id: SubscriptionId = serde_json::from_value(v[1].clone())?;
let event = Event::from_json_with_ctx(secp, v[2].to_string())?;
let event = Event::from_value(v[2].clone())?;

return Ok(Self::new_event(subscription_id, event));
}
Expand Down Expand Up @@ -381,19 +365,9 @@ impl RelayMessage {
}

/// Deserialize [`RelayMessage`] as JSON string
#[cfg(feature = "std")]
pub fn from_json<S>(msg: S) -> Result<Self, MessageHandleError>
where
S: Into<String>,
{
Self::from_json_with_ctx(&SECP256K1, msg)
}

/// Deserialize [`RelayMessage`] as JSON string
pub fn from_json_with_ctx<C, S>(secp: &Secp256k1<C>, msg: S) -> Result<Self, MessageHandleError>
where
C: Verification,
S: Into<String>,
{
let msg: &str = &msg.into();
tracing::trace!("{}", msg);
Expand All @@ -403,7 +377,7 @@ impl RelayMessage {
}

let value: Value = serde_json::from_str(msg)?;
Self::from_value_with_ctx(secp, value)
Self::from_value(value)
}
}

Expand Down

0 comments on commit 4542282

Please sign in to comment.