an application-level interface that sits between the application layer and the [MESSAGING-API](/standards/application/messaging-api.md) plus [P2P-RELIABILITY](/standards/application/p2p-reliability.md), i.e., `application`<->**reliable-channel-api**<->`messaging-api/p2p-reliability`.
It bundles segmentation, end-to-end reliability via [Scalable Data Sync (SDS)](https://lip.logos.co/ift-ts/raw/sds.html), rate limit management, and a pluggable encryption hook
into a single interface for sending and receiving messages reliably.
## Motivation
The [MESSAGING-API](/standards/application/messaging-api.md) provides peer-to-peer reliability via [P2P-RELIABILITY](/standards/application/p2p-reliability.md),
but does not provide high end-to-end delivery guarantees from sender to recipient.
This API addresses that gap by introducing:
- **Segmentation** to handle large messages exceeding network size limits.
- **SDS** to provide causal-history-based end-to-end acknowledgement and retransmission.
- **Rate Limit Manager** to comply with [RLN](https://lip.logos.co/messaging/standards/core/17/rln-relay.html) constraints when sending segmented messages.
- **Encryption Hook** to allow upper layers to provide a pluggable encryption mechanism. The main motivation for encryption is to protect the payload and content_topic from MessageEnvelope, defined in [MESSAGING-API](/standards/application/messaging-api.md).
This API considers the types defined by [MESSAGING-API](/standards/application/messaging-api.md) plus the following:
```yaml
types:
MessageChunk:
type: object
description: "Represents the minimum unit of data transmitted across the network. Its size is governed by SegmentationConfig. Chunks are chained to their predecessors, and any chunk whose linkage to its predecessor cannot be verified MUST be discarded.
Only the first chunk on every message, is rate-limited (RLN) and the subsequent chunks MUST be accepted rate-limit wise."
fields:
chunkId:
type: string
description: UUID for the chunk
previousChunkId:
type: string
description: Previous chunk ID. Chunks with unvalidated previous chunks MUST be rejected.
This field is empty when chunkIndex == 0.
chunkIndex:
type: uint
description: "Zero-based position of this chunk within the ordered sequence of chunks that form the original message."
lastChunkIndex:
type: uint
description: "All chunks of same message have the same value, i.e., num-chunks - 1."
description: "The request id this chunk belongs to. This is generated by the send function. `RequestId` is defined in [MESSAGING-API](./messaging-api.md)."
description: "Represents an extension of the MessageEnvelope defined in MESSAGING-API aiming mostly to allow
including a reliable channel id attribute that, when given, it will assume the message should be sent reliably. Therefore, we leave open for implementors to replace the MessageEnvelope implementation and just add the reliable channel id there."
fields:
messageEnvelope:
type: MessageEnvelope
description: "Please refer to the [MESSAGING-API](/standards/application/messaging-api.md) for details."
description: "Current synchronisation status of the channel. Transitions between 'syncing' and 'synced' as missing messages are detected and resolved."
description: "Time in milliseconds to wait for acknowledgement before retransmitting."
maxRetransmissions:
type: uint
default: 5
description: "Maximum number of retransmission attempts before considering delivery failed."
causalHistorySize:
type: uint
default: 2
description: "Number of message IDs to consider in the causal history. With longer value, a stronger correctness is guaranteed but it requires higher bandwidth and memory."
RateLimitConfig:
type: object
fields:
enabled:
type: bool
default: true
description: "Whether rate limiting is enforced. SHOULD be true when RLN is active."
epochSizeMs:
type: uint
default: 600000 # 10 minutes
description: "The epoch size used by the RLN relay, in milliseconds. Only the first message chunk is rate limited."
When an `IEncryption` implementation is provided, it MUST be applied as described in the [Messaging extended definitions](#messaging-extended-definitions).
When `send` is called, the implementation MUST process the message in the following order:
1.**Segment**: Split the payload into chunks of at most `chunkSizeBytes` as defined in `SegmentationConfig`.
2.**Apply SDS**: Register each chunk with the SDS layer to track acknowledgements and enable retransmission.
3.**Encrypt**: If an `IEncryption` implementation is provided, encrypt each chunk before transmission.
4.**Dispatch**: Send each chunk via the underlying [MESSAGING-API](/standards/application/messaging-api.md).
**Incoming message processing order**:
When a chunk is received from the network, the implementation MUST process it in the following order:
1.**Decrypt**: If an `IEncryption` implementation is provided, decrypt the chunk.
2.**Apply SDS**: Deliver the chunk to the SDS layer, which emits acknowledgements and detects gaps.
3.**Reassemble**: Once all chunks for a message have been received, reassemble and emit a `reliable:message:received` event.
**Retransmission**:
The SDS layer MUST retransmit unacknowledged chunks after `acknowledgementTimeoutMs`,
up to `maxRetransmissions` times.
If a chunk is not acknowledged after all retransmission attempts, a `reliable:message:send-error` event MUST be emitted.
**Rate limiting**:
When `RateLimitConfig.enabled` is `true`, the implementation MUST space chunk transmissions
to comply with the RLN epoch constraints defined in `epochSizeMs`.
Chunks MUST NOT be sent at a rate that would violate the RLN message rate limit for the active epoch.
## Components
### Segmentation
Segmentation splits outgoing messages into chunks before SDS processing.
This ensures each chunk fits within the network's maximum message size.
- The default chunk size is `100 KiB` (`102400 bytes`.)
- Chunks MUST be tagged with metadata sufficient for the receiver to reassemble the original message:
a message identifier, chunk index, and total chunk count.
- Segmentation MUST be transparent to the SDS layer; SDS operates on individual chunks.
- The maximum allowed message size is `1MiB` (`1048576 bytes`.)
- Messages that are bigger than the maximum allowed size will be discarded automatically and an error will be given to the caller.
### Scalable Data Sync (SDS)
SDS provides end-to-end delivery guarantees using causal history tracking.
- Each sent chunk is registered in an outgoing buffer.
- The recipient sends acknowledgements back to the sender upon receiving chunks.
- The sender removes acknowledged chunks from the outgoing buffer.
- Unacknowledged chunks are retransmitted after `acknowledgementTimeoutMs`.
- SDS state MUST be persisted in the configured `historyBackend`.
### Rate Limit Manager
The Rate Limit Manager ensures compliance with [RLN](https://lip.logos.co/messaging/standards/core/17/rln-relay.html) rate constraints.
- It tracks how many messages have been sent in the current epoch (only the first chunk of each message counts toward the rate limit; subsequent chunks are exempt).
- When the limit is approached, chunk dispatch MUST be delayed to the next epoch.
- The epoch size MUST match the `epochSizeMs` configured in `RateLimitConfig`.
### Encryption Hook
The Encryption Hook provides a pluggable interface for upper layers to inject encryption.
- The hook is optional; when not provided, messages are sent as plaintext.
- Encryption is applied per chunk, after segmentation and SDS registration.
- Decryption is applied per chunk, before SDS delivery.