diff --git a/crates/bcr-ebill-api/src/service/company_service.rs b/crates/bcr-ebill-api/src/service/company_service.rs index 8ee095ad..297ee1ac 100644 --- a/crates/bcr-ebill-api/src/service/company_service.rs +++ b/crates/bcr-ebill-api/src/service/company_service.rs @@ -611,6 +611,12 @@ impl CompanyServiceApi for CompanyService { debug!("creating company by creator {}", creator_email); let company_keys = self.store.get_key_pair(&id).await?; + // Register the company's identity with the transport layer before any file uploads, + // so that file metadata can be published with the correct signer. + self.transport_service + .add_identity(&id, &company_keys) + .await?; + let full_identity = self.identity_store.get_full().await?; // company can only be created by identified identity if full_identity.identity.t == IdentityType::Anon { @@ -712,11 +718,6 @@ impl CompanyServiceApi for CompanyService { .add_block(&id, create_company_block) .await?; - self.transport_service - .block_transport() - .add_company_transport(&company, &company_keys) - .await?; - self.populate_block(&company, &company_chain, &company_keys, None) .await?; @@ -1591,6 +1592,12 @@ impl CompanyServiceApi for CompanyService { // update signatories list in the DB self.store.update(id, &company).await?; + // Ensure the company identity is registered with the transport layer before + // broadcasting chain events, in case it was lost (e.g. after restart). + self.transport_service + .add_identity(id, &company_keys) + .await?; + // company block let previous_block = company_chain.get_latest_block(); let new_block = CompanyBlock::create_block_for_accept_signatory_invite( @@ -2410,6 +2417,10 @@ pub mod tests { .expect_publish_file_metadata() .returning(|_, _, _, _, _| Ok(())) .times(1); + transport + .expect_add_identity() + .returning(|_, _| Ok(())) + .times(1); transport.expect_on_block_transport(|t| { t.expect_send_company_chain_events() .returning(|_| Ok(())) @@ -2417,9 +2428,6 @@ pub mod tests { t.expect_send_identity_chain_events() .returning(|_| Ok(())) .times(1); - t.expect_add_company_transport() - .returning(|_, _| Ok(())) - .times(1); }); transport.expect_on_contact_transport(|c| { c.expect_publish_contact().returning(|_, _| Ok(())); @@ -2472,7 +2480,7 @@ pub mod tests { contact_store, identity_chain_store, company_chain_store, - notification, + mut notification, nostr_contact_store, email_client, email_notification_store, @@ -2496,6 +2504,10 @@ pub mod tests { key_pair: BcrKeys::new(), }) }); + notification + .expect_add_identity() + .returning(|_, _| Ok(())) + .times(1); let service = get_service( storage, file_upload_store, @@ -3037,6 +3049,10 @@ pub mod tests { identity_chain_store .expect_add_block() .returning(|_| Ok(())); + transport + .expect_add_identity() + .returning(|_, _| Ok(())) + .times(1); let service = get_service( storage, diff --git a/crates/bcr-ebill-api/src/service/file_reference_helper.rs b/crates/bcr-ebill-api/src/service/file_reference_helper.rs index 1ca15f42..7b366a06 100644 --- a/crates/bcr-ebill-api/src/service/file_reference_helper.rs +++ b/crates/bcr-ebill-api/src/service/file_reference_helper.rs @@ -365,6 +365,7 @@ mod tests { async fn send_retry_messages(&self) -> crate::service::transport_service::Result<()>; async fn sync_relays(&self) -> crate::service::transport_service::Result<()>; async fn retry_failed_syncs(&self) -> crate::service::transport_service::Result<()>; + async fn add_identity(&self, node_id: &bcr_common::core::NodeId, keys: &bcr_ebill_core::protocol::crypto::BcrKeys) -> crate::service::transport_service::Result<()>; async fn publish_file_metadata(&self, node_id: &bcr_common::core::NodeId, plaintext_hash: &str, encrypted_hash: &str, server_urls: Vec, mime_type: Option) -> crate::service::transport_service::Result<()>; async fn query_file_metadata_events(&self, file_hash: &str, nostr_hash: &str) -> crate::service::transport_service::Result>; } diff --git a/crates/bcr-ebill-api/src/service/transport_service/block_transport.rs b/crates/bcr-ebill-api/src/service/transport_service/block_transport.rs index 09706350..0e210770 100644 --- a/crates/bcr-ebill-api/src/service/transport_service/block_transport.rs +++ b/crates/bcr-ebill-api/src/service/transport_service/block_transport.rs @@ -3,8 +3,6 @@ use async_trait::async_trait; use bcr_common::core::{BillId, NodeId}; use bcr_ebill_core::{ application::ServiceTraitBounds, - application::company::Company, - protocol::crypto::BcrKeys, protocol::event::{BillChainEvent, CompanyChainEvent, IdentityChainEvent}, }; @@ -17,8 +15,6 @@ use mockall::automock; #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] #[cfg_attr(not(target_arch = "wasm32"), async_trait)] pub trait BlockTransportServiceApi: ServiceTraitBounds { - /// Adds a new transport client for a company if it does not already exist - async fn add_company_transport(&self, company: &Company, keys: &BcrKeys) -> Result<()>; /// Sent when an identity chain is created or updated async fn send_identity_chain_events(&self, events: IdentityChainEvent) -> Result<()>; /// Sent when a company chain is created or updated diff --git a/crates/bcr-ebill-api/src/service/transport_service/transport.rs b/crates/bcr-ebill-api/src/service/transport_service/transport.rs index 8b1c02cc..08980372 100644 --- a/crates/bcr-ebill-api/src/service/transport_service/transport.rs +++ b/crates/bcr-ebill-api/src/service/transport_service/transport.rs @@ -10,6 +10,7 @@ use bcr_ebill_core::{ BitcreditBill, participant::{BillIdentParticipant, BillParticipant}, }, + protocol::crypto::BcrKeys, protocol::event::ActionType, protocol::event::BillChainEvent, }; @@ -131,6 +132,10 @@ pub trait TransportServiceApi: ServiceTraitBounds { /// Retries failed relay sync attempts async fn retry_failed_syncs(&self) -> Result<()>; + /// Adds a new identity (company keys) to the multi-identity client. + /// This will also add a subscription for direct messages to this identity. + async fn add_identity(&self, node_id: &NodeId, keys: &BcrKeys) -> Result<()>; + /// Publishes file metadata (kind:1063) for the specified file. /// This is idempotent - it will only publish if the server URLs have changed. async fn publish_file_metadata( diff --git a/crates/bcr-ebill-transport/src/block_transport.rs b/crates/bcr-ebill-transport/src/block_transport.rs index 5ff018df..5cb4b8f1 100644 --- a/crates/bcr-ebill-transport/src/block_transport.rs +++ b/crates/bcr-ebill-transport/src/block_transport.rs @@ -8,10 +8,8 @@ use async_trait::async_trait; use bcr_common::core::{BillId, NodeId}; use bcr_ebill_api::service::transport_service::BlockTransportServiceApi; use bcr_ebill_core::application::ServiceTraitBounds; -use bcr_ebill_core::application::company::Company; use bcr_ebill_core::protocol::Sha256Hash; use bcr_ebill_core::protocol::blockchain::BlockchainType; -use bcr_ebill_core::protocol::crypto::BcrKeys; use bcr_ebill_core::protocol::event::{ BillChainEvent, CompanyChainEvent, EventEnvelope, IdentityChainEvent, }; @@ -300,11 +298,6 @@ impl BlockTransportServiceApi for BlockTransportService { self.identity_chain_event_processor.resync_chain().await?; Ok(()) } - - /// Adds a new transport client for a company if it does not already exist - async fn add_company_transport(&self, company: &Company, keys: &BcrKeys) -> Result<()> { - self.nostr_transport.add_company_keys(company, keys).await - } } #[cfg(test)] diff --git a/crates/bcr-ebill-transport/src/handler/company_invite_handler.rs b/crates/bcr-ebill-transport/src/handler/company_invite_handler.rs index 433511d1..871fd865 100644 --- a/crates/bcr-ebill-transport/src/handler/company_invite_handler.rs +++ b/crates/bcr-ebill-transport/src/handler/company_invite_handler.rs @@ -85,7 +85,7 @@ impl NotificationHandlerApi for CompanyInviteEventHandler { break; } } - // we are onboarded to the chain so store all Nostr chain data also the invalid one + // we are onboarded to the chain so store all valid Nostr chain data if let Err(e) = self .store_events( &decoded.data.chain_id, diff --git a/crates/bcr-ebill-transport/src/nostr_transport.rs b/crates/bcr-ebill-transport/src/nostr_transport.rs index db5c2399..4db05301 100644 --- a/crates/bcr-ebill-transport/src/nostr_transport.rs +++ b/crates/bcr-ebill-transport/src/nostr_transport.rs @@ -5,7 +5,6 @@ use bcr_common::core::NodeId; use bcr_ebill_api::service::transport_service::transport_client::TransportClientApi; use bcr_ebill_api::util::validate_node_id_network; use bcr_ebill_core::application::ServiceTraitBounds; -use bcr_ebill_core::application::company::Company; use bcr_ebill_core::application::nostr_contact::TrustLevel; use bcr_ebill_core::protocol::Address; use bcr_ebill_core::protocol::City; @@ -140,11 +139,10 @@ impl NostrTransportService { } } - pub(crate) async fn add_company_keys(&self, company: &Company, keys: &BcrKeys) -> Result<()> { - let node_id = NodeId::new(keys.pub_key(), company.id.network()); - debug!("Adding company keys for node_id: {node_id}"); + pub(crate) async fn add_identity(&self, node_id: &NodeId, keys: &BcrKeys) -> Result<()> { + debug!("Adding identity for node_id: {node_id}"); self.nostr_client - .add_identity(node_id, keys.clone()) + .add_identity(node_id.clone(), keys.clone()) .await?; Ok(()) } diff --git a/crates/bcr-ebill-transport/src/test_utils.rs b/crates/bcr-ebill-transport/src/test_utils.rs index 69da1f74..9559599d 100644 --- a/crates/bcr-ebill-transport/src/test_utils.rs +++ b/crates/bcr-ebill-transport/src/test_utils.rs @@ -62,7 +62,6 @@ use bcr_ebill_api::service::transport_service::{ NotificationTransportServiceApi, Result, }; -use bcr_ebill_core::application::company::Company; use bcr_ebill_core::protocol::event::{ BillChainEvent, BillChainEventPayload, CompanyChainEvent, Event, IdentityChainEvent, }; @@ -468,7 +467,6 @@ mockall::mock! { #[async_trait] impl BlockTransportServiceApi for BlockTransportService { - async fn add_company_transport(&self, company: &Company, keys: &BcrKeys) -> Result<()>; async fn send_identity_chain_events(&self, events: IdentityChainEvent) -> Result<()>; async fn send_company_chain_events(&self, events: CompanyChainEvent) -> Result<()>; async fn send_bill_chain_events(&self, events: BillChainEvent) -> Result<()>; diff --git a/crates/bcr-ebill-transport/src/transport_service.rs b/crates/bcr-ebill-transport/src/transport_service.rs index ff9c0b66..4f09a8e3 100644 --- a/crates/bcr-ebill-transport/src/transport_service.rs +++ b/crates/bcr-ebill-transport/src/transport_service.rs @@ -10,6 +10,7 @@ use bcr_ebill_core::protocol::blockchain::bill::BitcreditBill; use bcr_ebill_core::protocol::blockchain::bill::participant::{ BillIdentParticipant, BillParticipant, }; +use bcr_ebill_core::protocol::crypto::BcrKeys; use bcr_ebill_core::protocol::event::{BillChainEvent, BillChainEventPayload, Event}; use super::nostr_transport::NostrTransportService; @@ -63,6 +64,10 @@ impl TransportServiceApi for TransportService { self.nostr_transport.connect().await; } + async fn add_identity(&self, node_id: &NodeId, keys: &BcrKeys) -> Result<()> { + self.nostr_transport.add_identity(node_id, keys).await + } + async fn send_bill_is_signed_event(&self, event: &BillChainEvent) -> Result<()> { let event_type = BillEventType::BillSigned; let sender = event.sender();