Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MMR tag: add merkle mountain range tag #108

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/nostr/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ nip19 = ["dep:bech32"]
nip21 = ["nip19"]
nip46 = ["nip04"]
nip47 = ["nip04"]
mmr = []

[dependencies]
aes = { version = "0.8", optional = true }
Expand Down
50 changes: 47 additions & 3 deletions crates/nostr/src/event/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@

//! Event builder

#[cfg(feature = "mmr")]
use bitcoin_hashes::sha256::Hash;
use core::fmt;
#[cfg(not(target_arch = "wasm32"))]
use std::time::Instant;

#[cfg(target_arch = "wasm32")]
use instant::Instant;
use secp256k1::XOnlyPublicKey;
use serde_json::{json, Value};
#[cfg(not(target_arch = "wasm32"))]
use std::time::Instant;
use url::Url;

pub use super::kind::Kind;
Expand Down Expand Up @@ -169,6 +170,49 @@ impl EventBuilder {
tags.pop();
}
}

/// Build MMR [`Event`]
#[cfg(feature = "mmr")]
pub fn to_mmr_event(
self,
keys: &Keys,
prev_event_hash: Hash,
prev_mmr_root: Hash,
prev_event_pos: i64,
) -> Result<Event, Error> {
let pubkey: XOnlyPublicKey = keys.public_key();
Ok(self
.to_unsigned_mmr_event(pubkey, prev_event_hash, prev_mmr_root, prev_event_pos)
.sign(keys)?)
}

/// Build unsigned MMR [`Event`]
#[cfg(feature = "mmr")]
pub fn to_unsigned_mmr_event(
self,
pubkey: XOnlyPublicKey,
prev_event_id: Hash,
prev_mmr_root: Hash,
prev_event_pos: i64,
) -> UnsignedEvent {
let mut tags: Vec<Tag> = self.tags;
tags.push(Tag::Mmr {
prev_event_id,
prev_mmr_root,
prev_event_pos,
});
let created_at: Timestamp = Timestamp::now();
let id = EventId::new(&pubkey, created_at, &self.kind, &tags, &self.content);
// TODO verify if valid MMR append operation for vector commitment
UnsignedEvent {
id,
pubkey,
created_at,
kind: self.kind,
tags,
content: self.content,
}
}
}

impl EventBuilder {
Expand Down
36 changes: 36 additions & 0 deletions crates/nostr/src/event/tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use core::fmt;
use core::num::ParseIntError;
use core::str::FromStr;

#[cfg(feature = "mmr")]
use bitcoin_hashes::sha256::Hash;
use secp256k1::schnorr::Signature;
use secp256k1::XOnlyPublicKey;
use serde::de::Error as DeserializerError;
Expand Down Expand Up @@ -242,6 +244,9 @@ pub enum TagKind {
Lnurl,
/// Name tag
Name,
#[cfg(feature = "mmr")]
/// Merkle mountain range
Mmr,
/// Custom tag kind
Custom(String),
}
Expand Down Expand Up @@ -275,6 +280,8 @@ impl fmt::Display for TagKind {
Self::Amount => write!(f, "amount"),
Self::Lnurl => write!(f, "lnurl"),
Self::Name => write!(f, "name"),
#[cfg(feature = "mmr")]
Self::Mmr => write!(f, "mmr"),
Self::Custom(tag) => write!(f, "{tag}"),
}
}
Expand Down Expand Up @@ -313,6 +320,8 @@ where
"amount" => Self::Amount,
"lnurl" => Self::Lnurl,
"name" => Self::Name,
#[cfg(feature = "mmr")]
"mmr" => Self::Mmr,
tag => Self::Custom(tag.to_string()),
}
}
Expand Down Expand Up @@ -370,6 +379,12 @@ pub enum Tag {
Lnurl(String),
Name(String),
PublishedAt(Timestamp),
#[cfg(feature = "mmr")]
Mmr {
prev_event_id: Hash,
prev_mmr_root: Hash,
prev_event_pos: i64,
},
}

impl Tag {
Expand Down Expand Up @@ -420,6 +435,8 @@ impl Tag {
Tag::Amount(..) => TagKind::Amount,
Tag::Name(..) => TagKind::Name,
Tag::Lnurl(..) => TagKind::Lnurl,
#[cfg(feature = "mmr")]
Tag::Mmr { .. } => TagKind::Mmr,
}
}
}
Expand Down Expand Up @@ -581,6 +598,12 @@ where
conditions: Conditions::from_str(&tag[2])?,
sig: Signature::from_str(&tag[3])?,
}),
#[cfg(feature = "mmr")]
TagKind::Mmr => Ok(Self::Mmr {
prev_event_id: Hash::from_str(tag[1].as_str())?,
prev_mmr_root: Hash::from_str(tag[2].as_str())?,
prev_event_pos: i64::from_str(tag[3].as_str())?,
}),
_ => Ok(Self::Generic(tag_kind, tag[1..].to_vec())),
}
} else {
Expand Down Expand Up @@ -726,6 +749,19 @@ impl From<Tag> for Vec<String> {
Tag::Lnurl(lnurl) => {
vec![TagKind::Lnurl.to_string(), lnurl]
}
#[cfg(feature = "mmr")]
Tag::Mmr {
prev_event_id,
prev_mmr_root,
prev_event_pos,
} => {
vec![
TagKind::Mmr.to_string(),
prev_event_id.to_string(),
prev_mmr_root.to_string(),
prev_event_pos.to_string(),
]
}
}
}
}
Expand Down