daitchain

x/messaging Real (skeleton)

Wallet-to-wallet encrypted messaging. The chain stores pubkeys, contact graphs, group state, block lists, and quotas. Message bodies travel off-chain over a libp2p Waku relay using libsignal (X3DH + Double Ratchet) for 1:1 and OpenMLS (RFC 9420) for groups.

Design

The chain stores everything you need to addressbook and authenticate; it never stores message bodies. Spam mitigation layers against x/staking_tiers: each tier has a daily message quota, and senders can extend it by burning DAIT via MsgQuotaPurchase.

Quota window: rolling 24h, not UTC midnight

A strict UTC-midnight reset is replay-attackable: an attacker drains their quota at 23:59 UTC then drains it again at 00:01 UTC. The keeper instead tracks window_start_unix per account; the window resets when now - window_start >= 24h. See keeper/quotas.go::ConsumeQuota.

Messages (12)

// Pubkeys
MsgRegisterPubkey   { signer, pubkey, kind }
MsgRotatePubkey     { signer, new_pubkey, prev_sig }

// Contact graph
MsgAddContact       MsgRemoveContact

// Block list
MsgBlock            MsgUnblock

// Groups (MLS state on-chain)
MsgCreateGroup      MsgUpdateGroup     MsgLeaveGroup

// Receipts + quota
MsgReadReceipt      MsgQuotaPurchase
MsgUpdateParams     // gov-only

Queries

Cross-module hooks

What's wired today

Real Module wiring, params storage + tier-quota table, KV store layout + iterators, rolling-24h quota state machine and ConsumeQuota, all read queries, ValidateBasic for every Msg, gov-only MsgUpdateParams.

Phase 1 Pubkey registration / rotation handlers, consensual contact-graph two-call protocol, MLS group state machine (epoch monotonic, member churn), MsgQuotaPurchase burn via BankKeeper.BurnCoins, agent cross-hook for agent-sent messages.

Phase 2 RLN nullifier integration for stronger spam protection, off-chain Waku relay protocol bindings, XMTP interop gateway.

See also