From 270b97210a8fa2b538e846f4f4895ab744aa5688 Mon Sep 17 00:00:00 2001 From: Jazz Turner-Baggs <473256+jazzz@users.noreply.github.com> Date: Fri, 27 Jun 2025 09:38:07 -0700 Subject: [PATCH] simplify parsing --- proto/umbra/base.proto | 40 +++++++++---- proto/umbra/conversations/inbox_v1.proto | 4 +- proto/umbra/conversations/private_v1.proto | 15 +++-- rust/umbra-types/src/lib.rs | 21 +++++++ rust/umbra-types/src/payload.rs | 66 +++++++++++++++++++--- 5 files changed, 117 insertions(+), 29 deletions(-) diff --git a/proto/umbra/base.proto b/proto/umbra/base.proto index 8b9d7de..9e7c2d4 100644 --- a/proto/umbra/base.proto +++ b/proto/umbra/base.proto @@ -2,22 +2,42 @@ syntax = "proto3"; package umbra.base; +import "proto/umbra/encryption.proto"; /////////////////////////////////////////////////////////////////////////////// // SDS Payloads /////////////////////////////////////////////////////////////////////////////// message HistoryEntry { - string message_id = 1; // Unique identifier of the SDS message, as defined in `Message` - bytes retrieval_hint = 2; // Optional information to help remote parties retrieve this SDS - // message; For example, A Waku deterministic message hash or routing payload hash + string message_id = 1; // Unique identifier of the SDS message, as defined in `Message` + bytes retrieval_hint = 2; // Optional information to help remote parties retrieve this SDS + // message; For example, A Waku deterministic message hash or routing payload hash + } + + message ReliableBytes { + string message_id = 2; + string channel_id = 3; + int32 lamport_timestamp = 10; + repeated HistoryEntry causal_history = 11; + bytes bloom_filter = 12; + optional bytes content = 20; + } + + +/////////////////////////////////////////////////////////////////////////////// +// Encryption +/////////////////////////////////////////////////////////////////////////////// + +// TODO: This also encompasses plaintexts, is there a better name? +// Alternatives: ??? +message EncryptedBytes { + + oneof encryption { + encryption.Plaintext plaintext = 1; + encryption.Ecies ecies = 2; + } } -message ReliabilityInfo { - int32 lamport_timestamp = 10; - repeated HistoryEntry causal_history = 11; - bytes bloom_filter = 12; -} /////////////////////////////////////////////////////////////////////////////// // Payload Framing Messages @@ -27,7 +47,7 @@ message ReliabilityInfo { message UmbraEnvelopeV1 { string conversation_hint = 1; - uint32 nonce = 2; + uint64 salt = 2; - bytes encrypted_bytes = 100; + bytes payload = 5; } \ No newline at end of file diff --git a/proto/umbra/conversations/inbox_v1.proto b/proto/umbra/conversations/inbox_v1.proto index cb6663c..2418b82 100644 --- a/proto/umbra/conversations/inbox_v1.proto +++ b/proto/umbra/conversations/inbox_v1.proto @@ -9,8 +9,8 @@ import "proto/umbra/conversations/private_v1.proto"; message InboxV1Frame { string recipient = 1; - string conversation_type = 2; - oneof params { + // string conversation_type = 2; + oneof frame_type { convos.private_v1.ConversationInvite_PrivateV1 invite_private_v1 = 10; } } diff --git a/proto/umbra/conversations/private_v1.proto b/proto/umbra/conversations/private_v1.proto index 94410f9..ab73a64 100644 --- a/proto/umbra/conversations/private_v1.proto +++ b/proto/umbra/conversations/private_v1.proto @@ -2,7 +2,6 @@ syntax = "proto3"; package umbra.convos.private_v1; -import "proto/umbra/base.proto"; import "proto/umbra/common_frames.proto"; message ConversationInvite_PrivateV1 { @@ -11,16 +10,16 @@ message ConversationInvite_PrivateV1 { } -message PrivateV1Frame { - // SDS like information: Message ID and channel_id extracted for utility - string message_id = 2; - string conversation_id = 3; - - base.ReliabilityInfo reliability_info = 4; +message Placeholder { + uint32 counter = 1; +} + +message PrivateV1Frame { + string conversation_id = 1; oneof frame_type { common_frames.ContentFrame content = 10; + Placeholder placeholder = 11; // .... } } - diff --git a/rust/umbra-types/src/lib.rs b/rust/umbra-types/src/lib.rs index 1b37286..e03d6c7 100644 --- a/rust/umbra-types/src/lib.rs +++ b/rust/umbra-types/src/lib.rs @@ -1,3 +1,24 @@ pub mod payload; pub use payload::types::umbra::*; + +#[cfg(test)] + +mod tests { + use super::*; + use prost::Message; + + #[test] + fn test_private_v1_roundtrip() { + convos::private_v1::PrivateV1Frame { + conversation_id: "conversationId".to_string(), + frame_type: Some(convos::private_v1::private_v1_frame::FrameType::Content( + common_frames::ContentFrame { + domain: 0, + tag: 0, + bytes: "Hello, World!".to_string().encode_to_vec(), + }, + )), + }; + } +} diff --git a/rust/umbra-types/src/payload.rs b/rust/umbra-types/src/payload.rs index 0ce769a..a3a703a 100644 --- a/rust/umbra-types/src/payload.rs +++ b/rust/umbra-types/src/payload.rs @@ -2,8 +2,50 @@ pub mod types { include!(concat!(env!("OUT_DIR"), "/mod.rs")); } +use prost::Message; pub use types::umbra::*; +use crate::{ + base::{EncryptedBytes, UmbraEnvelopeV1}, + convos::{ + inbox::{InboxV1Frame, inbox_v1_frame}, + private_v1::{PrivateV1Frame, private_v1_frame}, + }, +}; + +impl PrivateV1Frame { + pub fn new(conversation_id: String, frame: private_v1_frame::FrameType) -> Self { + PrivateV1Frame { + conversation_id, + frame_type: Some(frame), + } + } +} + +impl InboxV1Frame { + pub fn new(recipient: String, frame: inbox_v1_frame::FrameType) -> Self { + InboxV1Frame { + recipient: recipient, + // conversation_id, + frame_type: Some(frame), + } + } +} + +pub trait ToEnvelope { + fn to_envelope(self, conversation_id: String, salt: u64) -> UmbraEnvelopeV1; +} + +impl ToEnvelope for EncryptedBytes { + fn to_envelope(self, conversation_id: String, salt: u64) -> UmbraEnvelopeV1 { + UmbraEnvelopeV1 { + conversation_hint: conversation_id, // TODO + salt, + payload: self.encode_to_vec(), // Avoid allocation here? + } + } +} + #[cfg(test)] mod tests { use super::*; @@ -13,14 +55,8 @@ mod tests { fn test_private_v1_roundtrip() { let text = "Hello, World!".to_string(); - let msg = convos::private_v1::PrivateV1Frame { - message_id: "messageId".to_string(), + let msg = PrivateV1Frame { conversation_id: "conversationId".to_string(), - reliability_info: Some(base::ReliabilityInfo { - lamport_timestamp: 0, - causal_history: vec![], - bloom_filter: vec![1, 2, 3, 4], - }), frame_type: Some(convos::private_v1::private_v1_frame::FrameType::Content( common_frames::ContentFrame { domain: 0, @@ -30,10 +66,22 @@ mod tests { )), }; - let bytes = msg.encode_to_vec(); + let reliable = base::ReliableBytes { + message_id: "msg_id".into(), + channel_id: msg.conversation_id.clone(), + lamport_timestamp: 0, + causal_history: vec![], + bloom_filter: vec![1, 2, 3, 4], + content: Some(msg.encode_to_vec()), + }; + + let buf = reliable.encode_to_vec(); + + let reliable_msg = base::ReliableBytes::decode(&*buf).unwrap(); let msg_from_bytes = - convos::private_v1::PrivateV1Frame::decode(&*bytes).expect("Failed to decode message"); + convos::private_v1::PrivateV1Frame::decode(&*reliable_msg.content.unwrap()) + .expect("Failed to decode message"); assert_eq!( msg, msg_from_bytes,