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. In the future, servers will also register themselves in the DRD.
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. |
Command codes 140–146 are unique across all RAIDA command groups — no other group uses these numbers.
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 (get/delete of a missing user, remove of a missing entry). |
| 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. |
| 252 | 0xFC | ERROR_INTERNAL | Server-side database failure. |
| 254 | 0xFE | ERROR_MEMORY_ALLOC | Server allocation failure. |