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
| Code | Hex | Command | Auth | Purpose |
|---|---|---|---|---|
| 140 | 0x8C | post_user | Owner AN | Create or update your own directory record. |
| 141 | 0x8D | get_user | None | Fetch one record by denomination + serial number. |
| 142 | 0x8E | search_users | None | Prefix-search records by first and/or last name. |
| 143 | 0x8F | delete_user | Owner AN | Remove your own directory record. |
| 144 | 0x90 | list_set | Owner AN | Add or update white/black list entries (batch). |
| 145 | 0x91 | list_remove | Owner AN | Remove white/black list entries (batch). |
| 146 | 0x92 | list_get | Owner AN | Read your own white/black list. Private to the owner. |
| 147 | 0x93 | get_changes | None | Read sharded DRD changes feed for sync clients. |
| 148 | 0x94 | stats | None | Read DRD aggregate counts/statistics. |
| 149 | 0x95 | server_post | Identity coin (dn+sn+AN) | Post one role descriptor (raida/qmail/beacon/drd/rke). |
| 150 | 0x96 | server_get | None | Read 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
| Data | Who can read | Who can write |
|---|---|---|
| User record (name, fee, symbols, timestamps) | Everyone (141, 142) | Owner only, AN-authenticated (140, 143) |
| White/black list entries | Owner 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.
| Offset | Size | Field | Description |
|---|---|---|---|
| 0 | 1 | Denomination | Signed byte, −8 to +6. |
| 1–4 | 4 | Serial Number | Big-endian. |
| 5–12 | 8 | Inbox fee | Big-endian signed units of 10−8 CC. |
| 13 | 1 | First symbol | Index into the 256-entry client SVG symbol table. |
| 14 | 1 | Second symbol | Second symbol index. |
| 15 | 1 | Class rejection | Signed minimum sender denomination; 0x00 = accept all. See Class rejection. |
| 16–23 | 8 | created_at | Big-endian Unix seconds; set on first post, never changed by updates. |
| 24–31 | 8 | updated_at | Big-endian Unix seconds; refreshed on every post. |
| 32 | 1 | First-name length | 0–63. |
| 33... | var | First name | UTF-8, no NUL terminator. |
| ... | 1 | Last-name length | 0–63. |
| ... | var | Last name | UTF-8, no NUL terminator. |
List entry (6 bytes)
| Offset | Size | Field | Description |
|---|---|---|---|
| 0 | 1 | Listed denomination | Denomination of the listed user’s coin. |
| 1–4 | 4 | Listed serial number | Big-endian. |
| 5 | 1 | List type | 0x00 = 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:
| Decimal | Hex | Symbol | Meaning |
|---|---|---|---|
| 250 | 0xFA | STATUS_SUCCESS | Command completed successfully. |
| 16 | 0x10 | ERROR_INVALID_PACKET_LENGTH | Body shorter than the command requires, or trailing bytes after the last defined field. |
| 36 | 0x24 | ERROR_EMPTY_REQUEST | Request arrived with no body at all. |
| 39 | 0x27 | ERROR_COINS_NOT_DIV | Batch list payload length is not a whole number of entries (144: 6-byte entries, 145: 5-byte entries). |
| 40 | 0x28 | ERROR_INVALID_SN_OR_DENOMINATION | The authenticating denomination/serial is not a coin this RAIDA holds. |
| 193 | 0xC1 | ERROR_NO_ENTRY | The requested record does not exist (missing user/list row, or 150 selector miss). |
| 198 | 0xC6 | ERROR_INVALID_PARAMETER | Field validation failed: negative fee, invalid class-rejection value, name longer than 63 bytes, bad list type, or a search with no name fields. |
| 200 | 0xC8 | ERROR_INVALID_AN | The presented AN does not match the stored AN for the denomination/serial. |
| 218 | 0xDA | ERROR_TCP_REQUIRED | Response is too large for one UDP datagram (for example 147/150 listings); retry over TCP. |
| 219 | 0xDB | ERROR_UNSUPPORTED_PROTOCOL | Command requires a newer protocol version (149/150 require HV=2). |
| 252 | 0xFC | ERROR_INTERNAL | Server-side database failure. |
| 254 | 0xFE | ERROR_MEMORY_ALLOC | Server allocation failure. |