Client Config CLI (rakurai-client-config)
Manage on-chain block-engine (recv bundles), post-pack / P2C (send txns for backrun), and virtual-priority (percent of a tip account’s tip) settings for Rakurai validators.
Audience: Rakurai ops (manager) and validator operators (proposals).
Program: rakurai_client_config.
Install: CLI overview.
This CLI does not manage TCA / PSA / MCA money accounts — only scheduler endpoints and virtual-priority tip maps.
1. Full payload: current + new
global update, validator update, proposal submit, and proposal update replace the entire on-chain Config. There is no patch/merge on write.
To add a block-engine, P2C, or virtual-priority set:
- Dump current config (
global show,validator show, orunion --vote) - Copy it
- Append the new named set (keep every set you still want)
- Submit that file
Do not submit a JSON that only contains the new set. That file becomes the whole PDA contents; other sets on that account are deleted.
union is a read: validator PDA if it exists, otherwise global. It does not merge payloads.
Worked example — add P2C p2c-new-1 on global when global already has p2c-main-1 and p2c-main-2:
{ "block_engine": { "sets": [ /* unchanged: copy from global show */ ] }, "p2c": { "sets": [ { "name": "p2c-main-1", "url": "https://p2c1.example", "mev": true }, { "name": "p2c-main-2", "url": "https://p2c2.example", "mev": true }, { "name": "p2c-new-1", "url": "https://p2c-new.example", "mev": true } ] }, "virtual_priority": { "sets": [ /* unchanged: copy from global show */ ] } }
Same pattern for a new block engine or virtual-priority set. Block engine allows one URL per UUID. P2C is one URL per UUID with optional mev / resell / enable_tpu_p2c_update (at least one of mev|resell; TPU only with mev).
examples/validator_config_overlay.json is not a write template. It only shows extra validator-named sets. Fold those extras into a full current snapshot before validator update or proposal submit.
2. Layers
| Account | Who | Meaning |
|---|---|---|
| Global | Manager | Defaults + size caps for every validator |
Validator (per --vote) | Manager | Live overlay + size caps (proposals use these) |
| Proposal | Operator → manager approve/reject | Draft; live unchanged until approve |
Effective config the node uses = validator PDA if present, otherwise global. No merge. union --vote prints that.
Size caps (ConfigLimits::V1) live on global/validator/proposal PDAs (≤ absolute safety max). Init: global init → validator init. Proposals snapshot validator limits on submit/update.
3. JSON shape
Each file has all three sections. See examples/validator_config.json.
{ "block_engine": { "sets": [ { "name": "be-main-1", "url": { "url": "https://be1.example", "max_bundles": 100, "period_ms": 100, "max_bundle_burst": 0 } } ] }, "p2c": { "sets": [ { "name": "p2c-main-1", "url": "https://p2c1.example", "mev": true, "resell": true, "enable_tpu_p2c_update": true } ] }, "virtual_priority": { "sets": [ { "name": "vp-main-1", "url": [{ "key": "<PUBKEY>", "value": 0.1 }] } ] } }
| Section | Fields |
|---|---|
| Block engine | One url object per UUID: url, max_bundles, period_ms, max_bundle_burst (0 = unlimited / treat burst as max_bundles when quota is set). Scheduler receives bundles from these URLs. |
| P2C | One url per UUID. Optional resell → StartExpiringPacketStream (no boost/TPU). Optional mev → StartExpiringMevPacketStream (boost); optional enable_tpu_p2c_update → TPU on Mev path. Both may be true (two connections, distinct hashes). See Post-pack confirmations. |
| Virtual priority | key (tip-account pubkey), value (fraction of that tip in [0.0, 1.0]; e.g. 0.1 = 10%) |
name is truncated to 32 bytes. Omit --config-file on global init to create empty sets, then update with a full file.
4. Global flags
| Flag | Default | Description |
|---|---|---|
-k, --keypair | ~/.config/solana/id.json | Manager or operator, depending on command |
-u, --url | t (testnet) | RPC URL or l / t / d / m |
-p, --program-id | 4uGNMjJFxgE3TfEiPmSpvfwYah12QZbaWWZDJqZvA9F4 | Program ID |
rakurai-client-config --url <RPC_URL> --program-id <PROGRAM_ID> --keypair <KEYPAIR> <COMMAND>
5. Commands
Always pass a full --config-file on update / submit.
Large configs are uploaded via ephemeral staging PDAs. If a previous staging upload failed mid-way, the CLI aborts any existing staging account before starting a new upload so init cannot fail on “account already exists”.
5.1. Global (manager)
rakurai-client-config global init --config-file cli/examples/validator_config.json # Optional caps on init (defaults shown): # --max-url-len 256 --max-sets-per-section 16 --max-urls-per-set 8 --max-vp-entries-per-set 64 rakurai-client-config global show # Edit the printed JSON (current + new), save, then: rakurai-client-config global update --config-file /tmp/global-current-plus-new.json rakurai-client-config global set-limits --max-url-len 256 --max-sets-per-section 16 rakurai-client-config global close
5.2. Validator live PDA (manager)
rakurai-client-config validator init --vote <VOTE_PUBKEY> --operator <OPERATOR_PUBKEY> rakurai-client-config validator set-operator --vote <VOTE_PUBKEY> --operator <OPERATOR_PUBKEY> rakurai-client-config validator set-limits --vote <VOTE_PUBKEY> --max-url-len 256 rakurai-client-config validator show --vote <VOTE_PUBKEY> rakurai-client-config validator update --vote <VOTE_PUBKEY> --config-file /tmp/validator-current-plus-new.json rakurai-client-config validator close --vote <VOTE_PUBKEY>
validator init copies then-current global config and limits. Later global edits do not rewrite existing validator PDAs.
5.3. Proposal (operator → manager)
# Operator: current validator/union JSON + new sets rakurai-client-config -k operator.json proposal submit --vote <VOTE> \ --config-file /tmp/proposal-current-plus-new.json rakurai-client-config proposal show --vote <VOTE> # Manager rakurai-client-config -k manager.json proposal approve --vote <VOTE> rakurai-client-config -k manager.json proposal reject --vote <VOTE>
5.4. Union
rakurai-client-config union rakurai-client-config union --vote <VOTE_PUBKEY>
6. Proposal flow (step by step)
Goal: operator proposes a new P2C set for one vote. The file they submit is the entire live validator config after approve — keep every current set and append the new one.
Placeholders: <VOTE>, manager keypair manager.json, operator keypair operator.json.
6.1. Step 1 — Manager: create the live validator PDA and name the operator
rakurai-client-config -k manager.json validator init \ --vote <VOTE> \ --operator <OPERATOR_PUBKEY>
This copies then-current global onto the validator PDA. Only this operator can proposal submit for that vote.
6.2. Step 2 — Operator: dump what is live today
Use whichever snapshot you will edit. union --vote is the effective config (validator PDA if present, else global). After validator init, that is the validator PDA.
rakurai-client-config union --vote <VOTE> # or rakurai-client-config validator show --vote <VOTE>
Copy the printed block_engine / p2c / virtual_priority sets into a file, e.g. /tmp/proposal-current-plus-new.json.
6.3. Step 3 — Operator: add the new set (keep current)
Do not send a file that only contains the new set. Example — current P2C p2c-main-1 stays, new p2c-op-1 is appended:
{ "block_engine": { "sets": [ /* copy from show / union — unchanged */ ] }, "p2c": { "sets": [ { "name": "p2c-main-1", "url": "https://p2c1.example", "mev": true }, { "name": "p2c-op-1", "url": "https://p2c-operator.example", "mev": true } ] }, "virtual_priority": { "sets": [ /* copy from show / union — unchanged */ ] } }
Same idea for a new block-engine or virtual-priority set.
6.4. Step 4 — Operator: submit the draft
Live validator config is unchanged until the manager acts.
rakurai-client-config -k operator.json proposal submit \ --vote <VOTE> \ --config-file /tmp/proposal-current-plus-new.json rakurai-client-config proposal show --vote <VOTE>
Re-run proposal submit with an updated full file to replace the draft before approve.
6.5. Step 5 — Manager: approve or reject
# Approve: proposal payload becomes the entire live validator config; proposal PDA is closed rakurai-client-config -k manager.json proposal approve --vote <VOTE> # Reject: live validator config stays as-is; proposal PDA is closed rakurai-client-config -k manager.json proposal reject --vote <VOTE>
After approve, validator show --vote <VOTE> should match the JSON from step 3. union --vote <VOTE> prints that same validator payload.
7. Help
rakurai-client-config --help rakurai-client-config global --help rakurai-client-config validator --help rakurai-client-config proposal --help