feat(chat): broadcast a tier-3 message across its transactions under one echo

Send side of tier-3 larger messages. sendChatMessage now composes via
composeMessageParts (splitOutgoingMessage), which returns one OutgoingChatMemos
per transaction, and enqueues each on the existing note-buffer coordinator — so
the parts drain sequentially against verified notes exactly like ordinary chat
sends, with no fund-path change (each part is the same pinned 0-value
chatSendOutputs z_sendmany).

A single echo bubble represents the whole message. A new per-echo outstanding-
part counter holds it at "Sending" until the LAST part is broadcast, then flips
it to Sent; if any part hits a hard failure the remaining queued parts are purged
(a message missing a slice can never reassemble, so sending the rest only wastes
fees) and the whole message is failed once — its existing Retry recomposes and
re-splits from the body. A transient-funds deferral still retries the part in
place. The counter map is cleared alongside the send queue on a wallet reset.

Inert until the composer cap is raised (the current 4000-char cap yields a
single tier-2 transaction); that + the multi-transaction composer indicator land
next. Build + tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-10-26 12:36:40 -05:00
co-authored by Claude Opus 4.8
parent 5e33bf2c41
commit e61772a825
4 changed files with 61 additions and 8 deletions
+9
View File
@@ -110,6 +110,15 @@ public:
const std::string& conversationId,
const std::string& plaintext,
OutgoingChatMemos& out) const;
// Construct the outgoing memos for an ENCRYPTED message, splitting it across as many transactions as
// its length needs (larger-messages tier 3). Returns one OutgoingChatMemos per transaction to send in
// order; a short message yields a single element (identical to composeMessage).
ChatComposeStatus composeMessageParts(const std::string& myReplyZaddr,
const std::string& peerPublicKeyHex,
const std::string& peerZaddr,
const std::string& conversationId,
const std::string& plaintext,
std::vector<OutgoingChatMemos>& out) const;
// Construct the outgoing memos for a plaintext contact request (no peer key needed yet).
ChatComposeStatus composeContactRequest(const std::string& myReplyZaddr,
const std::string& peerZaddr,