From 49bd376d7974c9e5c08a1d4af84eba3947370ead Mon Sep 17 00:00:00 2001 From: benthecarman Date: Mon, 8 Apr 2024 13:44:43 -0500 Subject: [PATCH 1/4] Negate keys for claiming hermes keys when needed --- mutiny-core/src/federation.rs | 2 +- mutiny-core/src/hermes.rs | 22 ++++++++++++++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/mutiny-core/src/federation.rs b/mutiny-core/src/federation.rs index 3d642b0af..57406b667 100644 --- a/mutiny-core/src/federation.rs +++ b/mutiny-core/src/federation.rs @@ -646,7 +646,7 @@ impl FederationClient { self.logger, "External receive not found, maybe already claimed?" ); - return Ok(()); + return Err(MutinyError::NotFound); } for operation_id in operation_ids { diff --git a/mutiny-core/src/hermes.rs b/mutiny-core/src/hermes.rs index d33079fce..d3444178f 100644 --- a/mutiny-core/src/hermes.rs +++ b/mutiny-core/src/hermes.rs @@ -8,6 +8,7 @@ use std::{ use async_lock::RwLock; use bitcoin::hashes::hex::FromHex; +use bitcoin::key::Parity; use bitcoin::secp256k1::ThirtyTwoByteHash; use bitcoin::{bip32::ExtendedPrivKey, secp256k1::Secp256k1}; use fedimint_core::config::FederationId; @@ -16,6 +17,7 @@ use lightning::util::logger::Logger; use lightning::{log_error, log_info, log_warn}; use lightning_invoice::Bolt11Invoice; use nostr::prelude::decrypt_received_private_zap_message; +use nostr::secp256k1::SecretKey; use nostr::{nips::nip04::decrypt, Event, JsonUtil, Keys, Tag, ToBech32}; use nostr::{Filter, Kind, Timestamp}; use nostr_sdk::{Client, RelayPoolNotification}; @@ -58,6 +60,7 @@ pub struct RegisterResponse { pub struct HermesClient { pub(crate) dm_key: Keys, + claim_key: SecretKey, pub public_key: nostr::PublicKey, pub client: Client, http_client: reqwest::Client, @@ -102,8 +105,17 @@ impl HermesClient { .await .expect("Failed to add relays"); + // we use even parity on hermes side, need to check if we need to negate + let sec = keys.secret_key().expect("must have"); + let claim_key = if sec.x_only_public_key(&Secp256k1::new()).1 == Parity::Even { + sec.clone() + } else { + sec.negate().into() + }; + Ok(Self { dm_key: keys, + claim_key: *claim_key, public_key, client, http_client: reqwest::Client::new(), @@ -171,6 +183,7 @@ impl HermesClient { let stop = self.stop.clone(); let client = self.client.clone(); let public_key = self.public_key; + let claim_key = self.claim_key; let storage = self.storage.clone(); let dm_key = self.dm_key.clone(); let federations = self.federations.clone(); @@ -207,7 +220,7 @@ impl HermesClient { Kind::EncryptedDirectMessage => { match decrypt_ecash_notification(&dm_key, event.pubkey, &event.content) { Ok(notification) => { - if let Err(e) = handle_ecash_notification(notification, event.created_at, &federations, &storage, &dm_key, profile_key.as_ref(), &logger).await { + if let Err(e) = handle_ecash_notification(notification, event.created_at, &federations, &storage, &claim_key, profile_key.as_ref(), &logger).await { log_error!(logger, "Error handling ecash notification: {e}"); } }, @@ -426,7 +439,7 @@ async fn handle_ecash_notification( created_at: Timestamp, federations: &RwLock>>>, storage: &S, - dm_key: &Keys, + claim_key: &SecretKey, profile_key: Option<&Keys>, logger: &MutinyLogger, ) -> anyhow::Result<()> { @@ -438,10 +451,7 @@ async fn handle_ecash_notification( if let Some(federation) = federations.read().await.get(¬ification.federation_id) { match federation - .claim_external_receive( - dm_key.secret_key().expect("must have"), - vec![notification.tweak_index], - ) + .claim_external_receive(claim_key, vec![notification.tweak_index]) .await { Ok(_) => { From 7954a50a64cef619359bb43d790c4989e037ab63 Mon Sep 17 00:00:00 2001 From: benthecarman Date: Mon, 8 Apr 2024 14:07:03 -0500 Subject: [PATCH 2/4] Reset sync time --- mutiny-core/src/hermes.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mutiny-core/src/hermes.rs b/mutiny-core/src/hermes.rs index d3444178f..e6af7bb2d 100644 --- a/mutiny-core/src/hermes.rs +++ b/mutiny-core/src/hermes.rs @@ -135,7 +135,7 @@ impl HermesClient { pub fn start(&self, profile_key: Option) -> Result<(), MutinyError> { // if we haven't synced before, use now and save to storage let last_sync_time = self.storage.get_dm_sync_time(true)?; - let time_stamp = match last_sync_time { + let mut time_stamp = match last_sync_time { None => { let now = Timestamp::now(); self.storage.set_dm_sync_time(now.as_u64(), true)?; @@ -144,6 +144,11 @@ impl HermesClient { Some(time) => Timestamp::from(time + 1), // add one so we get only new events }; + // if we have a time stamp before the bug, reset to 0 + if time_stamp.as_u64() < 1712862315 { + time_stamp = Timestamp::from(0); + } + // check to see if we currently have an address let logger_check_clone = self.logger.clone(); let stop_check_clone = self.stop.clone(); From 6867f28b3d2955d1e80805a8f7809bfb22a6119b Mon Sep 17 00:00:00 2001 From: benthecarman Date: Mon, 8 Apr 2024 14:16:52 -0500 Subject: [PATCH 3/4] Maybe fixes panic? --- mutiny-core/src/hermes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mutiny-core/src/hermes.rs b/mutiny-core/src/hermes.rs index e6af7bb2d..758c4451d 100644 --- a/mutiny-core/src/hermes.rs +++ b/mutiny-core/src/hermes.rs @@ -561,7 +561,7 @@ fn handle_private_zap( logger: &MutinyLogger, ) -> Option<(PrivacyLevel, Option, Option)> { let key = match profile_key { - Some(k) => k.secret_key().unwrap(), + Some(k) => k.secret_key().ok()?, None => { log_error!(logger, "No primary key to decrypt private zap"); return None; From 0e78786af80471716b67122ac8e67b4e460dc939 Mon Sep 17 00:00:00 2001 From: Tony Giorgio Date: Mon, 8 Apr 2024 15:26:57 -0500 Subject: [PATCH 4/4] Check all hermes DMs after restore --- mutiny-core/src/hermes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mutiny-core/src/hermes.rs b/mutiny-core/src/hermes.rs index 758c4451d..f2c15a694 100644 --- a/mutiny-core/src/hermes.rs +++ b/mutiny-core/src/hermes.rs @@ -137,7 +137,7 @@ impl HermesClient { let last_sync_time = self.storage.get_dm_sync_time(true)?; let mut time_stamp = match last_sync_time { None => { - let now = Timestamp::now(); + let now = Timestamp::from(0); self.storage.set_dm_sync_time(now.as_u64(), true)?; now }