chore: follow up on nip-4e (#195)

* update deps

* .

* remove resend button

* clean up

* .

* .

* .

* .

* .
This commit is contained in:
reya
2025-10-28 14:37:30 +07:00
committed by GitHub
parent b5ed079a0e
commit b9297d3a01
21 changed files with 199 additions and 176 deletions

View File

@@ -15,7 +15,6 @@ use crate::constants::{
BOOTSTRAP_RELAYS, METADATA_BATCH_LIMIT, METADATA_BATCH_TIMEOUT, QUERY_TIMEOUT, SEARCH_RELAYS,
};
use crate::paths::config_dir;
use crate::state::device::Device;
use crate::state::ingester::Ingester;
use crate::state::tracker::EventTracker;
@@ -24,6 +23,7 @@ mod ingester;
mod signal;
mod tracker;
pub use device::*;
pub use signal::*;
#[derive(Debug)]
@@ -43,6 +43,9 @@ pub struct AppState {
/// Cache of messaging relays for each public key
pub relay_cache: RwLock<HashMap<PublicKey, HashSet<RelayUrl>>>,
/// Cache of device announcement for each public key
pub announcement_cache: RwLock<HashMap<PublicKey, Option<Announcement>>>,
/// NIP-4e: https://github.com/nostr-protocol/nips/blob/per-device-keys/4e.md
pub device: RwLock<Device>,
@@ -83,6 +86,7 @@ impl AppState {
let device = RwLock::new(Device::default());
let event_tracker = RwLock::new(EventTracker::default());
let relay_cache = RwLock::new(HashMap::default());
let announcement_cache = RwLock::new(HashMap::default());
let signal = Signal::default();
let ingester = Ingester::default();
@@ -92,6 +96,7 @@ impl AppState {
device,
event_tracker,
relay_cache,
announcement_cache,
signal,
ingester,
initialized_at: Timestamp::now(),
@@ -138,6 +143,9 @@ impl AppState {
// Get user's gossip relays
self.get_nip65(pk).await.ok();
// Initialize the relay and announcement caches
self.init_cache().await.ok();
// Initialize client keys
self.init_client_keys().await.ok();
@@ -236,12 +244,16 @@ impl AppState {
match event.kind {
// Encryption Keys announcement event
Kind::Custom(10044) => {
if let Ok(true) = self.is_self_authored(&event).await {
if let Ok(announcement) = self.extract_announcement(&event) {
if let Ok(announcement) = self.extract_announcement(&event) {
if let Ok(true) = self.is_self_authored(&event).await {
self.signal
.send(SignalKind::EncryptionSet(announcement))
.send(SignalKind::EncryptionSet(announcement.clone()))
.await;
}
// Cache the announcement for further queries
let mut announcement_cache = self.announcement_cache.write().await;
announcement_cache.insert(event.pubkey, Some(announcement));
}
}
// Encryption Keys request event
@@ -572,6 +584,33 @@ impl AppState {
Ok(())
}
/// Initialize the relay and announcement caches with events from the local database
pub async fn init_cache(&self) -> Result<(), Error> {
let filter = Filter::new().kind(Kind::InboxRelays);
let events = self.client.database().query(filter).await?;
let mut relay_cache = self.relay_cache.write().await;
for event in events.into_iter() {
let relays: Vec<RelayUrl> =
nip17::extract_relay_list(&event).take(3).cloned().collect();
// Push all relays to the relay cache
relay_cache.entry(event.pubkey).or_default().extend(relays);
}
let filter = Filter::new().kind(Kind::Custom(10044));
let events = self.client.database().query(filter).await?;
let mut announcement_cache = self.announcement_cache.write().await;
for event in events.into_iter() {
if let Ok(announcement) = self.extract_announcement(&event) {
announcement_cache.insert(event.pubkey, Some(announcement));
}
}
Ok(())
}
/// Initialize the client keys to communicate between clients
///
/// NIP-4e: https://github.com/nostr-protocol/nips/blob/per-device-keys/4e.md
@@ -961,7 +1000,7 @@ impl AppState {
// Subscribe to gift wrap events
self.client
.subscribe_with_id_to(urls, id, filter, None)
.subscribe_with_id_to(&urls, id, filter, None)
.await?;
Ok(())
@@ -1037,22 +1076,22 @@ impl AppState {
}
// Try to unwrap with the available signer
if let Ok(unwrapped) = self.try_unwrap_gift_wrap(gift_wrap).await {
let sender = unwrapped.sender;
let mut rumor_unsigned = unwrapped.rumor;
let unwrapped = self.try_unwrap_gift_wrap(gift_wrap).await?;
let sender = unwrapped.sender;
let mut rumor_unsigned = unwrapped.rumor;
if !self.verify_sender(sender, &rumor_unsigned).await {
return Err(anyhow!("Invalid rumor"));
};
if !self.verify_sender(sender, &rumor_unsigned).await {
return Err(anyhow!("Invalid rumor"));
};
// Generate event id for the rumor if it doesn't have one
rumor_unsigned.ensure_id();
// Generate event id for the rumor if it doesn't have one
rumor_unsigned.ensure_id();
self.set_rumor(gift_wrap.id, &rumor_unsigned).await?;
self.process_rumor(gift_wrap.id, rumor_unsigned).await?;
// Cache the rumor
self.set_rumor(gift_wrap.id, &rumor_unsigned).await?;
return Ok(());
}
// Process the rumor
self.process_rumor(gift_wrap.id, rumor_unsigned).await?;
Ok(())
}
@@ -1062,20 +1101,21 @@ impl AppState {
// Try to unwrap with the device's encryption keys first
// NIP-4e: https://github.com/nostr-protocol/nips/blob/per-device-keys/4e.md
if let Some(signer) = self.device.read().await.encryption.as_ref() {
if let Ok(unwrapped) = UnwrappedGift::from_gift_wrap(signer, gift_wrap).await {
return Ok(unwrapped);
match UnwrappedGift::from_gift_wrap(signer, gift_wrap).await {
Ok(unwrapped) => {
return Ok(unwrapped);
}
Err(e) => {
log::error!("Failed to unwrap with the encryption key: {e}")
}
}
}
// Get user's signer
let signer = self.client.signer().await?;
// Try to unwrap with the user's signer
if let Ok(unwrapped) = UnwrappedGift::from_gift_wrap(&signer, gift_wrap).await {
return Ok(unwrapped);
}
let signer = self.client.signer().await?;
let unwrapped = UnwrappedGift::from_gift_wrap(&signer, gift_wrap).await?;
Err(anyhow!("No signer available"))
Ok(unwrapped)
}
/// Process a rumor event.