Skip to content

Commit

Permalink
nostr: add PartialEvent struct
Browse files Browse the repository at this point in the history
  • Loading branch information
yukibtc committed Oct 16, 2023
1 parent 8bb77e2 commit 47bd617
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 1 deletion.
2 changes: 2 additions & 0 deletions crates/nostr/src/event/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ use serde_json::Value;
pub mod builder;
pub mod id;
pub mod kind;
pub mod partial;
pub mod tag;
pub mod unsigned;

pub use self::builder::EventBuilder;
pub use self::id::EventId;
pub use self::kind::Kind;
pub use self::partial::PartialEvent;
pub use self::tag::{Marker, Tag, TagKind};
pub use self::unsigned::UnsignedEvent;
#[cfg(feature = "std")]
Expand Down
83 changes: 83 additions & 0 deletions crates/nostr/src/event/partial.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright (c) 2022-2023 Yuki Kishimoto
// Distributed under the MIT software license

//! Partial Event for fast deserialization and signature verification
use core::fmt;

use bitcoin::secp256k1::schnorr::Signature;
use bitcoin::secp256k1::{self, Message, Secp256k1, Verification, XOnlyPublicKey};

#[cfg(feature = "std")]
use crate::SECP256K1;
use crate::{EventId, JsonUtil};

/// [`PartialEvent`] error
#[derive(Debug)]
pub enum Error {
/// Error serializing or deserializing JSON data
Json(serde_json::Error),
/// Secp256k1 error
Secp256k1(secp256k1::Error),
/// Invalid signature
InvalidSignature,
}

#[cfg(feature = "std")]
impl std::error::Error for Error {}

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Json(e) => write!(f, "Json: {e}"),
Self::Secp256k1(e) => write!(f, "Secp256k1: {e}"),
Self::InvalidSignature => write!(f, "Invalid signature"),
}
}
}

impl From<serde_json::Error> for Error {
fn from(e: serde_json::Error) -> Self {
Self::Json(e)
}
}

impl From<secp256k1::Error> for Error {
fn from(e: secp256k1::Error) -> Self {
Self::Secp256k1(e)
}
}

/// Partial event
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct PartialEvent {
/// Id
pub id: EventId,
/// Author
pub pubkey: XOnlyPublicKey,
/// Signature
pub sig: Signature,
}

impl PartialEvent {
/// Verify [`Signature`]
#[cfg(feature = "std")]
pub fn verify_signature(&self) -> Result<(), Error> {
self.verify_signature_with_ctx(&SECP256K1)
}

/// Verify [`Signature`]
pub fn verify_signature_with_ctx<C>(&self, secp: &Secp256k1<C>) -> Result<(), Error>
where
C: Verification,
{
// Verify signature
let message = Message::from_slice(self.id.as_bytes())?;
secp.verify_schnorr(&self.sig, &message, &self.pubkey)
.map_err(|_| Error::InvalidSignature)
}
}

impl JsonUtil for PartialEvent {
type Err = Error;
}
2 changes: 1 addition & 1 deletion crates/nostr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub use self::event::tag::{
ExternalIdentity, HttpMethod, Identity, ImageDimensions, Marker, RelayMetadata, Report, Tag,
TagKind,
};
pub use self::event::{Event, EventBuilder, EventId, Kind, UnsignedEvent};
pub use self::event::{Event, EventBuilder, EventId, Kind, PartialEvent, UnsignedEvent};
pub use self::key::Keys;
pub use self::message::{
Alphabet, ClientMessage, Filter, RawRelayMessage, RelayMessage, SubscriptionId,
Expand Down

0 comments on commit 47bd617

Please sign in to comment.