DRD Overview (Group 16)

The Distributed Resource Directory. Users publish a small public record about themselves — name, inbox fee, and avatar symbols — keyed by their coin’s denomination and serial number, and privately manage a white/black list of other users. QMail consults this data to decide whether mail may be sent and what inbox fee applies. Servers also publish server-role descriptors via commands 149/150.

Overview

The DRD is a directory service hosted independently on every RAIDA. Each server keeps its own copy of two tables:

  • Users — one public record per identity coin: first name, last name, inbox fee, two avatar symbol bytes, a class-rejection byte (minimum sender denomination), and two server-stamped timestamps (created_at, updated_at).
  • White/black lists — private per-user entries naming other users. A whitelisted sender requires no payment to send QMail; a blacklisted sender is denied.

Records are searchable three ways: by the owner’s denomination + serial number (an exact key lookup), by first name, and by last name. Name searches are case-insensitive prefix matches — searching for ali finds Alice and Alison.

Anti-scam timestamp

created_at is stamped by the server the first time a record is posted and is never changed by later updates. Clients should display account age so users can spot freshly created look-alike accounts. Only deleting the record and re-posting resets it — which also resets the record’s history everywhere else.

Commands

CodeHexCommandAuthPurpose
1400x8Cpost_userOwner ANCreate or update your own directory record.
1410x8Dget_userNoneFetch one record by denomination + serial number.
1420x8Esearch_usersNonePrefix-search records by first and/or last name.
1430x8Fdelete_userOwner ANRemove your own directory record.
1440x90list_setOwner ANAdd or update white/black list entries (batch).
1450x91list_removeOwner ANRemove white/black list entries (batch).
1460x92list_getOwner ANRead your own white/black list. Private to the owner.
1470x93get_changesNoneRead sharded DRD changes feed for sync clients.
1480x94statsNoneRead DRD aggregate counts/statistics.
1490x95server_postIdentity coin (dn+sn+AN)Post one role descriptor (raida/qmail/beacon/drd/rke).
1500x96server_getNoneRead one/all server-role descriptors.

Command codes 140–150 are unique across all RAIDA command groups — no other group uses these numbers. Commands 149 and 150 are HV=2 only.

Identity & authentication

A DRD identity is a coin, addressed by its PQ: 1 byte denomination (signed, −8 to +6) followed by a 4-byte big-endian serial number — the same 5-byte form used throughout the RAIDA protocol.

Every command that changes a record (140, 143, 144, 145) and the private list read (146) carries the owner’s 16-byte Authenticity Number in the request body. The server compares it against the stored AN for that denomination/serial in the coin database — the exact same check detect (Group 1, cmd 10) performs per coin. A mismatch returns ERROR_INVALID_AN (200) and nothing is written; an unknown coin returns ERROR_INVALID_SN_OR_DENOMINATION (40). Read commands 141 and 142 carry no AN and are open to everyone.

Inbox fee encoding

The inbox fee is a decimal CloudCoin amount, e.g. 10992.934002. On the wire and in storage it is an 8-byte big-endian signed integer counting 10−8 CC units — the smallest denomination that exists (DEN_0_00000001 = −8). This keeps every representable fee exact; no floating point is used anywhere.

fee_units = fee_in_CC × 100,000,000

10992.934002 CC  →  1,099,293,400,200 units  →  00 00 00 FF F2 FE 1C 88
0.00000001 CC    →  1 unit                   →  00 00 00 00 00 00 00 01
0 CC (free)      →  0 units                  →  00 00 00 00 00 00 00 00

Negative fees are rejected with ERROR_INVALID_PARAMETER. Fees with more than 8 fractional decimal digits cannot be represented and must not be sent.

Default Tell fee for unregistered users

A recipient with no DRD record is not free to message: the beacon charges a default Tell fee of 10 CC. Without it, a spammer could sweep sequential serial numbers (if 22.34 exists, 22.33 and 22.35 probably do too) and every newly created qmailbox would receive the spam instantly. The value and an on/off switch live in each server’s config.toml under [drd] (default_tell_fee, default_tell_fee_enabled) so it can be disabled until client software lets users set their own fees. Posting a record with an explicit fee — including 0 — always overrides the default. See the Tell DRD gate for how this is enforced.

Avatar symbols

Every client ships the same table of 256 SVG symbols. A user picks two (first symbol, second symbol), letting them compose a personalized avatar while costing only 2 bytes on the wire. The server stores and returns these bytes verbatim and never validates them — any value 0–255 is legal in each slot.

Class rejection (minimum sender denomination)

