use signer trait
This commit is contained in:
+11
-8
@@ -14,7 +14,7 @@ use gpui::{
|
|||||||
use instant::Duration;
|
use instant::Duration;
|
||||||
use nostr_sdk::prelude::*;
|
use nostr_sdk::prelude::*;
|
||||||
use smallvec::{SmallVec, smallvec};
|
use smallvec::{SmallVec, smallvec};
|
||||||
use state::{DEVICE_GIFTWRAP, NostrRegistry, USER_GIFTWRAP, UniversalSigner};
|
use state::{DEVICE_GIFTWRAP, NostrRegistry, USER_GIFTWRAP};
|
||||||
|
|
||||||
mod message;
|
mod message;
|
||||||
mod room;
|
mod room;
|
||||||
@@ -740,11 +740,14 @@ impl ChatRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Unwraps a gift-wrapped event and processes its contents.
|
/// Unwraps a gift-wrapped event and processes its contents.
|
||||||
async fn extract_rumor(
|
async fn extract_rumor<S>(
|
||||||
client: &Client,
|
client: &Client,
|
||||||
signer: &UniversalSigner,
|
signer: &S,
|
||||||
gift_wrap: &Event,
|
gift_wrap: &Event,
|
||||||
) -> Result<UnsignedEvent, Error> {
|
) -> Result<UnsignedEvent, Error>
|
||||||
|
where
|
||||||
|
S: AsyncNip44 + ?Sized,
|
||||||
|
{
|
||||||
// Try to get cached rumor first
|
// Try to get cached rumor first
|
||||||
if let Ok(rumor) = get_rumor(client, gift_wrap.id).await {
|
if let Ok(rumor) = get_rumor(client, gift_wrap.id).await {
|
||||||
return Ok(rumor);
|
return Ok(rumor);
|
||||||
@@ -771,10 +774,10 @@ async fn extract_rumor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to unwrap a gift wrap event with a given signer.
|
/// Attempts to unwrap a gift wrap event with a given signer.
|
||||||
async fn try_unwrap_with(
|
async fn try_unwrap_with<S>(signer: &S, gift_wrap: &Event) -> Result<UnwrappedGift, Error>
|
||||||
signer: &UniversalSigner,
|
where
|
||||||
gift_wrap: &Event,
|
S: AsyncNip44 + ?Sized,
|
||||||
) -> Result<UnwrappedGift, Error> {
|
{
|
||||||
// Get the sealed event
|
// Get the sealed event
|
||||||
let seal = signer
|
let seal = signer
|
||||||
.nip44_decrypt_async(&gift_wrap.pubkey, &gift_wrap.content)
|
.nip44_decrypt_async(&gift_wrap.pubkey, &gift_wrap.content)
|
||||||
|
|||||||
+24
-21
@@ -10,7 +10,7 @@ use itertools::Itertools;
|
|||||||
use nostr_sdk::prelude::*;
|
use nostr_sdk::prelude::*;
|
||||||
use person::{Person, PersonRegistry};
|
use person::{Person, PersonRegistry};
|
||||||
use settings::{RoomConfig, SignerKind};
|
use settings::{RoomConfig, SignerKind};
|
||||||
use state::{NostrRegistry, TIMEOUT, UniversalSigner};
|
use state::{NostrRegistry, TIMEOUT};
|
||||||
|
|
||||||
use crate::{FileAttachment, KIND_FILE_MESSAGE, NewMessage};
|
use crate::{FileAttachment, KIND_FILE_MESSAGE, NewMessage};
|
||||||
|
|
||||||
@@ -473,31 +473,28 @@ impl Room {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Select the appropriate signer based on signer kind and available keys.
|
/// Select the appropriate signer based on signer kind and available keys.
|
||||||
fn select_signer(
|
fn select_signer<'a, S>(
|
||||||
signer_kind: &SignerKind,
|
signer_kind: &SignerKind,
|
||||||
has_announcement: bool,
|
has_announcement: bool,
|
||||||
encryption_signer: &Option<UniversalSigner>,
|
encryption_signer: &'a Option<S>,
|
||||||
user_signer: &UniversalSigner,
|
user_signer: &'a S,
|
||||||
) -> UniversalSigner {
|
) -> &'a S {
|
||||||
match signer_kind {
|
match signer_kind {
|
||||||
SignerKind::Auto => {
|
SignerKind::Auto => {
|
||||||
if has_announcement {
|
if has_announcement {
|
||||||
encryption_signer
|
encryption_signer.as_ref().unwrap_or(user_signer)
|
||||||
.clone()
|
|
||||||
.unwrap_or_else(|| user_signer.clone())
|
|
||||||
} else {
|
} else {
|
||||||
user_signer.clone()
|
user_signer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SignerKind::Encryption => encryption_signer
|
SignerKind::Encryption => encryption_signer
|
||||||
.clone()
|
.as_ref()
|
||||||
.expect("encryption signer must be set"),
|
.expect("encryption signer must be set"),
|
||||||
SignerKind::User => user_signer.clone(),
|
SignerKind::User => user_signer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send the rumor to every member's messaging relays
|
/// Send the rumor to every member's messaging relays.
|
||||||
/// and to the sender as a backup, when enabled.
|
|
||||||
pub fn send(&self, rumor: UnsignedEvent, cx: &App) -> Option<Task<Vec<SendReport>>> {
|
pub fn send(&self, rumor: UnsignedEvent, cx: &App) -> Option<Task<Vec<SendReport>>> {
|
||||||
let config = self.config.clone();
|
let config = self.config.clone();
|
||||||
|
|
||||||
@@ -558,14 +555,17 @@ impl Room {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Deliver a rumor to a single receiver.
|
/// Deliver a rumor to a single receiver.
|
||||||
async fn deliver(
|
async fn deliver<S>(
|
||||||
client: &Client,
|
client: &Client,
|
||||||
signer_kind: &SignerKind,
|
signer_kind: &SignerKind,
|
||||||
receiver: Person,
|
receiver: Person,
|
||||||
rumor: &UnsignedEvent,
|
rumor: &UnsignedEvent,
|
||||||
encryption_signer: &Option<UniversalSigner>,
|
encryption_signer: &Option<S>,
|
||||||
user_signer: &UniversalSigner,
|
user_signer: &S,
|
||||||
) -> SendReport {
|
) -> SendReport
|
||||||
|
where
|
||||||
|
S: AsyncGetPublicKey + AsyncSignEvent + AsyncNip44,
|
||||||
|
{
|
||||||
let public_key = receiver.public_key();
|
let public_key = receiver.public_key();
|
||||||
let announcement = receiver.announcement();
|
let announcement = receiver.announcement();
|
||||||
|
|
||||||
@@ -595,7 +595,7 @@ async fn deliver(
|
|||||||
user_signer,
|
user_signer,
|
||||||
);
|
);
|
||||||
|
|
||||||
match send_gift_wrap(client, &signer, &receiver, rumor, signer_kind).await {
|
match send_gift_wrap(client, signer, &receiver, rumor, signer_kind).await {
|
||||||
Ok(output) => SendReport {
|
Ok(output) => SendReport {
|
||||||
receiver: public_key,
|
receiver: public_key,
|
||||||
result: Ok(output),
|
result: Ok(output),
|
||||||
@@ -608,13 +608,16 @@ async fn deliver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Build the gift-wrapped event for a rumor and send it.
|
/// Build the gift-wrapped event for a rumor and send it.
|
||||||
async fn send_gift_wrap(
|
async fn send_gift_wrap<S>(
|
||||||
client: &Client,
|
client: &Client,
|
||||||
signer: &UniversalSigner,
|
signer: &S,
|
||||||
receiver: &Person,
|
receiver: &Person,
|
||||||
rumor: &UnsignedEvent,
|
rumor: &UnsignedEvent,
|
||||||
config: &SignerKind,
|
config: &SignerKind,
|
||||||
) -> Result<Output<EventId, EventSendStatus>, Error> {
|
) -> Result<Output<EventId, EventSendStatus>, Error>
|
||||||
|
where
|
||||||
|
S: AsyncGetPublicKey + AsyncSignEvent + AsyncNip44,
|
||||||
|
{
|
||||||
let mut extra_tags = vec![Tag::custom("k", [rumor.kind.to_string()])];
|
let mut extra_tags = vec![Tag::custom("k", [rumor.kind.to_string()])];
|
||||||
|
|
||||||
// Determine the receiver public key based on the config
|
// Determine the receiver public key based on the config
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ use concord::derive::{GroupKey, channel_rekey_group_key, epoch_key_commitment};
|
|||||||
use concord::state::{CommunityState, HeldKey};
|
use concord::state::{CommunityState, HeldKey};
|
||||||
use concord::{ChannelId, CommunityId, Epoch};
|
use concord::{ChannelId, CommunityId, Epoch};
|
||||||
use nostr_sdk::prelude::*;
|
use nostr_sdk::prelude::*;
|
||||||
use state::UniversalSigner;
|
|
||||||
|
|
||||||
use crate::sync::{self, PlaneKind};
|
use crate::sync::{self, PlaneKind};
|
||||||
|
|
||||||
@@ -175,13 +174,16 @@ pub struct ChannelAdoption {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Read every rekey wrap the local database holds and adopt what is admissible.
|
/// Read every rekey wrap the local database holds and adopt what is admissible.
|
||||||
pub async fn adopt(
|
pub async fn adopt<S>(
|
||||||
client: &Client,
|
client: &Client,
|
||||||
state: &CommunityState,
|
state: &CommunityState,
|
||||||
roles: &CommunityRoles,
|
roles: &CommunityRoles,
|
||||||
signer: &UniversalSigner,
|
signer: &S,
|
||||||
me: PublicKey,
|
me: PublicKey,
|
||||||
) -> Result<Adoptions> {
|
) -> Result<Adoptions>
|
||||||
|
where
|
||||||
|
S: AsyncNip44 + ?Sized,
|
||||||
|
{
|
||||||
let watches = watches(state)?;
|
let watches = watches(state)?;
|
||||||
|
|
||||||
let mut authors: BTreeSet<PublicKey> = BTreeSet::new();
|
let mut authors: BTreeSet<PublicKey> = BTreeSet::new();
|
||||||
@@ -362,15 +364,18 @@ impl Rewrite {
|
|||||||
|
|
||||||
/// Publish this client's own rotation of one scope to its next epoch.
|
/// Publish this client's own rotation of one scope to its next epoch.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub async fn rotate(
|
pub async fn rotate<S>(
|
||||||
client: &Client,
|
client: &Client,
|
||||||
state: &CommunityState,
|
state: &CommunityState,
|
||||||
roles: &CommunityRoles,
|
roles: &CommunityRoles,
|
||||||
signer: &UniversalSigner,
|
signer: &S,
|
||||||
me: PublicKey,
|
me: PublicKey,
|
||||||
rewrite: &Rewrite,
|
rewrite: &Rewrite,
|
||||||
at: Timestamp,
|
at: Timestamp,
|
||||||
) -> Result<Epoch> {
|
) -> Result<Epoch>
|
||||||
|
where
|
||||||
|
S: AsyncGetPublicKey + AsyncSignEvent + AsyncNip44 + ?Sized,
|
||||||
|
{
|
||||||
if rewrite.excluded.contains(&me) {
|
if rewrite.excluded.contains(&me) {
|
||||||
bail!("a rotation cannot cut off the member who publishes it");
|
bail!("a rotation cannot cut off the member who publishes it");
|
||||||
}
|
}
|
||||||
@@ -611,18 +616,21 @@ struct Delivery {
|
|||||||
|
|
||||||
/// Walk a scope's rotations forward, one epoch at a time, off the key held.
|
/// Walk a scope's rotations forward, one epoch at a time, off the key held.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
async fn walk(
|
async fn walk<S>(
|
||||||
scope: RekeyScope,
|
scope: RekeyScope,
|
||||||
permissions: &[u64],
|
permissions: &[u64],
|
||||||
mut held_epoch: Epoch,
|
mut held_epoch: Epoch,
|
||||||
mut held_key: [u8; 32],
|
mut held_key: [u8; 32],
|
||||||
state: &CommunityState,
|
state: &CommunityState,
|
||||||
roles: &CommunityRoles,
|
roles: &CommunityRoles,
|
||||||
signer: &UniversalSigner,
|
signer: &S,
|
||||||
me: PublicKey,
|
me: PublicKey,
|
||||||
rotations: &[Rotation],
|
rotations: &[Rotation],
|
||||||
published: &BTreeMap<RotationKey, u64>,
|
published: &BTreeMap<RotationKey, u64>,
|
||||||
) -> Result<Step> {
|
) -> Result<Step>
|
||||||
|
where
|
||||||
|
S: AsyncNip44 + ?Sized,
|
||||||
|
{
|
||||||
let mut step = Step::default();
|
let mut step = Step::default();
|
||||||
let mut stepped: Vec<HeldKey> = Vec::new();
|
let mut stepped: Vec<HeldKey> = Vec::new();
|
||||||
let ceiling = held_epoch.0 + REKEY_LOOKAHEAD;
|
let ceiling = held_epoch.0 + REKEY_LOOKAHEAD;
|
||||||
@@ -794,6 +802,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
use concord::state::{ChannelKeyRef, HeldRoot};
|
use concord::state::{ChannelKeyRef, HeldRoot};
|
||||||
use nostr_memory::MemoryDatabase;
|
use nostr_memory::MemoryDatabase;
|
||||||
|
use state::UniversalSigner;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ use concord::state::{CommunityState, HeldKey, HeldRoot, list_entry};
|
|||||||
use concord::{ChannelId, CommunityId, Epoch, GroupKey, decode_hex_32};
|
use concord::{ChannelId, CommunityId, Epoch, GroupKey, decode_hex_32};
|
||||||
use gpui::AsyncApp;
|
use gpui::AsyncApp;
|
||||||
use nostr_sdk::prelude::*;
|
use nostr_sdk::prelude::*;
|
||||||
use state::UniversalSigner;
|
|
||||||
|
|
||||||
use crate::cache::{self, Observed};
|
use crate::cache::{self, Observed};
|
||||||
use crate::history::{CURSOR_OVERLAP, Window};
|
use crate::history::{CURSOR_OVERLAP, Window};
|
||||||
@@ -348,11 +347,10 @@ pub async fn subscribe_list(client: &Client, self_pk: PublicKey) -> Result<()> {
|
|||||||
///
|
///
|
||||||
/// A held membership is dropped only when the List carries a tombstone at least
|
/// A held membership is dropped only when the List carries a tombstone at least
|
||||||
/// as new as it, because absence from the List is never a fact (§8).
|
/// as new as it, because absence from the List is never a fact (§8).
|
||||||
pub async fn load(
|
pub async fn load<S>(client: &Client, signer: &S, self_pk: PublicKey) -> Result<Vec<CommunityState>>
|
||||||
client: &Client,
|
where
|
||||||
signer: &UniversalSigner,
|
S: AsyncGetPublicKey + AsyncNip44 + ?Sized,
|
||||||
self_pk: PublicKey,
|
{
|
||||||
) -> Result<Vec<CommunityState>> {
|
|
||||||
let list = match load_list(client, signer, self_pk).await? {
|
let list = match load_list(client, signer, self_pk).await? {
|
||||||
Some(list) => list,
|
Some(list) => list,
|
||||||
None => return cache::load_states(client).await,
|
None => return cache::load_states(client).await,
|
||||||
@@ -735,6 +733,7 @@ mod tests {
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use nostr_memory::MemoryDatabase;
|
use nostr_memory::MemoryDatabase;
|
||||||
|
use state::UniversalSigner;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
|||||||
@@ -759,7 +759,10 @@ fn get_or_init_app_keys(cx: &App) -> Task<Result<Keys, Error>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Encrypt and store device keys in the local database.
|
/// Encrypt and store device keys in the local database.
|
||||||
async fn set_keys(client: &Client, signer: &UniversalSigner, secret: &str) -> Result<(), Error> {
|
async fn set_keys<S>(client: &Client, signer: &S, secret: &str) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
S: AsyncGetPublicKey + AsyncSignEvent + AsyncNip44 + ?Sized,
|
||||||
|
{
|
||||||
let public_key = signer.get_public_key_async().await?;
|
let public_key = signer.get_public_key_async().await?;
|
||||||
let content = signer.nip44_encrypt_async(&public_key, secret).await?;
|
let content = signer.nip44_encrypt_async(&public_key, secret).await?;
|
||||||
|
|
||||||
@@ -776,7 +779,10 @@ async fn set_keys(client: &Client, signer: &UniversalSigner, secret: &str) -> Re
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get device keys from the local database.
|
/// Get device keys from the local database.
|
||||||
async fn get_keys(client: &Client, signer: &UniversalSigner) -> Result<Keys, Error> {
|
async fn get_keys<S>(client: &Client, signer: &S) -> Result<Keys, Error>
|
||||||
|
where
|
||||||
|
S: AsyncGetPublicKey + AsyncNip44 + ?Sized,
|
||||||
|
{
|
||||||
let public_key = signer.get_public_key_async().await?;
|
let public_key = signer.get_public_key_async().await?;
|
||||||
|
|
||||||
let filter = Filter::new()
|
let filter = Filter::new()
|
||||||
|
|||||||
Reference in New Issue
Block a user