docs: add rpc/dlob/candles notes
This commit is contained in:
284
doc/solana-rpc-geyser-setup.md
Normal file
284
doc/solana-rpc-geyser-setup.md
Normal file
@@ -0,0 +1,284 @@
|
||||
# Bare metal: Solana RPC (non‑voting) + Geyser/“Yellowstone” gRPC (Ubuntu 24.04)
|
||||
|
||||
Cel: postawić **jedną maszynę** jako **źródło danych on‑chain**:
|
||||
- Solana `validator` w trybie **non‑voting** z **RPC + WS** (tylko prywatnie),
|
||||
- **Geyser gRPC** (“Yellowstone”) jako stabilny, skalowalny feed account/tx/slot,
|
||||
- serwisy tradingowe (DLOB/boty/DB/UI) działają **osobno** na VPS/k3s.
|
||||
|
||||
Ten dokument jest runbookiem. Nie zawiera sekretów.
|
||||
|
||||
---
|
||||
|
||||
## Powiązane dokumenty (DLOB + metryki + koszty)
|
||||
|
||||
Żeby spiąć “RPC/Geyser → dane → metryki → UI”, zobacz też:
|
||||
|
||||
- Mapa dokumentów o RPC/DLOB/metrykach: `doc/solana-rpc.md`
|
||||
- DLOB (co działa w k3s, jakie tabele, skąd dane): `doc/dlob-services.md`
|
||||
- DLOB basics (L1/L2/L3, pojęcia): `doc/dlob-basics.md`
|
||||
- Ingest ticków / candles / źródła danych: `doc/workflow-api-ingest.md`
|
||||
- Readiness do live tradingu (w tym plan pod własny RPC + streaming): `doc/trading-readiness.md`
|
||||
- Czy da się bez własnego RPC / bez RPC w ogóle (mapowanie źródeł danych): `doc/drift-data-bez-solana-rpc.md`
|
||||
- Kanoniczna architektura “własny RPC + własny DLOB” (co skąd bierzemy): `doc/rpc-dlob-kanoniczna-architektura.md`
|
||||
- Koszty kontraktu: API compute/monitor (backend liczy, UI tylko rysuje): `doc/contract-cost-api.md`
|
||||
- Kanoniczny payload eventów bota pod koszty/PnL (żeby agregacje działały): `doc/bot-events-cost-payload.md`
|
||||
|
||||
## 0) Założenia
|
||||
|
||||
- OS: **Ubuntu 24.04**
|
||||
- Sprzęt: **Ryzen 9 9950X, 192GB RAM, 2× Gen5 NVMe, 1Gbps**
|
||||
- Rola: **RPC node bez voting** (brak vote account)
|
||||
- Prywatny dostęp: **WireGuard** między bare metal a k3s/VPS
|
||||
|
||||
---
|
||||
|
||||
## 1) Dlaczego RPC+WS i gRPC jednocześnie
|
||||
|
||||
- **RPC/WS** (HTTP + WebSocket) zostaje jako:
|
||||
- wysyłka transakcji (place/cancel/close),
|
||||
- odczyty ad‑hoc i fallback.
|
||||
- **Geyser/Yellowstone gRPC** jest preferowany jako:
|
||||
- stabilny stream updates (account/slot/tx) dla DLOB/indexerów,
|
||||
- mniejsze “rwanie” niż WS przy większej skali.
|
||||
|
||||
W praktyce: data plane = gRPC, execution plane = RPC.
|
||||
|
||||
---
|
||||
|
||||
## 2) Podział dysków (must‑have)
|
||||
|
||||
Rekomendacja (żeby uniknąć I/O contention):
|
||||
- NVMe #1: ledger / accounts
|
||||
- mount: `/solana/ledger`
|
||||
- NVMe #2: snapshots / logs / plugin state
|
||||
- mount: `/solana/snapshots`
|
||||
- ewentualnie: `/var/lib/yellowstone`
|
||||
|
||||
---
|
||||
|
||||
## 3) Porty (proponowane)
|
||||
|
||||
Publicznie:
|
||||
- `22/tcp` (SSH) – tylko z Twoich IP (allowlist)
|
||||
|
||||
Tylko po WireGuard (private):
|
||||
- `8899/tcp` RPC HTTP
|
||||
- `8900/tcp` RPC WS
|
||||
- `10000/tcp` Geyser gRPC (Yellowstone)
|
||||
|
||||
Uwaga: dokładne porty Solany (gossip/TPU) są inne i zależą od flag; one zwykle muszą być publicznie osiągalne do sieci Solany, ale **RPC ma być private**.
|
||||
|
||||
---
|
||||
|
||||
## 4) WireGuard (skeleton)
|
||||
|
||||
Założenie: bare metal = `wg0 = 10.8.0.1`, k3s/VPS = `wg0 = 10.8.0.2`.
|
||||
|
||||
### 4.1 Bare metal: `/etc/wireguard/wg0.conf`
|
||||
|
||||
```ini
|
||||
[Interface]
|
||||
Address = 10.8.0.1/24
|
||||
ListenPort = 51820
|
||||
PrivateKey = <BARE_METAL_PRIVATE_KEY>
|
||||
|
||||
# opcjonalnie: NAT dla ruchu wychodzącego
|
||||
# PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
|
||||
# PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
|
||||
|
||||
[Peer]
|
||||
PublicKey = <K3S_PUBLIC_KEY>
|
||||
AllowedIPs = 10.8.0.2/32
|
||||
```
|
||||
|
||||
### 4.2 VPS/k3s: `/etc/wireguard/wg0.conf`
|
||||
|
||||
```ini
|
||||
[Interface]
|
||||
Address = 10.8.0.2/24
|
||||
PrivateKey = <K3S_PRIVATE_KEY>
|
||||
|
||||
[Peer]
|
||||
PublicKey = <BARE_METAL_PUBLIC_KEY>
|
||||
Endpoint = <BARE_METAL_PUBLIC_IP>:51820
|
||||
AllowedIPs = 10.8.0.1/32
|
||||
PersistentKeepalive = 25
|
||||
```
|
||||
|
||||
Start:
|
||||
|
||||
```bash
|
||||
sudo systemctl enable --now wg-quick@wg0
|
||||
```
|
||||
|
||||
Test:
|
||||
|
||||
```bash
|
||||
ping -c 2 10.8.0.1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5) Firewall: zasada “RPC i gRPC tylko private”
|
||||
|
||||
Wariant z `ufw` (przykład, dopasuj do swojego środowiska):
|
||||
|
||||
```bash
|
||||
sudo ufw default deny incoming
|
||||
sudo ufw default allow outgoing
|
||||
|
||||
# SSH – najlepiej allowlist Twoje IP
|
||||
sudo ufw allow 22/tcp
|
||||
|
||||
# WireGuard
|
||||
sudo ufw allow 51820/udp
|
||||
|
||||
# RPC/WS/gRPC tylko na interfejsie wg0 (ufw ma ograniczone wsparcie; alternatywnie nftables)
|
||||
# Minimalnie: nie otwieraj 8899/8900/10000 na publicznym NIC.
|
||||
|
||||
sudo ufw enable
|
||||
sudo ufw status verbose
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6) Instalacja i uruchomienie Solany (non‑voting)
|
||||
|
||||
### 6.1 Zasada bezpieczeństwa
|
||||
- identity key i konfiguracja tylko na serwerze,
|
||||
- nie commituj tego do gita,
|
||||
- RPC ma być “private RPC”.
|
||||
|
||||
### 6.2 Flagi mogą się zmieniać
|
||||
Solana bywa zmienna w detalach CLI. Zawsze weryfikuj:
|
||||
|
||||
```bash
|
||||
solana-validator --help | less
|
||||
```
|
||||
|
||||
### 6.3 Minimalny szkic uruchomienia (do uzupełnienia)
|
||||
|
||||
Poniżej jest “kształt” – nie traktuj jako jedyny prawdziwy set flag:
|
||||
|
||||
```bash
|
||||
solana-validator \
|
||||
--identity /etc/solana/identity.json \
|
||||
--ledger /solana/ledger \
|
||||
--snapshots /solana/snapshots \
|
||||
--rpc-port 8899 \
|
||||
--rpc-bind-address 10.8.0.1 \
|
||||
--private-rpc \
|
||||
--ws-port 8900 \
|
||||
--dynamic-port-range 8000-8020 \
|
||||
--no-voting \
|
||||
--entrypoint <ENTRYPOINT_1> \
|
||||
--entrypoint <ENTRYPOINT_2> \
|
||||
--entrypoint <ENTRYPOINT_3> \
|
||||
--expected-genesis-hash <GENESIS_HASH> \
|
||||
--wal-recovery-mode skip_any_corrupted_record
|
||||
```
|
||||
|
||||
Uwagi:
|
||||
- `--rpc-bind-address` ustaw na IP WireGuard (private).
|
||||
- `--no-voting` = non‑voting.
|
||||
- `--dynamic-port-range` i reszta portów zależą od Twojej polityki sieciowej.
|
||||
|
||||
### 6.4 systemd (skeleton)
|
||||
|
||||
Plik: `/etc/systemd/system/solana-validator.service`
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Solana Validator (non-voting, private RPC)
|
||||
After=network-online.target wg-quick@wg0.service
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
User=solana
|
||||
Group=solana
|
||||
LimitNOFILE=1048576
|
||||
ExecStart=/usr/local/bin/solana-validator <ARGS...>
|
||||
Restart=always
|
||||
RestartSec=3
|
||||
TimeoutStopSec=120
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7) Geyser / “Yellowstone” gRPC
|
||||
|
||||
### 7.1 Co to jest
|
||||
Geyser to plugin, który “wypycha” stream danych z runtime’u walidatora.
|
||||
Yellowstone gRPC to popularny stack, który wystawia ten stream przez gRPC.
|
||||
|
||||
### 7.2 Model wdrożenia (recommended)
|
||||
- plugin jest skonfigurowany przy starcie `solana-validator` (`--geyser-plugin-config <path>`),
|
||||
- gRPC endpoint nasłuchuje na `10.8.0.1:10000` (private),
|
||||
- klienci (k3s) subskrybują gRPC.
|
||||
|
||||
### 7.3 Konfiguracja pluginu (placeholder)
|
||||
Dokładny format config zależy od wybranego pluginu/wersji.
|
||||
Trzymaj config jako plik na serwerze, np. `/etc/solana/geyser-grpc.json`.
|
||||
|
||||
Wymagania, które chcemy mieć niezależnie od implementacji:
|
||||
- bind na interfejsie WireGuard (`10.8.0.1`),
|
||||
- opcjonalny auth/token dla klientów,
|
||||
- limit/allowlist klientów,
|
||||
- logi do journald + limitowanie.
|
||||
|
||||
Test (z VPS/k3s po WireGuard):
|
||||
- port open: `nc -vz 10.8.0.1 10000` (albo `grpcurl` jeśli masz),
|
||||
- stream slotów/health (zależy od klienta).
|
||||
|
||||
---
|
||||
|
||||
## 8) Integracja z naszym stackiem `trade`
|
||||
|
||||
### 8.1 Co zmieniamy w k3s
|
||||
|
||||
Aktualizujemy secreta z endpointami RPC/WS dla `dlob-publisher` i executora:
|
||||
- `ENDPOINT=http://10.8.0.1:8899`
|
||||
- `WS_ENDPOINT=ws://10.8.0.1:8900`
|
||||
|
||||
Docelowo dodamy również:
|
||||
- `GEYSER_GRPC_URL=http://10.8.0.1:10000` (lub `grpc://...`) do collectorów.
|
||||
|
||||
### 8.2 Fallback
|
||||
Zostawiamy fallback RPC endpoint (np. publiczny provider) dla:
|
||||
- awarii bare-metala,
|
||||
- bootstrapu,
|
||||
- sanity check.
|
||||
|
||||
Executor ma zawsze mieć tryb degradacji:
|
||||
- Vast down → `observe/off`,
|
||||
- feed down → `panic` lub `off` zależnie od ryzyka.
|
||||
|
||||
---
|
||||
|
||||
## 9) Operacje i monitoring (must‑have)
|
||||
|
||||
Mierz/alertuj:
|
||||
- slot lag / “behind”,
|
||||
- iowait + saturacja NVMe,
|
||||
- disk fill (`ledger` rośnie),
|
||||
- restart loop serwisów,
|
||||
- liczba klientów gRPC / błędy streamu,
|
||||
- RPC latencja / error rate.
|
||||
|
||||
Minimalne narzędzia:
|
||||
- `node_exporter` + Prometheus/Grafana,
|
||||
- logrotate/journald limity,
|
||||
- `smartctl`/`nvme smart-log` dla NVMe.
|
||||
|
||||
---
|
||||
|
||||
## 10) Gotowość do startu (checklista)
|
||||
|
||||
- [ ] WireGuard działa (ping wg IP).
|
||||
- [ ] RPC/WS/gRPC są dostępne tylko po WG.
|
||||
- [ ] `solana-validator` trzyma sync, nie robi OOM, I/O stabilne.
|
||||
- [ ] Geyser gRPC stream stabilny (brak częstych reconnect).
|
||||
- [ ] `dlob-publisher` działa na nowych endpointach bez “No ws data … resubscribing”.
|
||||
Reference in New Issue
Block a user