Every user record carries a 1-byte class-rejection value: the minimum denomination a sender’s address coin must have for this user to accept their QMail. QMail address classes are tied to coin denominations, so this lets a user refuse mail from cheap, throwaway low-denomination addresses regardless of any fee paid.

The byte is signed and uses the standard denomination encoding — keep this in mind in any comparison logic:

0x00 =  0  = 1 CC (.bit)        DEFAULT: accepts ALL denominations (no filtering)
0x01 =  1  = 10 CC (.byte)      rejects 1 CC and below, accepts 10 CC and up
0x02 =  2  = 100 CC (.kilo)     rejects 10 CC and below
0xFF = -1  = 0.1 CC (a dime)    rejects 0.01 CC and below - signed! 0xFF < 0x00
0xF8 = -8  = 0.00000001 CC      lowest denomination that exists

0x00 is special: it is the default and disables denomination filtering entirely. Any other value must be a valid denomination (−8…+6) and rejects senders whose address denomination is below it (signed comparison). Enforcement happens at the QMail Tell gate, which returns ERROR_SENDER_CLASS_REJECTED (237); a whitelist entry bypasses the check.

Privacy model

DataWho can readWho can write
User record (name, fee, symbols, timestamps)Everyone (141, 142)Owner only, AN-authenticated (140, 143)
White/black list entriesOwner only, AN-authenticated (146)Owner only, AN-authenticated (144, 145)

White/black lists are private because they reveal a user’s social graph and disputes. Note that whether a specific sender is allowed is still learned indirectly through QMail behavior (mail accepted, fee waived, or denied) — the DRD simply refuses to enumerate anyone’s list to third parties.

Distribution model

Each RAIDA’s DRD is fully independent — there is no server-to-server synchronization. The client is responsible for consistency:

  • Writes: send the same command to all 25 RAIDAs in parallel.
  • Reads: query one or a few RAIDAs; compare answers if it matters.
  • Repair: if servers disagree (a write missed some RAIDAs), the client re-posts its record to the servers that are behind.

Record formats

User record (variable length, 34 + names bytes)

Returned by get_user and search_users. Names are UTF-8, length-prefixed, maximum 63 bytes each.

OffsetSizeFieldDescription
01DenominationSigned byte, −8 to +6.
1–44Serial NumberBig-endian.
5–128Inbox feeBig-endian signed units of 10−8 CC.
131First symbolIndex into the 256-entry client SVG symbol table.
141Second symbolSecond symbol index.
151Class rejectionSigned minimum sender denomination; 0x00 = accept all. See Class rejection.
16–238created_atBig-endian Unix seconds; set on first post, never changed by updates.
24–318updated_atBig-endian Unix seconds; refreshed on every post.
321First-name length0–63.
33...varFirst nameUTF-8, no NUL terminator.
...1Last-name length0–63.
...varLast nameUTF-8, no NUL terminator.

List entry (6 bytes)

OffsetSizeFieldDescription
01Listed denominationDenomination of the listed user’s coin.
1–44Listed serial numberBig-endian.
51List type0x00 = whitelist (no payment required), 0x01 = blacklist (mail denied).

Status codes

DRD uses the standard RAIDA status enum from protocol.h. The codes any DRD handler can return:

DecimalHexSymbolMeaning
2500xFASTATUS_SUCCESSCommand completed successfully.
160x10ERROR_INVALID_PACKET_LENGTHBody shorter than the command requires, or trailing bytes after the last defined field.
360x24ERROR_EMPTY_REQUESTRequest arrived with no body at all.
390x27ERROR_COINS_NOT_DIVBatch list payload length is not a whole number of entries (144: 6-byte entries, 145: 5-byte entries).
400x28ERROR_INVALID_SN_OR_DENOMINATIONThe authenticating denomination/serial is not a coin this RAIDA holds.
1930xC1ERROR_NO_ENTRYThe requested record does not exist (missing user/list row, or 150 selector miss).
1980xC6ERROR_INVALID_PARAMETERField validation failed: negative fee, invalid class-rejection value, name longer than 63 bytes, bad list type, or a search with no name fields.
2000xC8ERROR_INVALID_ANThe presented AN does not match the stored AN for the denomination/serial.
2180xDAERROR_TCP_REQUIREDResponse is too large for one UDP datagram (for example 147/150 listings); retry over TCP.
2190xDBERROR_UNSUPPORTED_PROTOCOLCommand requires a newer protocol version (149/150 require HV=2).
2520xFCERROR_INTERNALServer-side database failure.
2540xFEERROR_MEMORY_ALLOCServer allocation failure.