diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 95b55ca3..05ff71c5 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -70,11 +70,11 @@ All instance-storage keys share **one** `LedgerEntry` (the contract instance). T Each key is a separate `LedgerEntry` with its own independently tracked TTL. -| Key | Type | Description | TTL — bump / threshold (ledgers) | Approx. cost (XLM / 30 days) | -| --------------------- | -------------- | ------------------------------------ | -------------------------------- | ---------------------------- | -| `OWNERS` | `Vec
` | Fixed owner set (max 20 addresses) | 518,400 / 17,280 | ~0.052 XLM | -| `("PROP", id)` | `Proposal` | Per-proposal state | 518,400 / 17,280 | ~0.052 XLM | -| `("APPR", id, owner)` | `bool` | Per-owner approval flag per proposal | 518,400 / 17,280 | ~0.052 XLM | +| Key | Type | Description | TTL — bump / threshold (ledgers) | Approx. cost (XLM / 30 days) | +| --------------------- | ------------------ | ------------------------------------------ | -------------------------------- | ---------------------------- | +| `OWNERS` | `Map` | Owner address → voting weight map (max 20) | 518,400 / 17,280 | ~0.052 XLM | +| `("PROP", id)` | `Proposal` | Per-proposal state | 518,400 / 17,280 | ~0.052 XLM | +| `("APPR", id, owner)` | `u32` | Per-owner approval weight per proposal | 518,400 / 17,280 | ~0.052 XLM | ### Proposal Struct Fields @@ -108,7 +108,8 @@ Accord uses two patterns: | `NEXT` | Monotonic proposal ID counter | | `ACTCNT` | Count of currently active proposals | | `TLOCK` | Time-lock delay in seconds | -| `OWNERS` | Owner address list | +| `TWGT` | Cached total owner weight | +| `OWNERS` | Owner address → weight map | **Tuple keys** — two- or three-part tuples for per-entity records, where the first element is a short symbol namespace: @@ -174,23 +175,49 @@ rent_fee_stroops = ceil(entry_size_bytes / 1024) × fee_rate_1kb × delta_ledger | `("PROP", id)` entry size | ~396 bytes (100-char description) | XDR field sum below; 300-char max adds ~200 bytes, still rounds to 1 KB | | `("APPR", id, owner)` entry size | ~144 bytes | XDR field sum below | +**XDR byte breakdown — `OWNERS` entry (Map):** + +| Field | XDR bytes | +| ---------------------------------- | ------------------------------- | +| Key (`OWNERS` symbol) | 8 | +| Map length prefix | 4 | +| Per entry: Address (discriminant + ed25519 key) | 40 | +| Per entry: u32 weight | 4 | +| **1 owner** | **52 bytes → 1 KB billed** | +| **7 owners** | **316 bytes → 1 KB billed** | +| **20 owners (max)** | **808 bytes → 1 KB billed** | + +**Before weighted governance:** `OWNERS` was `Vec` — 1 owner = 52 bytes, 7 owners = 332 bytes, 20 owners = 820 bytes. The `Map` adds 4 bytes per entry for the weight value, yielding a modest increase. + +**XDR byte breakdown — `("APPR", id, owner)` approval entry (weighted):** + +| Field | XDR bytes | +| ------------------------------------- | ---------------------------- | +| Key (`"APPR"` symbol + u64 + Address) | 60 | +| Value (`u32` approval weight) | 4 | +| LedgerEntry framing and metadata | ~80 | +| **Total** | **~144 bytes → 1 KB billed** | + +**Before weighted governance:** the approval entry stored a `bool` (4 bytes). After: stores a `u32` weight (4 bytes) — same byte count, different semantic. + **XDR byte breakdown — `("PROP", id)` Proposal entry (100-char description):** | Field | XDR bytes | | ---------------------------------------------------------- | ---------------------------- | | Key (`"PROP"` symbol + u64 id) | 16 | | `id` (u64) | 8 | -| `proposer` (Address) | 44 | -| `description` (String, 100 chars) | 108 | +| `proposer` (Address) | 40 | +| `description` (String, 100 chars) | 104 | | `deadline` (u64) | 8 | | `approvals` (u32) | 4 | +| `approval_weight` (u32) | 4 | | `status` (enum) | 4 | -| `kind` (Transfer: discriminant + Address + i128 + Address) | 108 | +| `kind` (Transfer: discriminant + Vec