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

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.

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

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 (get/delete of a missing user, remove of a missing entry).
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.
2520xFCERROR_INTERNALServer-side database failure.
2540xFEERROR_MEMORY_ALLOCServer allocation failure.