feat: choose a channel's encryption mechanism at creation

Channel traffic could not flow at all: the Encrypt/Decrypt brokers had no
provider registered, so every segment failed with "no provider registered
for input signature" and the send surfaced as "one or more segments
failed". createReliableChannel documents that providers must be installed
first, but library/ never installed any and exposed no way for a caller
to, which made the channel API unusable through the FFI.

The mechanism is named per channel rather than defaulted, so nothing
silently gets pass-through "encryption" on a network built for private
messaging -- the caller has to say "noop" and mean it. Only noop exists
today; anything else is rejected rather than ignored.

Caveat, noted in the code: the brokers dispatch to one provider
process-wide, so the per-channel name installs a global provider and
channels asking for different mechanisms would fight over it. Naming it
at creation is still the right seam for when real providers land.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Ivan FB 2026-07-16 08:40:05 +02:00
parent 7080a629da
commit 1ef53c9506
No known key found for this signature in database
GPG Key ID: DF0C67A04C543270
3 changed files with 23 additions and 4 deletions

View File

@ -3,19 +3,36 @@ import chronos, results, ffi
import
logos_delivery/waku/common/base64,
logos_delivery,
logos_delivery/channels/encryption/noop_encryption,
logos_delivery/waku/waku_core/topics/content_topic,
logos_delivery/api/types,
../declare_lib
proc installEncryption(mechanism: string): Result[void, string] =
## The Encrypt/Decrypt brokers dispatch to a single provider, so this installs
## it process-wide even though the mechanism is named per channel: channels
## created with different mechanisms would fight over it, last one winning.
## Traffic cannot flow until some provider is registered.
case mechanism
of "noop":
setNoopEncryption()
ok()
else:
err("unknown encryption mechanism '" & mechanism & "'; supported: noop")
proc logosdeliveryChannelCreate*(
lib: LogosDelivery,
channelIdStr: string,
contentTopicStr: string,
senderIdStr: string,
encryptionStr: string,
): Future[Result[string, string]] {.ffi.} =
requireChannels(lib, "ChannelCreate"):
return err(errMsg)
installEncryption(encryptionStr).isOkOr:
return err("ChannelCreate failed: " & error)
let id = lib.reliableChannelManager.createReliableChannel(
ChannelId(channelIdStr),
ContentTopic(contentTopicStr),

View File

@ -1365,8 +1365,8 @@ impl LogosDeliveryCtx {
decode_cbor::<String>(&raw_bytes)
}
pub fn channel_create(&self, channel_id_str: String, content_topic_str: String, sender_id_str: String) -> Result<String, String> {
let req = LogosdeliveryChannelCreateReq { channel_id_str, content_topic_str, sender_id_str };
pub fn channel_create(&self, channel_id_str: String, content_topic_str: String, sender_id_str: String, encryption_str: String) -> Result<String, String> {
let req = LogosdeliveryChannelCreateReq { channel_id_str, content_topic_str, sender_id_str, encryption_str };
let req_bytes = encode_cbor(&req)?;
let raw_bytes = ffi_call_sync(self.timeout, |cb, ud| unsafe {
ffi::logosdelivery_channel_create(self.ptr, cb, ud, req_bytes.as_ptr(), req_bytes.len())
@ -1374,8 +1374,8 @@ impl LogosDeliveryCtx {
decode_cbor::<String>(&raw_bytes)
}
pub async fn channel_create_async(&self, channel_id_str: String, content_topic_str: String, sender_id_str: String) -> Result<String, String> {
let req = LogosdeliveryChannelCreateReq { channel_id_str, content_topic_str, sender_id_str };
pub async fn channel_create_async(&self, channel_id_str: String, content_topic_str: String, sender_id_str: String, encryption_str: String) -> Result<String, String> {
let req = LogosdeliveryChannelCreateReq { channel_id_str, content_topic_str, sender_id_str, encryption_str };
let req_bytes = encode_cbor(&req)?;
let ptr = self.ptr as usize;
let raw_bytes = ffi_call_async(self.timeout, move |cb, ud| unsafe {

View File

@ -367,6 +367,8 @@ pub struct LogosdeliveryChannelCreateReq {
pub content_topic_str: String,
#[serde(rename = "senderIdStr")]
pub sender_id_str: String,
#[serde(rename = "encryptionStr")]
pub encryption_str: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]