██╗ ██╗███████╗██╗ ██╗ ██████╗ ██████╗
██║ ██║██╔════╝╚██╗██╔╝██╔═══██╗██╔══██╗
██║ ██║█████╗ ╚███╔╝ ██║ ██║██████╔╝
╚██╗ ██╔╝██╔══╝ ██╔██╗ ██║ ██║██╔══██╗
╚████╔╝ ███████╗██╔╝ ██╗╚██████╔╝██║ ██║
╚═══╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝
A custom Solana validator client written in Zig.
Vexor is an independent Solana validator client written from scratch in Zig. It is not a fork of Agave or Firedancer — it is a ground-up implementation of the Solana consensus and execution protocol.
Currently running on testnet:
- Identity:
3J2jADiEoKMaooCQbkyr9aLnjAb5ApDWfVvKgzyK2fbP - Server: AMD EPYC 9374F (32 cores), 503 GB RAM, 3.6 TB NVMe, Broadcom 10G NICs
- Epoch 933 — actively voting, zero STATE-DIVERGENCE, votes landing on-chain
- 36 leader slots assigned for epoch 934
| Component | Status |
|---|---|
| Gossip / TVU / TPU | ✅ Running |
| Shred assembly (AF_XDP copy-mode) | ✅ Running |
| Transaction replay | ✅ Running |
| Bank hash (SIMD-215 two-step LtHash) | ✅ Correct |
| Native SBPF v0 VM | ✅ Running (no C dependency) |
| Vote submission (TowerSync) | ✅ Landing on-chain |
| Block production (leader slots) | ✅ Implemented |
| VEXstore LSM storage engine | 🔧 In development |
| CPI (cross-program invocation) | 🔧 RPC shadow bridge (interim) |
| Mainnet | 📋 Planned |
┌─────────────────────────────────────────────────────────────────┐
│ VEXOR VALIDATOR │
├──────────────┬──────────────┬─────────────────┬─────────────────┤
│ NETWORK │ CONSENSUS │ EXECUTION │ STORAGE │
│ │ │ │ │
│ AF_XDP │ Tower BFT │ SBPF v0 VM │ AccountsDb │
│ copy-mode │ Fork Choice │ (native Zig) │ (in-memory + │
│ 10G NICs │ Vote Submit │ │ NVMe) │
│ │ │ RPC Shadow BPF │ │
│ Gossip │ Leader Sched│ (CPI fallback) │ VEXstore LSM │
│ TVU / TPU │ Epoch Stakes│ │ (WiscKey-style)│
│ Turbine │ │ ELF Loader │ │
└──────────────┴──────────────┴─────────────────┴─────────────────┘
Vexor includes a complete native Zig implementation of the Solana BPF virtual machine — no Firedancer C library, no external dependencies:
- Full SBPF v0 instruction set: all ALU64/ALU32, load/store, jump, and LDDW instructions
- Correct Solana memory model: four virtual address regions (0x100000000 program, 0x200000000 stack, 0x300000000 heap, 0x400000000 input), each with host-pointer translation and write-protection
- 27 syscalls:
sol_log_,sol_memcpy_,sol_memcmp_,sol_memset_,sol_sha256,sol_keccak256,sol_blake3,sol_create_program_address_,sol_try_find_program_address, and more — all syscall IDs computed asmurmur3_32(name, 0)and verified against Agave - CPI fallback:
sol_invoke_signedreturnsCpiRequired; the executor transparently falls back to an RPC shadow that fetches confirmed account state for that slot
Implements SIMD-215 two-step formula:
step1 = SHA256(parent_hash || sig_count_u64_LE || last_blockhash)
bank_hash = SHA256(step1 || lthash_2048_bytes)
LtHash uses Blake3 XOF → 2048 bytes per account, with element-wise u16 add/subtract for account updates. Matches the network exactly — zero STATE-DIVERGENCE since deployment.
- Legacy backend: in-memory HashMap with NVMe persistence, used in production
- VEXstore: custom WiscKey-inspired LSM engine (2,500+ lines), being integrated as primary backend. Separates keys (index in SSTable) from values (NVMe value log), avoiding write amplification on large account data
AF_XDP copy-mode on enp5s0f0np0 (Broadcom BCM57416, 10G). Zero-copy mode (xsk_umem_register) is not supported by this NIC's bnxt_en driver — copy-mode is the correct configuration. Shred repair runs on enp5s0f1np1 (.155).
The testnet validator runs on dedicated bare metal:
| Component | Spec |
|---|---|
| CPU | AMD EPYC 9374F (32 cores, Zen 4) |
| RAM | 503 GB DDR5 |
| NVMe | 3.6 TB |
| NICs | Dual Broadcom BCM57416 10G (enp5s0f0np0 + enp5s0f1np1) |
| OS | Debian 12, kernel 6.12.74 |
| Compiler | Zig 0.14.0 |
CPU pinning: cores 6–19 for Vexor (14 cores), cores 2–5 for IRQ affinity.
# Standard build (for your local machine)
zig build -Doptimize=ReleaseFast
# Production build (AMD EPYC / znver4)
zig build -Doptimize=ReleaseFast -Dcpu=znver4
# Optional: future Firedancer VM comparison (not required)
zig build -Doptimize=ReleaseFast -Dcpu=znver4 \
-Dfiredancer_src=/path/to/firedancer/src
# Optional build flags
-Dstorage_backend=vexstore # use VEXstore as primary backend
-Dvexstore_shadow=true # shadow writes to VEXstore alongside legacyRequirements: Zig 0.14.0. No other build dependencies.
./vexor-launch.sh testnetKey flags used in production:
--bootstrap --testnet
--identity ****
--vote-account ****
--ledger /mnt/ledger/vexor-testnet
--accounts /mnt/ramdisk/vexor-testnet
--snapshots /mnt/snapshots/vexor-testnet
--public-ip 38.58.183.154
--gossip-port 8001 --tvu-port 8003 --repair-port 8002
--repair-bind-addr 38.58.183.155
--expected-genesis-hash 4uhcVJyU9pJkvQyS88uRDiswHXSCkY3zQawwpjk2NsNY
--known-validator [4 testnet validators]
--entrypoint [3 testnet entrypoints]
--enable-af-xdp --interface enp5s0f0np0
--enable-fec-recovery --enable-io-uring
--limit-ledger-size 50000000
Do not use --xdp-zero-copy — not supported by bnxt_en driver.
Vexor logs a rolling 60-slot TPS window every minute:
[METRICS] slot=397856000 | replay_TPS=4230 tx/s (last 60 slots, 101520 txns) |
net_est=3750 tx/s | lifetime: 2847300 txns across 14230 slots |
votes=28460 blocks=4 bad_shreds=0
- replay_TPS: how fast Vexor's SBPF VM processes transactions (wall-clock)
- net_est: estimated network-wide TPS from avg transactions per slot ÷ 0.4s
- lifetime: cumulative totals since process start
# Watch identity balance drain (5,000 lamports per vote)
solana balance 3J2jADiEoKMaooCQbkyr9aLnjAb5ApDWfVvKgzyK2fbP --url testnet
# Watch Vexor logs
tail -f /home/davidb/vexor_testnet.log | grep -E "VoteSubmitter|METRICS|HASH"| Pattern | Meaning |
|---|---|
[VoteSubmitter] Attempting vote for slot N |
Vote being submitted |
[METRICS] replay_TPS=N |
Rolling TPS report (every 60 slots) |
[HASH-COMPARATOR] MATCHES |
Bank hash matches network |
[RpcShadowBpf] N BPF accounts tracked, N changed |
CPI fallback active for slot |
[BlockProducer] WE ARE LEADER |
Leader slot, producing block |
[STATE-DIVERGENCE] |
❌ Should not appear — means bank hash mismatch |
Near term
- Full CPI (cross-program invocation) in native Zig VM — eliminates RPC shadow dependency
- VEXstore as primary storage backend (flat index elimination complete)
- SIMD-0161 (SBPF v1) instruction set support
- Prometheus
/metricsHTTP endpoint
Medium term
- Mainnet readiness: stake-weighted quality-of-service, stake delegation
- Native secp256k1 recover syscall (currently returns error code 1)
- Alpenglow consensus (SIMD-0236) — faster finality
- QUIC TPU ingress
Long term
- Full hardware zero-copy XDP (requires NIC with
XDP_SETUP_XSK_POOLsupport) - Multi-validator cluster testing
- Jito MEV integration
src/
├── runtime/
│ ├── bank.zig Bank state, LtHash, freeze(), RPC shadow injection
│ ├── replay_stage.zig Shred assembly, TX replay, TPS metrics
│ ├── bootstrap.zig Startup, snapshot load, vote loop
│ ├── vote_state_serde.zig VoteState V1/V2/V3/V4 round-trip serde
│ ├── rpc_shadow_bpf.zig CPI fallback: fetch confirmed BPF state from RPC
│ └── bpf/
│ ├── interpreter.zig Native Zig SBPF v0 VM (virtual address memory model)
│ ├── syscalls.zig 27 syscalls, murmur3_32 dispatch, Zig 0.14 crypto
│ ├── sbpf_executor.zig Serialise accounts → run VM → deserialise mutations
│ └── elf_loader.zig SBPF ELF → combined rodata buffer + entry_pc
├── consensus/
│ ├── tower.zig Tower BFT, lockouts, timely vote credits (SIMD-033)
│ └── fork_choice.zig Heaviest-subtree stake-weighted fork selection
├── storage/
│ ├── accounts.zig AccountsDb, LtHash cache, top_votes, SIMD-0084
│ └── vexstore.zig VEXstore WiscKey LSM engine (in development)
└── crypto/
└── lthash.zig Blake3 XOF → 2048-byte LtHash, u16 element add/sub
Vexor is an independent implementation of the Solana protocol. In studying the protocol, the following open-source projects were invaluable references:
- Firedancer (Jump Trading, Apache-2.0) — virtual machine architecture, memory region layout concepts, syscall dispatch approach
- Agave / solana-rbpf (Solana Labs, MIT) — virtual address constants (
MM_PROG_STARTetc.), calling convention, SBPF v0 specification - SIG (Syndica, MIT) — Zig patterns for Solana protocol implementation
Vexor's code is written from scratch in Zig. All syscall IDs are computed independently via murmur3_32(name, 0). The Solana protocol specification (SIMDs) are the authoritative reference for all consensus-critical behaviour.
Built with ❤️ and Zig. Running on Solana testnet.