use alloc::string::String;
use alloc::vec::Vec;
use core::fmt;
use bitcoin::secp256k1::schnorr::Signature;
use bitcoin::secp256k1::{self, Message, Secp256k1, Verification};
use super::raw::{self, RawEvent};
use super::tag;
#[cfg(feature = "std")]
use crate::SECP256K1;
use crate::{Event, EventId, JsonUtil, Kind, PublicKey, Tag, Timestamp};
#[derive(Debug)]
pub enum Error {
Json(serde_json::Error),
Secp256k1(secp256k1::Error),
RawEvent(raw::Error),
Tag(tag::Error),
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::RawEvent(e) => write!(f, "Raw event: {e}"),
Self::Tag(e) => write!(f, "Tag: {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)
}
}
impl From<raw::Error> for Error {
fn from(e: raw::Error) -> Self {
Self::RawEvent(e)
}
}
impl From<tag::Error> for Error {
fn from(e: tag::Error) -> Self {
Self::Tag(e)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct PartialEvent {
pub id: EventId,
pub pubkey: PublicKey,
pub sig: Signature,
}
impl PartialEvent {
pub fn from_raw(raw: &RawEvent) -> Result<Self, Error> {
Ok(raw.try_into()?)
}
#[cfg(feature = "std")]
pub fn verify_signature(&self) -> Result<(), Error> {
self.verify_signature_with_ctx(&SECP256K1)
}
pub fn verify_signature_with_ctx<C>(&self, secp: &Secp256k1<C>) -> Result<(), Error>
where
C: Verification,
{
let message = Message::from_slice(self.id.as_bytes())?;
secp.verify_schnorr(&self.sig, &message, &self.pubkey)
.map_err(|_| Error::InvalidSignature)
}
pub fn merge(&self, missing: MissingPartialEvent) -> Result<Event, Error> {
let mut tags: Vec<Tag> = Vec::with_capacity(missing.tags.len());
for tag in missing.tags.into_iter() {
tags.push(Tag::parse(tag)?);
}
Ok(Event::new(
self.id,
self.pubkey,
missing.created_at,
missing.kind,
tags,
missing.content,
self.sig,
))
}
}
impl JsonUtil for PartialEvent {
type Err = Error;
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct MissingPartialEvent {
pub created_at: Timestamp,
pub kind: Kind,
pub tags: Vec<Vec<String>>,
pub content: String,
}
impl MissingPartialEvent {
pub fn from_raw(raw: RawEvent) -> Self {
Self {
created_at: Timestamp::from(raw.created_at),
kind: Kind::from(raw.kind),
tags: raw.tags,
content: raw.content,
}
}
pub fn identifier(&self) -> Option<&str> {
for tag in self.tags.iter() {
if let Some("d") = tag.first().map(|x| x.as_str()) {
return tag.get(1).map(|x| x.as_str());
}
}
None
}
}
impl JsonUtil for MissingPartialEvent {
type Err = Error;
}