Documentation Index
Fetch the complete documentation index at: https://docs.ryvo.network/llms.txt
Use this file to discover all available pages before exploring further.
Ryvo stores protocol state in global singletons plus bucketed state accounts. This page describes the live bucket architecture and canonical PDA seeds.
GlobalConfig
Singleton account holding protocol-wide configuration.
Seeds: ["global-config"]
| Field | Type | Notes |
|---|
authority | Pubkey | Active config authority |
fee_recipient | Pubkey | Receives withdrawal fees and registration fees |
fee_bps | u16 | Withdrawal fee in basis points (3–30) |
withdrawal_timelock_seconds | i64 | Fixed at initialize time by chain ID |
registration_fee_lamports | u64 | Flat SOL fee charged at initialize_participant |
next_participant_id | u32 | Monotonic counter for new participants |
bump | u8 | PDA bump |
chain_id | u16 | Deployment chain ID, fixed at initialize |
message_domain | [u8; 16] | Deployment-scoped signing domain |
pending_authority | Pubkey | Nominated successor (two-step handoff) |
_reserved | [u8; 14] | Future expansion |
chain_id and message_domain are immutable after initialize. Updating them would require a fresh deployment.
TokenRegistry
Singleton account holding the allowlist of supported settlement tokens.
Seeds: ["token-registry"]
| Field | Type | Notes |
|---|
authority | Pubkey | Registry authority - can register new tokens |
tokens | Vec<TokenEntry> | Up to 198 entries |
bump | u8 | PDA bump |
pending_authority | Pubkey | Nominated successor (two-step handoff) |
Each TokenEntry (51 bytes):
| Field | Type | Notes |
|---|
id | u16 | Unique token_id used in signed messages |
mint | Pubkey | SPL token mint |
decimals | u8 | Token decimals (≤ 20) |
symbol | [u8; 8] | ASCII symbol, null-terminated |
registered_at | i64 | Unix timestamp of registration (immutable) |
A registered (id, mint) mapping is immutable. The registry authority cannot swap which mint a token_id refers to.
Participant buckets
Participant state is bucketed. A participant ID maps to one slot inside one ParticipantBucket.
Seeds: ["participant-bucket-v2", bucket_id (LE u32)]
Live sizing constants:
PARTICIPANT_BUCKET_SLOT_COUNT = 9
MAX_BUCKET_TOKEN_BALANCES = 16
Routing from participant_id:
bucket_id = participant_id / 9
slot_index = participant_id % 9
Each participant slot stores:
owner
participant_id
inbound_channel_policy
- BLS registration fields (
bls_scheme_version, bls_pubkey_compressed)
- up to 16 token-balance entries (
available_balance, withdrawing_balance, withdrawal_unlock_at, withdrawal_destination)
Owner index buckets
Owner lookup is bucketed separately so owner -> participant_id resolution stays deterministic.
Seeds: ["owner-index-bucket-v2", bucket_id (LE u32)]
Live sizing constants:
OWNER_INDEX_BUCKET_COUNT = 1024
OWNER_INDEX_BUCKET_SLOT_COUNT = 32
Routing from owner:
bucket_id = sha256(owner)[0..4] % 1024
Channel buckets
Channel state is also bucketed by token and participant pair ordinal.
Seeds: ["channel-bucket-v2", token_id (LE u16), bucket_id (LE u32)]
Live sizing constants:
CHANNEL_BUCKET_SLOT_COUNT = 46
Each slot stores one canonical participant pair (lower_participant_id, higher_participant_id) and two directional lanes:
lower_to_higher
higher_to_lower
Each directional lane stores:
settled_cumulative
locked_balance
authorized_signer
- pending unlock fields
- pending signer-rotation fields
Canonical lane selection is derived from (payer_id, payee_id) ordering, so settlement always writes one deterministic lane per direction.
Protocol vault
Tokens deposited into Ryvo live in per-token vault token accounts derived from the program. They are SPL Token accounts owned by the program, not participant balances. Participant available_balance and channel locked_balance are ledger positions against this vault, the vault is the single source of truth for tokens actually held by the program.
See Balances and withdrawals for how the vault relates to participant state.
See also