diff --git a/base_layer/chat_ffi/chat.h b/base_layer/chat_ffi/chat.h index 7117f6df17e..635d2558430 100644 --- a/base_layer/chat_ffi/chat.h +++ b/base_layer/chat_ffi/chat.h @@ -490,6 +490,7 @@ void destroy_conversationalists_vector(struct ConversationalistsVector *ptr); * The ```Message``` received should be destroyed after use */ struct Message *create_chat_message(struct TariAddress *receiver, + struct TariAddress *sender, const char *message, int *error_out); @@ -587,7 +588,7 @@ struct ChatByteVector *read_chat_message_body(struct Message *message, int *erro * `message` should be destroyed eventually * the returned `TariAddress` should be destroyed eventually */ -struct TariAddress *read_chat_message_address(struct Message *message, int *error_out); +struct TariAddress *read_chat_message_from_address(struct Message *message, int *error_out); /** * Returns a c_uchar representation of the Direction enum diff --git a/base_layer/chat_ffi/src/callback_handler.rs b/base_layer/chat_ffi/src/callback_handler.rs index 1c1e0268dd9..ae11f9e3275 100644 --- a/base_layer/chat_ffi/src/callback_handler.rs +++ b/base_layer/chat_ffi/src/callback_handler.rs @@ -134,7 +134,7 @@ impl CallbackHandler { debug!( target: LOG_TARGET, "Calling MessageReceived callback function for sender {}", - message.address, + message.from_address, ); unsafe { diff --git a/base_layer/chat_ffi/src/message.rs b/base_layer/chat_ffi/src/message.rs index 99eba1d2e1e..cb335b965a9 100644 --- a/base_layer/chat_ffi/src/message.rs +++ b/base_layer/chat_ffi/src/message.rs @@ -50,6 +50,7 @@ use crate::{ #[no_mangle] pub unsafe extern "C" fn create_chat_message( receiver: *mut TariAddress, + sender: *mut TariAddress, message: *const c_char, error_out: *mut c_int, ) -> *mut Message { @@ -60,6 +61,10 @@ pub unsafe extern "C" fn create_chat_message( error = LibChatError::from(InterfaceError::NullError("receiver".to_string())).code; ptr::swap(error_out, &mut error as *mut c_int); } + if sender.is_null() { + error = LibChatError::from(InterfaceError::NullError("sender".to_string())).code; + ptr::swap(error_out, &mut error as *mut c_int); + } let message_str = match CStr::from_ptr(message).to_str() { Ok(str) => str.to_string(), @@ -71,7 +76,8 @@ pub unsafe extern "C" fn create_chat_message( }; let message_out = MessageBuilder::new() - .address((*receiver).clone()) + .to_address((*receiver).clone()) + .from_address((*sender).clone()) .message(message_str) .build(); @@ -259,7 +265,10 @@ pub unsafe extern "C" fn read_chat_message_body(message: *mut Message, error_out /// `message` should be destroyed eventually /// the returned `TariAddress` should be destroyed eventually #[no_mangle] -pub unsafe extern "C" fn read_chat_message_address(message: *mut Message, error_out: *mut c_int) -> *mut TariAddress { +pub unsafe extern "C" fn read_chat_message_from_address( + message: *mut Message, + error_out: *mut c_int, +) -> *mut TariAddress { let mut error = 0; ptr::swap(error_out, &mut error as *mut c_int); @@ -269,7 +278,7 @@ pub unsafe extern "C" fn read_chat_message_address(message: *mut Message, error_ return ptr::null_mut(); } - let address = (*message).address.clone(); + let address = (*message).from_address.clone(); Box::into_raw(Box::new(address)) } @@ -513,17 +522,22 @@ mod test { #[test] fn test_reading_message_address() { - let address = + let to_address = TariAddress::from_hex("0c017c5cd01385f34ac065e3b05948326dc55d2494f120c6f459a07389011b4ec1").unwrap(); - let message = MessageBuilder::new().address(address.clone()).build(); + let from_address = + TariAddress::from_hex("3e596f98f6904f0fc1c8685e2274bd8b2c445d5dac284a9398d09a0e9a760436d0").unwrap(); + let message = MessageBuilder::new() + .to_address(to_address.clone()) + .from_address(from_address.clone()) + .build(); let message_ptr = Box::into_raw(Box::new(message)); let error_out = Box::into_raw(Box::new(0)); unsafe { - let address_ptr = read_chat_message_address(message_ptr, error_out); + let address_ptr = read_chat_message_from_address(message_ptr, error_out); - assert_eq!(address.to_bytes(), (*address_ptr).to_bytes()); + assert_eq!(from_address.to_bytes(), (*address_ptr).to_bytes()); destroy_chat_message(message_ptr); destroy_tari_address(address_ptr); diff --git a/base_layer/chat_ffi/src/message_metadata.rs b/base_layer/chat_ffi/src/message_metadata.rs index b5a7b776117..ebdcf9fb884 100644 --- a/base_layer/chat_ffi/src/message_metadata.rs +++ b/base_layer/chat_ffi/src/message_metadata.rs @@ -211,7 +211,8 @@ mod test { let message_ptr = Box::into_raw(Box::new( MessageBuilder::new() .message("hello".to_string()) - .address(address) + .to_address(address.clone()) + .from_address(address) .build(), )); let error_out = Box::into_raw(Box::new(0)); diff --git a/base_layer/common_types/src/wallet_types.rs b/base_layer/common_types/src/wallet_types.rs index a152b4bcda6..80fd197cb01 100644 --- a/base_layer/common_types/src/wallet_types.rs +++ b/base_layer/common_types/src/wallet_types.rs @@ -19,8 +19,9 @@ // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#[cfg(feature = "ledger")] +use std::convert::TryFrom; use std::{ - convert::TryFrom, fmt, fmt::{Display, Formatter}, }; diff --git a/base_layer/contacts/migrations/2024-05-27-145100_add_from_to_fields/up.sql b/base_layer/contacts/migrations/2024-05-27-145100_add_from_to_fields/up.sql deleted file mode 100644 index 6d00a18aa9d..00000000000 --- a/base_layer/contacts/migrations/2024-05-27-145100_add_from_to_fields/up.sql +++ /dev/null @@ -1,3 +0,0 @@ - ALTER TABLE messages ADD to_address BLOB NOT NULL; - ALTER TABLE messages ADD from_address BLOB NOT NULL; - ALTER TABLE messages DROP address; \ No newline at end of file diff --git a/base_layer/contacts/migrations/2024-05-27-145200_add_from_to_fields/up.sql b/base_layer/contacts/migrations/2024-05-27-145200_add_from_to_fields/up.sql new file mode 100644 index 00000000000..35feeaaee7c --- /dev/null +++ b/base_layer/contacts/migrations/2024-05-27-145200_add_from_to_fields/up.sql @@ -0,0 +1,9 @@ +DROP INDEX idx_messages_address; + +ALTER TABLE messages DROP address; + +ALTER TABLE messages ADD to_address BLOB NOT NULL; +ALTER TABLE messages ADD from_address BLOB NOT NULL; + +CREATE INDEX idx_messages_to_address ON messages (to_address); +CREATE INDEX idx_messages_from_address ON messages (from_address); diff --git a/base_layer/contacts/proto/message.proto b/base_layer/contacts/proto/message.proto index 92c3b7d7fcb..3ccf44ebd12 100644 --- a/base_layer/contacts/proto/message.proto +++ b/base_layer/contacts/proto/message.proto @@ -7,9 +7,10 @@ package tari.contacts.chat; message Message { bytes body = 1; repeated MessageMetadata metadata = 2; - bytes address = 3; - DirectionEnum direction = 4; - bytes message_id = 5; + bytes to_address = 3; + bytes from_address = 4; + DirectionEnum direction = 5; + bytes message_id = 6; } enum DirectionEnum { diff --git a/base_layer/contacts/src/chat_client/src/client.rs b/base_layer/contacts/src/chat_client/src/client.rs index b00d572145c..d200d593706 100644 --- a/base_layer/contacts/src/chat_client/src/client.rs +++ b/base_layer/contacts/src/chat_client/src/client.rs @@ -195,7 +195,7 @@ impl ChatClient for Client { async fn send_read_receipt(&self, message: Message) -> Result<(), Error> { if let Some(mut contacts_service) = self.contacts.clone() { contacts_service - .send_read_confirmation(message.address.clone(), message.message_id) + .send_read_confirmation(message.from_address.clone(), message.message_id) .await?; } @@ -203,7 +203,11 @@ impl ChatClient for Client { } fn create_message(&self, receiver: &TariAddress, message: String) -> Message { - MessageBuilder::new().address(receiver.clone()).message(message).build() + MessageBuilder::new() + .to_address(receiver.clone()) + .from_address(self.address().clone()) + .message(message) + .build() } fn add_metadata(&self, mut message: Message, key: String, data: String) -> Message { diff --git a/base_layer/contacts/src/contacts_service/service.rs b/base_layer/contacts/src/contacts_service/service.rs index bd31c80b26f..f7689d07c8e 100644 --- a/base_layer/contacts/src/contacts_service/service.rs +++ b/base_layer/contacts/src/contacts_service/service.rs @@ -582,11 +582,10 @@ where T: ContactsBackend + 'static message: Message, source_public_key: CommsPublicKey, ) -> Result<(), ContactsServiceError> { - if source_public_key != *message.from_address.public_spend_key() { + if source_public_key != *message.from_address.public_key() { return Err(ContactsServiceError::MessageSourceDoesNotMatchOrigin); } let our_message = Message { - address: TariAddress::from_public_key(&source_public_key, message.address.network()), stored_at: EpochTime::now().as_u64(), ..message }; @@ -617,7 +616,7 @@ where T: ContactsBackend + 'static &mut self, message: &Message, ) -> Result<(), ContactsServiceError> { - let address = &message.address; + let address = &message.from_address; let confirmation = MessageDispatch::DeliveryConfirmation(Confirmation { message_id: message.message_id.clone(), timestamp: message.stored_at, diff --git a/base_layer/contacts/src/contacts_service/storage/types/messages.rs b/base_layer/contacts/src/contacts_service/storage/types/messages.rs index 372b69eb77f..c56fdf65ffa 100644 --- a/base_layer/contacts/src/contacts_service/storage/types/messages.rs +++ b/base_layer/contacts/src/contacts_service/storage/types/messages.rs @@ -113,6 +113,20 @@ impl MessagesSql { .load::(conn)?) } + pub fn find_by_address( + address: &[u8], + limit: i64, + page: i64, + conn: &mut SqliteConnection, + ) -> Result, ContactsServiceStorageError> { + Ok(messages::table + .filter(messages::from_address.eq(address).or(messages::to_address.eq(address))) + .order(messages::stored_at.desc()) + .offset(limit * page) + .limit(limit) + .load::(conn)?) + } + /// Find a particular message by its message_id pub fn find_by_message_id( message_id: &[u8], @@ -140,7 +154,7 @@ impl MessagesSql { pub fn find_all_conversationlists( conn: &mut SqliteConnection, ) -> Result>, ContactsServiceStorageError> { - Ok(messages::table.select(messages::address).distinct().load(conn)?) + Ok(messages::table.select(messages::from_address).distinct().load(conn)?) } } @@ -150,13 +164,18 @@ impl TryFrom for Message { #[allow(clippy::cast_sign_loss)] fn try_from(o: MessagesSql) -> Result { - let address = TariAddress::from_bytes(&o.address).map_err(|_| ContactsServiceStorageError::ConversionError)?; + let to_address = + TariAddress::from_bytes(&o.to_address).map_err(|_| ContactsServiceStorageError::ConversionError)?; + let from_address = + TariAddress::from_bytes(&o.from_address).map_err(|_| ContactsServiceStorageError::ConversionError)?; let metadata: Vec = serde_json::from_str( &String::from_utf8(o.metadata.clone()).map_err(|_| ContactsServiceStorageError::ConversionError)?, ) .map_err(|_| ContactsServiceStorageError::ConversionError)?; Ok(Self { + metadata, + body: o.body, to_address, from_address, direction: Direction::from_byte( @@ -167,8 +186,6 @@ impl TryFrom for Message { stored_at: o.stored_at.timestamp() as u64, delivery_confirmation_at: Some(o.stored_at.timestamp() as u64), read_confirmation_at: Some(o.stored_at.timestamp() as u64), - body: o.body, - metadata, message_id: o.message_id, }) } @@ -181,9 +198,9 @@ impl TryFrom for MessagesSqlInsert { fn try_from(o: Message) -> Result { let metadata = serde_json::to_string(&o.metadata).map_err(|_| ContactsServiceStorageError::ConversionError)?; - Ok(Self { - address: o.address.to_bytes().to_vec(), + to_address: o.to_address.to_bytes().to_vec(), + from_address: o.from_address.to_bytes().to_vec(), message_id: o.message_id, body: o.body, metadata: metadata.into_bytes().to_vec(), diff --git a/base_layer/contacts/src/contacts_service/types/message.rs b/base_layer/contacts/src/contacts_service/types/message.rs index 1c57a7db2ce..b5956c827f6 100644 --- a/base_layer/contacts/src/contacts_service/types/message.rs +++ b/base_layer/contacts/src/contacts_service/types/message.rs @@ -88,7 +88,8 @@ impl TryFrom for Message { Ok(Self { body: message.body, metadata, - address: TariAddress::from_bytes(&message.address).map_err(|e| e.to_string())?, + to_address: TariAddress::from_bytes(&message.to_address).map_err(|e| e.to_string())?, + from_address: TariAddress::from_bytes(&message.from_address).map_err(|e| e.to_string())?, // A Message from a proto::Message will always be an inbound message direction: Direction::Inbound, message_id: message.message_id, @@ -106,7 +107,8 @@ impl From for proto::Message { .iter() .map(|m| proto::MessageMetadata::from(m.clone())) .collect(), - address: message.address.to_bytes().to_vec(), + to_address: message.to_address.to_bytes().to_vec(), + from_address: message.from_address.to_bytes().to_vec(), direction: i32::from(message.direction.as_byte()), message_id: message.message_id, } diff --git a/base_layer/contacts/src/contacts_service/types/message_builder.rs b/base_layer/contacts/src/contacts_service/types/message_builder.rs index 788c31e1a52..27d109344eb 100644 --- a/base_layer/contacts/src/contacts_service/types/message_builder.rs +++ b/base_layer/contacts/src/contacts_service/types/message_builder.rs @@ -52,6 +52,7 @@ impl MessageBuilder { }, } } + pub fn from_address(&self, from_address: TariAddress) -> Self { Self { inner: Message { diff --git a/base_layer/contacts/tests/contacts_service.rs b/base_layer/contacts/tests/contacts_service.rs index 3c762874dff..0c1332461ef 100644 --- a/base_layer/contacts/tests/contacts_service.rs +++ b/base_layer/contacts/tests/contacts_service.rs @@ -243,7 +243,8 @@ pub fn test_message_pagination() { for num in 0..8 { let message = MessageBuilder::new() .message(format!("Test {:?}", num)) - .address(address.clone()) + .to_address(address.clone()) + .from_address(address.clone()) .build(); contacts_db.save_message(message.clone()).expect("Message to be saved"); @@ -273,7 +274,8 @@ pub fn test_message_pagination() { for num in 0..3000 { let message = MessageBuilder::new() .message(format!("Test {:?}", num)) - .address(address.clone()) + .to_address(address.clone()) + .from_address(address.clone()) .build(); contacts_db.save_message(message.clone()).expect("Message to be saved"); diff --git a/base_layer/wallet_ffi/src/lib.rs b/base_layer/wallet_ffi/src/lib.rs index f1017f8ddad..c7b132e56a6 100644 --- a/base_layer/wallet_ffi/src/lib.rs +++ b/base_layer/wallet_ffi/src/lib.rs @@ -11584,7 +11584,8 @@ mod test { alice_wallet_runtime.block_on(alice_wallet_contacts_service.send_message(Message { body: vec![i], metadata: vec![MessageMetadata::default()], - address: bob_wallet_address.clone(), + to_address: alice_wallet_address.clone(), + from_address: bob_wallet_address.clone(), direction: Direction::Outbound, stored_at: u64::from(i), sent_at: u64::from(i), @@ -11601,7 +11602,8 @@ mod test { bob_wallet_runtime.block_on(bob_wallet_contacts_service.send_message(Message { body: vec![i], metadata: vec![MessageMetadata::default()], - address: alice_wallet_address.clone(), + from_address: alice_wallet_address.clone(), + to_address: bob_wallet_address.clone(), direction: Direction::Outbound, stored_at: u64::from(i), sent_at: u64::from(i), @@ -11643,6 +11645,7 @@ mod test { // - Bob can still retrieve messages Alice sent let bob_contacts_get_messages = bob_wallet_runtime.block_on(bob_wallet_contacts_service.get_messages(alice_wallet_address, 1, 1)); + dbg!(&bob_contacts_get_messages); assert!(bob_contacts_get_messages.is_ok()); // Cleanup