Galaxy King Dog / Supporting design document

Deploy checklist — gkd_chain

Step-by-step deploy + initialization for the gkd_chain program. Handles real SOL — do a devnet dry-run and ideally a security audit first. I only ever need public keys; you run the signing commands yourself.

0. What you provide

Item What Notes
Founder/creator pubkey wallet that receives the 49% creator split public key only
Admin/deployer keypair deploys + initializes + upgrade authority you hold/sign this
Program keypair the program's address reuse target/deploy/gkd_chain-keypair.json or generate a new one
Pyth SOL/USD account price feed for the weekly $0.10 re-peg the feed account pubkey on the target cluster
(optional) 2/3 multisig 3 member pubkeys for fee override + pause
(optional) charity ops charity wallet pubkeys added later via whitelist_charity

8qCpYyRjdG8Y1jW5fu77XZ3qkWErgABhscEuuY4mRjnr is the devnet-only creator wallet. Never use it as the mainnet founder/creator pubkey; mainnet initialization requires a separately supplied wallet.

1. Program id

The repo currently uses a placeholder id. Pick the program keypair you will deploy, then sync the id:

solana address -k target/deploy/gkd_chain-keypair.json     # your real program id
# put that id in BOTH:
#   programs/gkd_chain/src/lib.rs   -> declare_id!("<ID>")
#   Anchor.toml                     -> [programs.mainnet]/[programs.devnet] gkd_chain = "<ID>"
#   src/chain/chain_config.js       -> programId

Rebuild after changing declare_id! (Windows toolchain workaround — see POOL_MECHANISM.md):

rustup toolchain link 1.84.1-sbpf-solana-v1.51 "$HOME/.cache/solana/v1.51/platform-tools/rust"
export PATH="$HOME/.cargo/bin:$PATH"
( cd programs/gkd_chain && cargo-build-sbf --skip-tools-install )

tools/dryrun_local.js runs the full core init sequence (config → pools → token → record → leaderboard → season) and verifies every account/PDA on a live validator.

  • Local validator (fastest): on Windows enable Developer Mode (or run elevated) so solana-test-validator can create its symlinks, then:
    solana-test-validator --reset
    solana program deploy target/deploy/gkd_chain.so --program-id target/deploy/gkd_chain-keypair.json --url localhost
    node tools/dryrun_local.js
    
  • Devnet (no Developer Mode needed): solana config set --url devnet, fund the deployer (solana airdrop in small chunks until you have ~6 SOL), solana program deploy ... --url devnet, then RPC_URL=https://api.devnet.solana.com node tools/dryrun_local.js.

Expected: DRY-RUN PASS ✅. NFT/governance/fee-refresh paths need Metaplex/Pyth accounts and are covered by cargo test -p gkd_chain + the Ed25519 layout cross-check.

Then validate the exact canonical browser client through the persistent strict verifier and the real Devnet program:

npm run verifier:key:init
npm run verifier:set:devnet
node verifier/server.js
npm run test:devnet:browser

This pays a real Devnet entry fee, finalizes the event ledger, obtains the configured verifier's canonical signature, submits submit_verified_run directly from the browser client, and confirms the RunRecord and leaderboard PDAs. It does not prove authoritative gameplay physics; close that security boundary before enabling score-derived mainnet rewards.

3. Mainnet deploy

solana config set --url mainnet-beta
solana balance                                  # deployer must hold enough SOL (program ~0.76 MB)
solana program deploy target/deploy/gkd_chain.so --program-id target/deploy/gkd_chain-keypair.json

Switch Anchor.toml [provider].cluster = "mainnet-beta" and chain_config.js cluster too.

chain_config.js intentionally keeps the mainnet program id empty. Add the audited mainnet id to the GKD_PROGRAM_IDS["mainnet-beta"] entry only after deployment and full PDA initialization. The validated devnet id must never be copied into the mainnet entry.

4. Initialize (admin signs, in order)

  1. initialize_config(creator_wallet, normal_fee_lamports=270000)
  2. initialize_pools() — Game Pool + Charity Pool PDAs
  3. initialize_token() — $420POP mint (authority = PDA)
  4. initialize_record_state()
  5. initialize_leaderboard()
  6. initialize_fee_gov(members, threshold=2, target_usd_micros=100000, pyth_sol_usd)
  7. initialize_season(season_id, mint_cap, score_target, reward_per_run) — per epoch, caps from HUMAN_SEASON_CAPS × 10^9 (season 33 = Chaos cap × 10^9)
  8. set_verifier(<verifier pubkey>) — turns on the on-chain anti-cheat score signature gate
  9. (optional) whitelist_charity(operator, name) per charity

tools/gate_e_submit_run.js already performs steps 1, 4, 5, 7 automatically when submitting a run; the rest are one-time admin calls.

5. Go-live wiring

  • Run the verifier with STRICT_GATE_D=true, REQUIRE_ENTRY_TX=true, ALLOW_BROWSER_COMPAT=false, and ENABLE_MEMO_SUBMIT=false.
  • Keep VERIFIER_SECRET_KEY_B64 in HSM/KMS-backed production secret storage; its pubkey must equal step 8. Never commit or expose the secret.
  • Replace the local JSON ledger with a durable transactional database and run the verifier as a monitored, redundant service.
  • Use a dedicated production RPC with rate limits/failover; do not depend on a public RPC endpoint.
  • chain_config.js: cluster, programId, usePoolProgram=true, showLeaderboard=true.
  • Confirm the browser sends submit_verified_run directly with a self-contained Ed25519 instruction before it. The program tolerates wallet-added ComputeBudget prefixes but never accepts a signature instruction after the submit; keep the legacy memo relay disabled.
  • Confirm entry fee flows into the Pool PDA and the real top-3 leaderboard renders.
  • Transfer program/admin authority to the approved multisig and complete the independent audit before adding the mainnet program id.

Cost note

A ~0.76 MB program is deployed as an upgradeable buffer (~2× rent-exempt). Fund the deployer generously and verify the exact lamports with a deploy dry-run; you can later reclaim/close the buffer if needed.