From 4d1c32a5e20f02d028fe21e8f53b58a966ba0282 Mon Sep 17 00:00:00 2001 From: kaichaosun Date: Tue, 6 Jan 2026 14:38:56 +0800 Subject: [PATCH 1/6] feat: add protobuf definitions --- protos/conversations/group_v1.proto | 28 ++++++++++++++++++++++++++++ protos/encryption.proto | 26 ++++++++++++++++++++++++++ protos/envelope.proto | 16 ++++++++++++++++ protos/inbox.proto | 17 +++++++++++++++++ protos/invite.proto | 14 ++++++++++++++ protos/private_v1.proto | 19 +++++++++++++++++++ protos/reliability.proto | 23 +++++++++++++++++++++++ 7 files changed, 143 insertions(+) create mode 100644 protos/conversations/group_v1.proto create mode 100644 protos/encryption.proto create mode 100644 protos/envelope.proto create mode 100644 protos/inbox.proto create mode 100644 protos/invite.proto create mode 100644 protos/private_v1.proto create mode 100644 protos/reliability.proto diff --git a/protos/conversations/group_v1.proto b/protos/conversations/group_v1.proto new file mode 100644 index 0000000..fde7013 --- /dev/null +++ b/protos/conversations/group_v1.proto @@ -0,0 +1,28 @@ +syntax = "proto3"; + +package wap.convos.group_v1; + +import "base.proto"; +import "common_frames.proto"; + + + +message ConversationInvite_GroupV1 { + repeated string participants = 1; +} + + + +message GroupV1Frame { + // SDS like information: Message ID and channel_id extracted for utility + string message_id = 2; + string channel_id = 3; // Channel_id is associated with a set of participants + // This conflicts with conversation based encryption, + // need to ensure the derived sender is a valid participant + base.ReliabilityInfo reliability_info = 10; + + oneof frame_type { + common_frames.ContentFrame content = 100; + // ... + } +} diff --git a/protos/encryption.proto b/protos/encryption.proto new file mode 100644 index 0000000..cda0fb0 --- /dev/null +++ b/protos/encryption.proto @@ -0,0 +1,26 @@ +syntax = "proto3"; + +package wap.encryption; + + +// TODO: This also encompasses plaintexts, is there a better name? +// Alternatives: ??? +message EncryptedPayload { + + oneof encryption { + encryption.Plaintext plaintext = 1; + encryption.Doubleratchet doubleratchet = 2; + } +} + +message Plaintext { + bytes payload=1; +} + +message Doubleratchet { + bytes dh = 1; // 32 byte array + uint32 msgNum = 2; + uint32 prevChainLen = 3; + bytes ciphertext = 4; + string aux = 5; +} diff --git a/protos/envelope.proto b/protos/envelope.proto new file mode 100644 index 0000000..6a961d4 --- /dev/null +++ b/protos/envelope.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +package wap.envelope; + + +/////////////////////////////////////////////////////////////////////////////// +// Payload Framing Messages +/////////////////////////////////////////////////////////////////////////////// + +message WapEnvelopeV1 { + + string conversation_hint = 1; + uint64 salt = 2; + + bytes payload = 5; +} diff --git a/protos/inbox.proto b/protos/inbox.proto new file mode 100644 index 0000000..438b977 --- /dev/null +++ b/protos/inbox.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; + +package wap.inbox; + +import "invite.proto"; + +message Note{ + string text = 1; +} + +message InboxV1Frame { + string recipient = 1; + oneof frame_type { + invite.InvitePrivateV1 invite_private_v1 = 10; + Note note = 11; + } +} diff --git a/protos/invite.proto b/protos/invite.proto new file mode 100644 index 0000000..da9f560 --- /dev/null +++ b/protos/invite.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; + +package wap.invite; + +import "encryption.proto"; + +message InvitePrivateV1 { + bytes initiator = 1; + bytes initiator_ephemeral = 2; + bytes participant = 3; + int32 participant_ephemeral_id= 4; + string discriminator = 5; + encryption.EncryptedPayload initial_message = 6; +} diff --git a/protos/private_v1.proto b/protos/private_v1.proto new file mode 100644 index 0000000..7dd69ff --- /dev/null +++ b/protos/private_v1.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; + +package wap.convos.private_v1; + + +message Placeholder { + uint32 counter = 1; +} + +message PrivateV1Frame { + string conversation_id = 1; + bytes sender = 2; + int64 timestamp = 3; // Sender reported timestamp + oneof frame_type { + bytes content = 10; + Placeholder placeholder = 11; + // .... + } +} diff --git a/protos/reliability.proto b/protos/reliability.proto new file mode 100644 index 0000000..f71f9b2 --- /dev/null +++ b/protos/reliability.proto @@ -0,0 +1,23 @@ +syntax = "proto3"; + +package wap.reliability; + +/////////////////////////////////////////////////////////////////////////////// +// 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 + } + + message ReliablePayload { + string message_id = 2; + string channel_id = 3; + int32 lamport_timestamp = 10; + repeated HistoryEntry causal_history = 11; + bytes bloom_filter = 12; + // Optional field causes errors in nim protobuf generation. Removing for now as optional is implied anways. + bytes content = 20; + } From 39474393c0584980031ce04e4be65bdf731fdcf8 Mon Sep 17 00:00:00 2001 From: kaichaosun Date: Tue, 6 Jan 2026 15:30:37 +0800 Subject: [PATCH 2/6] feat: buf generate with prost --- README.md | 60 +++++++++++- buf.gen.yaml | 6 ++ buf.yaml | 10 ++ gen/rust/.gitignore | 1 + gen/rust/Cargo.lock | 95 +++++++++++++++++++ gen/rust/Cargo.toml | 7 ++ gen/rust/src/lib.rs | 30 ++++++ .../private_v1/wap.convos.private_v1.rs | 31 ++++++ gen/rust/src/wap/encryption/wap.encryption.rs | 39 ++++++++ gen/rust/src/wap/envelope/wap.envelope.rs | 16 ++++ gen/rust/src/wap/inbox/wap.inbox.rs | 25 +++++ gen/rust/src/wap/invite/wap.invite.rs | 18 ++++ .../src/wap/reliability/wap.reliability.rs | 32 +++++++ protos/conversations/group_v1.proto | 28 ------ 14 files changed, 369 insertions(+), 29 deletions(-) create mode 100644 buf.gen.yaml create mode 100644 buf.yaml create mode 100644 gen/rust/.gitignore create mode 100644 gen/rust/Cargo.lock create mode 100644 gen/rust/Cargo.toml create mode 100644 gen/rust/src/lib.rs create mode 100644 gen/rust/src/wap/convos/private_v1/wap.convos.private_v1.rs create mode 100644 gen/rust/src/wap/encryption/wap.encryption.rs create mode 100644 gen/rust/src/wap/envelope/wap.envelope.rs create mode 100644 gen/rust/src/wap/inbox/wap.inbox.rs create mode 100644 gen/rust/src/wap/invite/wap.invite.rs create mode 100644 gen/rust/src/wap/reliability/wap.reliability.rs delete mode 100644 protos/conversations/group_v1.proto diff --git a/README.md b/README.md index 2f12ed0..ccba49f 100644 --- a/README.md +++ b/README.md @@ -1 +1,59 @@ -# chat_proto \ No newline at end of file +# Chat Protobuf Definitionss + +This repository contains the canonical **protobuf definitions** for the WAP (Waku Application Protocol) used by LibChat and related components. + +It is **schema-only**: +- No application logic +- Stable, versioned wire formats +- Intended to be consumed by multiple languages + +Generated bindings (e.g. Rust) are produced from these schemas. + +--- + +## Prerequisites + +This project uses [Buf](https://buf.build) for protobuf linting and code generation. + +### Install Buf + +On macOS and Linux: +```sh +brew install bufbuild/buf/buf +``` + +For other platforms, See https://buf.build/docs/cli/installation/. + +## Repository Structure + +``` +protos/ # Protobuf source files +buf.yaml # Buf module configuration +buf.gen.yaml # Code generation configuration +gen/ + └── rust/ # Generated Rust bindings (prost) +``` + +## Generate Rust bindings + +``` +buf generate +``` + +This will generate Rust code under: `gen/rust/`, The generated crate can be used directly as a dependency in Rust projects. + +## Usage (Rust) + +Add in Cargo.toml: +``` +chat-proto = { git = "https://github.com/logos-messaging/chat_proto" } +``` + +Example import: +``` +use chat_proto::wap::{ + inbox::InboxV1Frame, + invite::InvitePrivateV1, + encryption::EncryptedPayload, +}; +``` diff --git a/buf.gen.yaml b/buf.gen.yaml new file mode 100644 index 0000000..1473f61 --- /dev/null +++ b/buf.gen.yaml @@ -0,0 +1,6 @@ +version: v2 +plugins: + - remote: buf.build/community/neoeinstein-prost:v0.5.0 + out: gen/rust/src + opt: + - bytes=. diff --git a/buf.yaml b/buf.yaml new file mode 100644 index 0000000..3e61dfc --- /dev/null +++ b/buf.yaml @@ -0,0 +1,10 @@ +version: v2 + +modules: + - path: protos +lint: + use: + - DEFAULT +breaking: + use: + - FILE diff --git a/gen/rust/.gitignore b/gen/rust/.gitignore new file mode 100644 index 0000000..2f7896d --- /dev/null +++ b/gen/rust/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/gen/rust/Cargo.lock b/gen/rust/Cargo.lock new file mode 100644 index 0000000..6f9eaaa --- /dev/null +++ b/gen/rust/Cargo.lock @@ -0,0 +1,95 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "bytes" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" + +[[package]] +name = "chat-proto" +version = "0.1.0" +dependencies = [ + "prost", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "proc-macro2" +version = "1.0.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "quote" +version = "1.0.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.113" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678faa00651c9eb72dd2020cbdf275d92eccb2400d568e419efdd64838145cb4" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" diff --git a/gen/rust/Cargo.toml b/gen/rust/Cargo.toml new file mode 100644 index 0000000..96d14d7 --- /dev/null +++ b/gen/rust/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "chat-proto" +version = "0.1.0" +edition = "2021" + +[dependencies] +prost = "0.14" diff --git a/gen/rust/src/lib.rs b/gen/rust/src/lib.rs new file mode 100644 index 0000000..d41c597 --- /dev/null +++ b/gen/rust/src/lib.rs @@ -0,0 +1,30 @@ +// #![allow(clippy::all)] +// #![allow(warnings)] + +pub mod wap { + pub mod convos { + pub mod private_v1 { + include!("wap/convos/private_v1/wap.convos.private_v1.rs"); + } + } + + pub mod encryption { + include!("wap/encryption/wap.encryption.rs"); + } + + pub mod envelope { + include!("wap/envelope/wap.envelope.rs"); + } + + pub mod inbox { + include!("wap/inbox/wap.inbox.rs"); + } + + pub mod invite { + include!("wap/invite/wap.invite.rs"); + } + + pub mod reliability { + include!("wap/reliability/wap.reliability.rs"); + } +} diff --git a/gen/rust/src/wap/convos/private_v1/wap.convos.private_v1.rs b/gen/rust/src/wap/convos/private_v1/wap.convos.private_v1.rs new file mode 100644 index 0000000..b658325 --- /dev/null +++ b/gen/rust/src/wap/convos/private_v1/wap.convos.private_v1.rs @@ -0,0 +1,31 @@ +// @generated +// This file is @generated by prost-build. +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct Placeholder { + #[prost(uint32, tag="1")] + pub counter: u32, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct PrivateV1Frame { + #[prost(string, tag="1")] + pub conversation_id: ::prost::alloc::string::String, + #[prost(bytes="bytes", tag="2")] + pub sender: ::prost::bytes::Bytes, + /// Sender reported timestamp + #[prost(int64, tag="3")] + pub timestamp: i64, + #[prost(oneof="private_v1_frame::FrameType", tags="10, 11")] + pub frame_type: ::core::option::Option, +} +/// Nested message and enum types in `PrivateV1Frame`. +pub mod private_v1_frame { + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)] + pub enum FrameType { + #[prost(bytes, tag="10")] + Content(::prost::bytes::Bytes), + /// .... + #[prost(message, tag="11")] + Placeholder(super::Placeholder), + } +} +// @@protoc_insertion_point(module) diff --git a/gen/rust/src/wap/encryption/wap.encryption.rs b/gen/rust/src/wap/encryption/wap.encryption.rs new file mode 100644 index 0000000..1495f03 --- /dev/null +++ b/gen/rust/src/wap/encryption/wap.encryption.rs @@ -0,0 +1,39 @@ +// @generated +// This file is @generated by prost-build. +/// TODO: This also encompasses plaintexts, is there a better name? +/// Alternatives: ??? +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct EncryptedPayload { + #[prost(oneof="encrypted_payload::Encryption", tags="1, 2")] + pub encryption: ::core::option::Option, +} +/// Nested message and enum types in `EncryptedPayload`. +pub mod encrypted_payload { + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)] + pub enum Encryption { + #[prost(message, tag="1")] + Plaintext(super::Plaintext), + #[prost(message, tag="2")] + Doubleratchet(super::Doubleratchet), + } +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct Plaintext { + #[prost(bytes="bytes", tag="1")] + pub payload: ::prost::bytes::Bytes, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct Doubleratchet { + /// 32 byte array + #[prost(bytes="bytes", tag="1")] + pub dh: ::prost::bytes::Bytes, + #[prost(uint32, tag="2")] + pub msg_num: u32, + #[prost(uint32, tag="3")] + pub prev_chain_len: u32, + #[prost(bytes="bytes", tag="4")] + pub ciphertext: ::prost::bytes::Bytes, + #[prost(string, tag="5")] + pub aux: ::prost::alloc::string::String, +} +// @@protoc_insertion_point(module) diff --git a/gen/rust/src/wap/envelope/wap.envelope.rs b/gen/rust/src/wap/envelope/wap.envelope.rs new file mode 100644 index 0000000..c6b26c4 --- /dev/null +++ b/gen/rust/src/wap/envelope/wap.envelope.rs @@ -0,0 +1,16 @@ +// @generated +// This file is @generated by prost-build. +// ///////////////////////////////////////////////////////////////////////////// +// Payload Framing Messages +// ///////////////////////////////////////////////////////////////////////////// + +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct WapEnvelopeV1 { + #[prost(string, tag="1")] + pub conversation_hint: ::prost::alloc::string::String, + #[prost(uint64, tag="2")] + pub salt: u64, + #[prost(bytes="bytes", tag="5")] + pub payload: ::prost::bytes::Bytes, +} +// @@protoc_insertion_point(module) diff --git a/gen/rust/src/wap/inbox/wap.inbox.rs b/gen/rust/src/wap/inbox/wap.inbox.rs new file mode 100644 index 0000000..a08b290 --- /dev/null +++ b/gen/rust/src/wap/inbox/wap.inbox.rs @@ -0,0 +1,25 @@ +// @generated +// This file is @generated by prost-build. +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct Note { + #[prost(string, tag="1")] + pub text: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct InboxV1Frame { + #[prost(string, tag="1")] + pub recipient: ::prost::alloc::string::String, + #[prost(oneof="inbox_v1_frame::FrameType", tags="10, 11")] + pub frame_type: ::core::option::Option, +} +/// Nested message and enum types in `InboxV1Frame`. +pub mod inbox_v1_frame { + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)] + pub enum FrameType { + #[prost(message, tag="10")] + InvitePrivateV1(super::super::invite::InvitePrivateV1), + #[prost(message, tag="11")] + Note(super::Note), + } +} +// @@protoc_insertion_point(module) diff --git a/gen/rust/src/wap/invite/wap.invite.rs b/gen/rust/src/wap/invite/wap.invite.rs new file mode 100644 index 0000000..013e528 --- /dev/null +++ b/gen/rust/src/wap/invite/wap.invite.rs @@ -0,0 +1,18 @@ +// @generated +// This file is @generated by prost-build. +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct InvitePrivateV1 { + #[prost(bytes="bytes", tag="1")] + pub initiator: ::prost::bytes::Bytes, + #[prost(bytes="bytes", tag="2")] + pub initiator_ephemeral: ::prost::bytes::Bytes, + #[prost(bytes="bytes", tag="3")] + pub participant: ::prost::bytes::Bytes, + #[prost(int32, tag="4")] + pub participant_ephemeral_id: i32, + #[prost(string, tag="5")] + pub discriminator: ::prost::alloc::string::String, + #[prost(message, optional, tag="6")] + pub initial_message: ::core::option::Option, +} +// @@protoc_insertion_point(module) diff --git a/gen/rust/src/wap/reliability/wap.reliability.rs b/gen/rust/src/wap/reliability/wap.reliability.rs new file mode 100644 index 0000000..36f2e46 --- /dev/null +++ b/gen/rust/src/wap/reliability/wap.reliability.rs @@ -0,0 +1,32 @@ +// @generated +// This file is @generated by prost-build. +// ///////////////////////////////////////////////////////////////////////////// +// SDS Payloads +// ///////////////////////////////////////////////////////////////////////////// + +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct HistoryEntry { + /// Unique identifier of the SDS message, as defined in `Message` + #[prost(string, tag="1")] + pub message_id: ::prost::alloc::string::String, + /// Optional information to help remote parties retrieve this SDS + #[prost(bytes="bytes", tag="2")] + pub retrieval_hint: ::prost::bytes::Bytes, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ReliablePayload { + #[prost(string, tag="2")] + pub message_id: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub channel_id: ::prost::alloc::string::String, + #[prost(int32, tag="10")] + pub lamport_timestamp: i32, + #[prost(message, repeated, tag="11")] + pub causal_history: ::prost::alloc::vec::Vec, + #[prost(bytes="bytes", tag="12")] + pub bloom_filter: ::prost::bytes::Bytes, + /// Optional field causes errors in nim protobuf generation. Removing for now as optional is implied anways. + #[prost(bytes="bytes", tag="20")] + pub content: ::prost::bytes::Bytes, +} +// @@protoc_insertion_point(module) diff --git a/protos/conversations/group_v1.proto b/protos/conversations/group_v1.proto deleted file mode 100644 index fde7013..0000000 --- a/protos/conversations/group_v1.proto +++ /dev/null @@ -1,28 +0,0 @@ -syntax = "proto3"; - -package wap.convos.group_v1; - -import "base.proto"; -import "common_frames.proto"; - - - -message ConversationInvite_GroupV1 { - repeated string participants = 1; -} - - - -message GroupV1Frame { - // SDS like information: Message ID and channel_id extracted for utility - string message_id = 2; - string channel_id = 3; // Channel_id is associated with a set of participants - // This conflicts with conversation based encryption, - // need to ensure the derived sender is a valid participant - base.ReliabilityInfo reliability_info = 10; - - oneof frame_type { - common_frames.ContentFrame content = 100; - // ... - } -} From 403029a541ff0a199c8943d106f6ea204e79aad5 Mon Sep 17 00:00:00 2001 From: kaichaosun Date: Tue, 6 Jan 2026 15:45:48 +0800 Subject: [PATCH 3/6] chore: add tests --- gen/rust/Cargo.lock | 1 + gen/rust/Cargo.toml | 3 ++ gen/rust/src/lib.rs | 79 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+) diff --git a/gen/rust/Cargo.lock b/gen/rust/Cargo.lock index 6f9eaaa..f527aae 100644 --- a/gen/rust/Cargo.lock +++ b/gen/rust/Cargo.lock @@ -18,6 +18,7 @@ checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" name = "chat-proto" version = "0.1.0" dependencies = [ + "bytes", "prost", ] diff --git a/gen/rust/Cargo.toml b/gen/rust/Cargo.toml index 96d14d7..56cc506 100644 --- a/gen/rust/Cargo.toml +++ b/gen/rust/Cargo.toml @@ -5,3 +5,6 @@ edition = "2021" [dependencies] prost = "0.14" + +[dev-dependencies] +bytes = "1.3" diff --git a/gen/rust/src/lib.rs b/gen/rust/src/lib.rs index d41c597..75700a9 100644 --- a/gen/rust/src/lib.rs +++ b/gen/rust/src/lib.rs @@ -28,3 +28,82 @@ pub mod wap { include!("wap/reliability/wap.reliability.rs"); } } + +#[cfg(test)] +mod tests { + use super::wap::{ + encryption::{encrypted_payload::Encryption, EncryptedPayload, Plaintext}, + inbox::{inbox_v1_frame::FrameType, InboxV1Frame, Note}, + invite::InvitePrivateV1, + }; + use bytes::Bytes; + use prost::Message; + + #[test] + fn test_encrypted_payload_roundtrip() { + let payload = EncryptedPayload { + encryption: Some(Encryption::Plaintext(Plaintext { + payload: Bytes::from_static(b"hello world"), + })), + }; + + // Encode to bytes + let mut buf = Vec::new(); + payload.encode(&mut buf).expect("Encoding failed"); + + // Decode back + let decoded = EncryptedPayload::decode(&buf[..]).expect("Decoding failed"); + + match decoded.encryption { + Some(Encryption::Plaintext(p)) => { + assert_eq!(p.payload, Bytes::from_static(b"hello world")); + } + _ => panic!("Expected plaintext variant"), + } + } + + #[test] + fn test_inbox_frame_roundtrip() { + let note = Note { + text: "This is a test note".to_string(), + }; + + let frame = InboxV1Frame { + recipient: "alice".to_string(), + frame_type: Some(FrameType::Note(note.clone())), + }; + + let mut buf = Vec::new(); + frame.encode(&mut buf).expect("Encoding failed"); + + let decoded = InboxV1Frame::decode(&buf[..]).expect("Decoding failed"); + + match decoded.frame_type { + Some(FrameType::Note(n)) => { + assert_eq!(n.text, note.text); + } + _ => panic!("Expected Note variant"), + } + } + + #[test] + fn test_invite_private_roundtrip() { + let invite = InvitePrivateV1 { + initiator: Bytes::from_static(b"initiator"), + initiator_ephemeral: Bytes::from_static(b"ephemeral"), + participant: Bytes::from_static(b"participant"), + participant_ephemeral_id: 42, + discriminator: "test_discriminator".to_string(), + initial_message: None, // skipping encrypted payload for simplicity + }; + + let mut buf = Vec::new(); + invite.encode(&mut buf).expect("Encoding failed"); + + let decoded = InvitePrivateV1::decode(&buf[..]).expect("Decoding failed"); + + assert_eq!(decoded.initiator, Bytes::from_static(b"initiator")); + assert_eq!(decoded.participant_ephemeral_id, 42); + assert_eq!(decoded.discriminator, "test_discriminator"); + } +} From fb4fd1c84a3d0788a487a66d5da3fb508c930bc3 Mon Sep 17 00:00:00 2001 From: kaichaosun Date: Tue, 6 Jan 2026 15:49:27 +0800 Subject: [PATCH 4/6] chore: ci for test --- .github/workflows/rust.yaml | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 .github/workflows/rust.yaml diff --git a/.github/workflows/rust.yaml b/.github/workflows/rust.yaml new file mode 100644 index 0000000..784a55f --- /dev/null +++ b/.github/workflows/rust.yaml @@ -0,0 +1,33 @@ +name: Rust + +on: + pull_request: + branches: + - main + paths-ignore: + - "**README.md" + - ".gitignore" + - "LICENSE" + +jobs: + test: + name: Cargo Check + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + + - name: Check Rust bindings + working-directory: gen/rust + run: cargo check --all-targets + + - name: Test Rust bindings + working-directory: gen/rust + run: cargo test From ea7ef838985be89c827b5d64f78cb3113c057fbc Mon Sep 17 00:00:00 2001 From: kaichaosun Date: Fri, 9 Jan 2026 10:12:15 +0800 Subject: [PATCH 5/6] chore: rename package name --- gen/rust/src/lib.rs | 16 ++++++++-------- .../private_v1/logoschat.convos.private_v1.rs} | 0 .../encryption/logoschat.encryption.rs} | 0 .../envelope/logoschat.envelope.rs} | 2 +- .../inbox/logoschat.inbox.rs} | 0 .../invite/logoschat.invite.rs} | 0 .../reliability/logoschat.reliability.rs} | 0 protos/encryption.proto | 2 +- protos/envelope.proto | 4 ++-- protos/inbox.proto | 2 +- protos/invite.proto | 2 +- protos/private_v1.proto | 2 +- protos/reliability.proto | 2 +- 13 files changed, 16 insertions(+), 16 deletions(-) rename gen/rust/src/{wap/convos/private_v1/wap.convos.private_v1.rs => logoschat/convos/private_v1/logoschat.convos.private_v1.rs} (100%) rename gen/rust/src/{wap/encryption/wap.encryption.rs => logoschat/encryption/logoschat.encryption.rs} (100%) rename gen/rust/src/{wap/envelope/wap.envelope.rs => logoschat/envelope/logoschat.envelope.rs} (95%) rename gen/rust/src/{wap/inbox/wap.inbox.rs => logoschat/inbox/logoschat.inbox.rs} (100%) rename gen/rust/src/{wap/invite/wap.invite.rs => logoschat/invite/logoschat.invite.rs} (100%) rename gen/rust/src/{wap/reliability/wap.reliability.rs => logoschat/reliability/logoschat.reliability.rs} (100%) diff --git a/gen/rust/src/lib.rs b/gen/rust/src/lib.rs index 75700a9..4e9d5c6 100644 --- a/gen/rust/src/lib.rs +++ b/gen/rust/src/lib.rs @@ -1,37 +1,37 @@ // #![allow(clippy::all)] // #![allow(warnings)] -pub mod wap { +pub mod logoschat { pub mod convos { pub mod private_v1 { - include!("wap/convos/private_v1/wap.convos.private_v1.rs"); + include!("logoschat/convos/private_v1/logoschat.convos.private_v1.rs"); } } pub mod encryption { - include!("wap/encryption/wap.encryption.rs"); + include!("logoschat/encryption/logoschat.encryption.rs"); } pub mod envelope { - include!("wap/envelope/wap.envelope.rs"); + include!("logoschat/envelope/logoschat.envelope.rs"); } pub mod inbox { - include!("wap/inbox/wap.inbox.rs"); + include!("logoschat/inbox/logoschat.inbox.rs"); } pub mod invite { - include!("wap/invite/wap.invite.rs"); + include!("logoschat/invite/logoschat.invite.rs"); } pub mod reliability { - include!("wap/reliability/wap.reliability.rs"); + include!("logoschat/reliability/logoschat.reliability.rs"); } } #[cfg(test)] mod tests { - use super::wap::{ + use super::logoschat::{ encryption::{encrypted_payload::Encryption, EncryptedPayload, Plaintext}, inbox::{inbox_v1_frame::FrameType, InboxV1Frame, Note}, invite::InvitePrivateV1, diff --git a/gen/rust/src/wap/convos/private_v1/wap.convos.private_v1.rs b/gen/rust/src/logoschat/convos/private_v1/logoschat.convos.private_v1.rs similarity index 100% rename from gen/rust/src/wap/convos/private_v1/wap.convos.private_v1.rs rename to gen/rust/src/logoschat/convos/private_v1/logoschat.convos.private_v1.rs diff --git a/gen/rust/src/wap/encryption/wap.encryption.rs b/gen/rust/src/logoschat/encryption/logoschat.encryption.rs similarity index 100% rename from gen/rust/src/wap/encryption/wap.encryption.rs rename to gen/rust/src/logoschat/encryption/logoschat.encryption.rs diff --git a/gen/rust/src/wap/envelope/wap.envelope.rs b/gen/rust/src/logoschat/envelope/logoschat.envelope.rs similarity index 95% rename from gen/rust/src/wap/envelope/wap.envelope.rs rename to gen/rust/src/logoschat/envelope/logoschat.envelope.rs index c6b26c4..f63ee37 100644 --- a/gen/rust/src/wap/envelope/wap.envelope.rs +++ b/gen/rust/src/logoschat/envelope/logoschat.envelope.rs @@ -5,7 +5,7 @@ // ///////////////////////////////////////////////////////////////////////////// #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] -pub struct WapEnvelopeV1 { +pub struct EnvelopeV1 { #[prost(string, tag="1")] pub conversation_hint: ::prost::alloc::string::String, #[prost(uint64, tag="2")] diff --git a/gen/rust/src/wap/inbox/wap.inbox.rs b/gen/rust/src/logoschat/inbox/logoschat.inbox.rs similarity index 100% rename from gen/rust/src/wap/inbox/wap.inbox.rs rename to gen/rust/src/logoschat/inbox/logoschat.inbox.rs diff --git a/gen/rust/src/wap/invite/wap.invite.rs b/gen/rust/src/logoschat/invite/logoschat.invite.rs similarity index 100% rename from gen/rust/src/wap/invite/wap.invite.rs rename to gen/rust/src/logoschat/invite/logoschat.invite.rs diff --git a/gen/rust/src/wap/reliability/wap.reliability.rs b/gen/rust/src/logoschat/reliability/logoschat.reliability.rs similarity index 100% rename from gen/rust/src/wap/reliability/wap.reliability.rs rename to gen/rust/src/logoschat/reliability/logoschat.reliability.rs diff --git a/protos/encryption.proto b/protos/encryption.proto index cda0fb0..a245369 100644 --- a/protos/encryption.proto +++ b/protos/encryption.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package wap.encryption; +package logoschat.encryption; // TODO: This also encompasses plaintexts, is there a better name? diff --git a/protos/envelope.proto b/protos/envelope.proto index 6a961d4..6aedc90 100644 --- a/protos/envelope.proto +++ b/protos/envelope.proto @@ -1,13 +1,13 @@ syntax = "proto3"; -package wap.envelope; +package logoschat.envelope; /////////////////////////////////////////////////////////////////////////////// // Payload Framing Messages /////////////////////////////////////////////////////////////////////////////// -message WapEnvelopeV1 { +message EnvelopeV1 { string conversation_hint = 1; uint64 salt = 2; diff --git a/protos/inbox.proto b/protos/inbox.proto index 438b977..1159eb7 100644 --- a/protos/inbox.proto +++ b/protos/inbox.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package wap.inbox; +package logoschat.inbox; import "invite.proto"; diff --git a/protos/invite.proto b/protos/invite.proto index da9f560..608f8d4 100644 --- a/protos/invite.proto +++ b/protos/invite.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package wap.invite; +package logoschat.invite; import "encryption.proto"; diff --git a/protos/private_v1.proto b/protos/private_v1.proto index 7dd69ff..436d90b 100644 --- a/protos/private_v1.proto +++ b/protos/private_v1.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package wap.convos.private_v1; +package logoschat.convos.private_v1; message Placeholder { diff --git a/protos/reliability.proto b/protos/reliability.proto index f71f9b2..6c49105 100644 --- a/protos/reliability.proto +++ b/protos/reliability.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package wap.reliability; +package logoschat.reliability; /////////////////////////////////////////////////////////////////////////////// // SDS Payloads From 00f1b42288269fed2e3101d5e296a20e01dd8012 Mon Sep 17 00:00:00 2001 From: kaichaosun Date: Fri, 9 Jan 2026 10:13:28 +0800 Subject: [PATCH 6/6] chore: update doc --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ccba49f..1262c1a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Chat Protobuf Definitionss -This repository contains the canonical **protobuf definitions** for the WAP (Waku Application Protocol) used by LibChat and related components. +This repository contains the canonical **protobuf definitions** for the logoschat (Logos Chat Protocol) used by LibChat and related components. It is **schema-only**: - No application logic @@ -51,7 +51,7 @@ chat-proto = { git = "https://github.com/logos-messaging/chat_proto" } Example import: ``` -use chat_proto::wap::{ +use chat_proto::logoschat::{ inbox::InboxV1Frame, invite::InvitePrivateV1, encryption::EncryptedPayload,