update nostr sdk
This commit is contained in:
@@ -2,6 +2,7 @@ use std::cell::Cell;
|
||||
use std::collections::HashSet;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{Context as AnyhowContext, Error, anyhow};
|
||||
@@ -11,7 +12,7 @@ use gpui::{
|
||||
};
|
||||
use nostr_sdk::prelude::*;
|
||||
use person::PersonRegistry;
|
||||
use state::{Announcement, NostrRegistry, StateEvent, TIMEOUT, app_name};
|
||||
use state::{Announcement, CoopSigner, NostrRegistry, StateEvent, TIMEOUT, app_name};
|
||||
use theme::ActiveTheme;
|
||||
use ui::avatar::Avatar;
|
||||
use ui::button::Button;
|
||||
@@ -110,6 +111,8 @@ impl DeviceRegistry {
|
||||
fn handle_notifications(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let nostr = NostrRegistry::global(cx);
|
||||
let client = nostr.read(cx).client();
|
||||
let signer = nostr.read(cx).signer();
|
||||
|
||||
let (tx, rx) = flume::bounded::<Event>(100);
|
||||
|
||||
self.tasks.push(cx.background_spawn(async move {
|
||||
@@ -127,12 +130,12 @@ impl DeviceRegistry {
|
||||
|
||||
match event.kind {
|
||||
Kind::Custom(4454) => {
|
||||
if verify_author(&client, event.as_ref()).await {
|
||||
if verify_author(&signer, event.as_ref()).await {
|
||||
tx.send_async(event.into_owned()).await?;
|
||||
}
|
||||
}
|
||||
Kind::Custom(4455) => {
|
||||
if verify_author(&client, event.as_ref()).await {
|
||||
if verify_author(&signer, event.as_ref()).await {
|
||||
tx.send_async(event.into_owned()).await?;
|
||||
}
|
||||
}
|
||||
@@ -181,7 +184,7 @@ impl DeviceRegistry {
|
||||
/// Set the decoupled encryption key for the current user
|
||||
fn set_signer<S>(&mut self, new: S, cx: &mut Context<Self>)
|
||||
where
|
||||
S: NostrSigner + 'static,
|
||||
S: AsyncNostrSigner,
|
||||
{
|
||||
let nostr = NostrRegistry::global(cx);
|
||||
let signer = nostr.read(cx).signer();
|
||||
@@ -203,9 +206,10 @@ impl DeviceRegistry {
|
||||
pub fn backup(&self, path: PathBuf, cx: &App) -> Task<Result<(), Error>> {
|
||||
let nostr = NostrRegistry::global(cx);
|
||||
let client = nostr.read(cx).client();
|
||||
let signer = nostr.read(cx).signer();
|
||||
|
||||
cx.background_spawn(async move {
|
||||
let keys = get_keys(&client).await?;
|
||||
let keys = get_keys(&client, &signer).await?;
|
||||
let content = keys.secret_key().to_bech32()?;
|
||||
|
||||
smol::fs::write(path, &content).await?;
|
||||
@@ -218,9 +222,10 @@ impl DeviceRegistry {
|
||||
pub fn get_announcement(&mut self, cx: &mut Context<Self>) {
|
||||
let nostr = NostrRegistry::global(cx);
|
||||
let client = nostr.read(cx).client();
|
||||
let signer = nostr.read(cx).signer();
|
||||
|
||||
let task: Task<Result<Event, Error>> = cx.background_spawn(async move {
|
||||
let signer = client.signer().context("Signer not found")?;
|
||||
let signer = signer.get().await;
|
||||
let public_key = signer.get_public_key().await?;
|
||||
|
||||
// Construct the filter for the device announcement event
|
||||
@@ -293,19 +298,24 @@ impl DeviceRegistry {
|
||||
fn create_encryption(&self, keys: Keys, cx: &App) -> Task<Result<Keys, Error>> {
|
||||
let nostr = NostrRegistry::global(cx);
|
||||
let client = nostr.read(cx).client();
|
||||
let signer = nostr.read(cx).signer();
|
||||
|
||||
let secret = keys.secret_key().to_secret_hex();
|
||||
let n = keys.public_key();
|
||||
|
||||
cx.background_spawn(async move {
|
||||
// Construct an announcement event
|
||||
let builder = EventBuilder::new(Kind::Custom(10044), "").tags(vec![
|
||||
Tag::custom(TagKind::custom("n"), vec![n]),
|
||||
Tag::client(app_name()),
|
||||
]);
|
||||
|
||||
// Sign the event with user's signer
|
||||
let event = client.sign_event_builder(builder).await?;
|
||||
let event = EventBuilder::new(Kind::Custom(10044), "")
|
||||
.tags(vec![
|
||||
Tag::custom("n", vec![n]),
|
||||
Nip89Tag::Client {
|
||||
name: app_name().to_string(),
|
||||
address: None,
|
||||
}
|
||||
.to_tag(),
|
||||
])
|
||||
.sign_async(&signer.get().await)
|
||||
.await?;
|
||||
|
||||
// Publish announcement
|
||||
client
|
||||
@@ -315,7 +325,7 @@ impl DeviceRegistry {
|
||||
.await?;
|
||||
|
||||
// Save device keys to the database
|
||||
set_keys(&client, &secret).await?;
|
||||
set_keys(&client, &signer, &secret).await?;
|
||||
|
||||
Ok(keys)
|
||||
})
|
||||
@@ -325,13 +335,14 @@ impl DeviceRegistry {
|
||||
fn set_encryption(&mut self, event: &Event, cx: &mut Context<Self>) {
|
||||
let nostr = NostrRegistry::global(cx);
|
||||
let client = nostr.read(cx).client();
|
||||
let signer = nostr.read(cx).signer();
|
||||
|
||||
let announcement = Announcement::from(event);
|
||||
let device_pubkey = announcement.public_key();
|
||||
|
||||
// Get encryption key from the database and compare with the announcement
|
||||
let task: Task<Result<Keys, Error>> = cx.background_spawn(async move {
|
||||
let keys = get_keys(&client).await?;
|
||||
let keys = get_keys(&client, &signer).await?;
|
||||
|
||||
// Compare the public key from the announcement with the one from the database
|
||||
if keys.public_key() != device_pubkey {
|
||||
@@ -403,14 +414,20 @@ impl DeviceRegistry {
|
||||
Some(event) => Ok(Some(event)),
|
||||
// No approval event found, construct a request event
|
||||
None => {
|
||||
// Construct an event for device key request
|
||||
let builder = EventBuilder::new(Kind::Custom(4454), "").tags(vec![
|
||||
Tag::custom(TagKind::custom("P"), vec![app_pubkey]),
|
||||
Tag::client(app_name()),
|
||||
]);
|
||||
let signer = signer.get().await;
|
||||
|
||||
// Sign the event with user's signer
|
||||
let event = client.sign_event_builder(builder).await?;
|
||||
// Construct an event for device key request
|
||||
let event = EventBuilder::new(Kind::Custom(4454), "")
|
||||
.tags(vec![
|
||||
Tag::custom("P", vec![app_pubkey]),
|
||||
Nip89Tag::Client {
|
||||
name: app_name().to_string(),
|
||||
address: None,
|
||||
}
|
||||
.to_tag(),
|
||||
])
|
||||
.sign_async(&signer)
|
||||
.await?;
|
||||
|
||||
// Send the event to write relays
|
||||
client.send_event(&event).to_nip65().await?;
|
||||
@@ -471,17 +488,19 @@ impl DeviceRegistry {
|
||||
fn extract_encryption(&mut self, event: Event, cx: &mut Context<Self>) {
|
||||
let nostr = NostrRegistry::global(cx);
|
||||
let app_keys = nostr.read(cx).keys();
|
||||
let app_signer: Arc<dyn AsyncNostrSigner> = Arc::new(app_keys);
|
||||
|
||||
let task: Task<Result<Keys, Error>> = cx.background_spawn(async move {
|
||||
let master = event
|
||||
.tags
|
||||
.find(TagKind::custom("P"))
|
||||
.iter()
|
||||
.find(|tag| tag.kind() == "P")
|
||||
.and_then(|tag| tag.content())
|
||||
.and_then(|content| PublicKey::parse(content).ok())
|
||||
.context("Invalid event's tags")?;
|
||||
|
||||
let payload = event.content.as_str();
|
||||
let decrypted = app_keys.nip44_decrypt(&master, payload).await?;
|
||||
let decrypted = app_signer.nip44_decrypt(&master, payload).await?;
|
||||
|
||||
let secret = SecretKey::from_hex(&decrypted)?;
|
||||
let keys = Keys::new(secret);
|
||||
@@ -510,6 +529,7 @@ impl DeviceRegistry {
|
||||
fn approve(&mut self, event: &Event, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let nostr = NostrRegistry::global(cx);
|
||||
let client = nostr.read(cx).client();
|
||||
let signer = nostr.read(cx).signer();
|
||||
|
||||
// Get user's write relays
|
||||
let event = event.clone();
|
||||
@@ -517,31 +537,36 @@ impl DeviceRegistry {
|
||||
|
||||
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
||||
// Get device keys
|
||||
let keys = get_keys(&client).await?;
|
||||
let keys = get_keys(&client, &signer).await?;
|
||||
let public_key = keys.public_key();
|
||||
let secret = keys.secret_key().to_secret_hex();
|
||||
let device_signer: Arc<dyn AsyncNostrSigner> = Arc::new(keys);
|
||||
|
||||
let signer = signer.get().await;
|
||||
|
||||
// Extract the target public key from the event tags
|
||||
let target = event
|
||||
.tags
|
||||
.find(TagKind::custom("P"))
|
||||
.iter()
|
||||
.find(|tag| tag.kind() == "P")
|
||||
.and_then(|tag| tag.content())
|
||||
.and_then(|content| PublicKey::parse(content).ok())
|
||||
.context("Target is not a valid public key")?;
|
||||
|
||||
// Encrypt the device keys with the user's signer
|
||||
let payload = keys.nip44_encrypt(&target, &secret).await?;
|
||||
let payload = device_signer.nip44_encrypt(&target, &secret).await?;
|
||||
|
||||
// Construct the response event
|
||||
//
|
||||
// P tag: the current device's public key
|
||||
// p tag: the requester's public key
|
||||
let builder = EventBuilder::new(Kind::Custom(4455), payload).tags(vec![
|
||||
Tag::custom(TagKind::custom("P"), vec![keys.public_key().to_hex()]),
|
||||
Tag::public_key(target),
|
||||
]);
|
||||
|
||||
// Sign the builder
|
||||
let event = client.sign_event_builder(builder).await?;
|
||||
let event = EventBuilder::new(Kind::Custom(4455), payload)
|
||||
.tags(vec![
|
||||
Tag::custom("P", vec![public_key.to_hex()]),
|
||||
Tag::public_key(target),
|
||||
])
|
||||
.sign_async(&signer)
|
||||
.await?;
|
||||
|
||||
// Send the response event to the user's relay list
|
||||
client.send_event(&event).to_nip65().await?;
|
||||
@@ -689,18 +714,15 @@ impl DeviceRegistry {
|
||||
struct DeviceNotification;
|
||||
|
||||
/// Verify the author of an event
|
||||
async fn verify_author(client: &Client, event: &Event) -> bool {
|
||||
if let Some(signer) = client.signer()
|
||||
&& let Ok(public_key) = signer.get_public_key().await
|
||||
{
|
||||
async fn verify_author(signer: &Arc<CoopSigner>, event: &Event) -> bool {
|
||||
if let Ok(public_key) = signer.get_public_key().await {
|
||||
return public_key == event.pubkey;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Encrypt and store device keys in the local database.
|
||||
async fn set_keys(client: &Client, secret: &str) -> Result<(), Error> {
|
||||
let signer = client.signer().context("Signer not found")?;
|
||||
async fn set_keys(client: &Client, signer: &Arc<CoopSigner>, secret: &str) -> Result<(), Error> {
|
||||
let public_key = signer.get_public_key().await?;
|
||||
|
||||
// Encrypt the value
|
||||
@@ -710,7 +732,7 @@ async fn set_keys(client: &Client, secret: &str) -> Result<(), Error> {
|
||||
let event = EventBuilder::new(Kind::ApplicationSpecificData, content)
|
||||
.tag(Tag::identifier(IDENTIFIER))
|
||||
.build(public_key)
|
||||
.sign(&Keys::generate())
|
||||
.sign_async(&Keys::generate())
|
||||
.await?;
|
||||
|
||||
// Save the event to the database
|
||||
@@ -720,8 +742,7 @@ async fn set_keys(client: &Client, secret: &str) -> Result<(), Error> {
|
||||
}
|
||||
|
||||
/// Get device keys from the local database.
|
||||
async fn get_keys(client: &Client) -> Result<Keys, Error> {
|
||||
let signer = client.signer().context("Signer not found")?;
|
||||
async fn get_keys(client: &Client, signer: &Arc<CoopSigner>) -> Result<Keys, Error> {
|
||||
let public_key = signer.get_public_key().await?;
|
||||
|
||||
let filter = Filter::new()
|
||||
|
||||
Reference in New Issue
Block a user