Files
dchain/docs/node/multi-server.md
vsecoder 7e7393e4f8 chore: initial commit for v0.0.1
DChain single-node blockchain + React Native messenger client.

Core:
- PBFT consensus with multi-sig validator admission + equivocation slashing
- BadgerDB + schema migration scaffold (CurrentSchemaVersion=0)
- libp2p gossipsub (tx/v1, blocks/v1, relay/v1, version/v1)
- Native Go contracts (username_registry) alongside WASM (wazero)
- WebSocket gateway with topic-based fanout + Ed25519-nonce auth
- Relay mailbox with NaCl envelope encryption (X25519 + Ed25519)
- Prometheus /metrics, per-IP rate limit, body-size cap

Deployment:
- Single-node compose (deploy/single/) with Caddy TLS + optional Prometheus
- 3-node dev compose (docker-compose.yml) with mocked internet topology
- 3-validator prod compose (deploy/prod/) for federation
- Auto-update from Gitea via /api/update-check + systemd timer
- Build-time version injection (ldflags → node --version)
- UI / Swagger toggle flags (DCHAIN_DISABLE_UI, DCHAIN_DISABLE_SWAGGER)

Client (client-app/):
- Expo / React Native / NativeWind
- E2E NaCl encryption, typing indicator, contact requests
- Auto-discovery of canonical contracts, chain_id aware, WS reconnect on node switch

Documentation:
- README.md, CHANGELOG.md, CONTEXT.md
- deploy/single/README.md with 6 operator scenarios
- deploy/UPDATE_STRATEGY.md with 4-layer forward-compat design
- docs/contracts/*.md per contract
2026-04-17 14:16:44 +03:00

292 lines
9.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Деплой на реальные серверы
Руководство по запуску трёх полноценных нод на разных VPS/серверах в интернете.
## Концепция
```
Server A (1.2.3.11) Server B (1.2.3.12) Server C (1.2.3.13)
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ node1 │ │ node2 │ │ node3 │
│ validator │◀────────▶│ validator │◀────────▶│ validator │
│ relay (2000µT) │ │ relay (1500µT) │ │ relay (1000µT) │
│ :4001 :8080 │ │ :4001 :8080 │ │ :4001 :8080 │
└────────┬────────┘ └────────┬────────┘ └────────┬────────┘
│ │ │
└────────────────────────────┴─────────────────────────────┘
libp2p P2P
gossipsub: tx + blocks
streams: PBFT consensus, sync
```
Каждая нода — полноценный **валидатор** (участвует в PBFT-консенсусе) и **relay-провайдер** (хранит и доставляет зашифрованные сообщения).
## Требования
- Ubuntu 22.04 / Debian 12 (или любой Linux)
- Открытый TCP-порт `4001` (P2P) и опционально `8080` (HTTP API)
- Go 1.21+ **только для сборки** (на сервере нужен только бинарник)
## 1. Подготовка ключей
На любой машине (ноутбук / CI):
```bash
# Сгенерировать 3 ключа
./client keygen --out keys/node1.json
./client keygen --out keys/node2.json
./client keygen --out keys/node3.json
# Получить pubkey и peer ID для каждого
./peerid --key keys/node1.json --ip <SERVER_A_IP> --port 4001
./peerid --key keys/node2.json --ip <SERVER_B_IP> --port 4001
./peerid --key keys/node3.json --ip <SERVER_C_IP> --port 4001
```
Вывод `peerid`:
```
pub_key: 26018d40...
peer_id: 12D3KooW...
multiaddr: /ip4/1.2.3.11/tcp/4001/p2p/12D3KooW...
```
Запишите `pub_key` и `peer_id` для каждой ноды — они нужны в конфигурации.
## 2. Сборка бинарника
```bash
git clone https://github.com/your/go-blockchain
cd go-blockchain
CGO_ENABLED=0 GOOS=linux go build -trimpath -o node ./cmd/node
CGO_ENABLED=0 GOOS=linux go build -trimpath -o client ./cmd/client
# Скопировать на серверы
scp node client root@1.2.3.11:/usr/local/bin/
scp node client root@1.2.3.12:/usr/local/bin/
scp node client root@1.2.3.13:/usr/local/bin/
```
## 3. Копирование ключей
```bash
# Каждый сервер получает ТОЛЬКО свой ключ
scp keys/node1.json root@1.2.3.11:/etc/dchain/node.json
scp keys/node2.json root@1.2.3.12:/etc/dchain/node.json
scp keys/node3.json root@1.2.3.13:/etc/dchain/node.json
chmod 600 /etc/dchain/node.json # на каждом сервере
```
## 4. Переменные конфигурации
Подставьте реальные значения из шага 1:
```bash
# Validators — все три pubkey через запятую
VALIDATORS="<NODE1_PUB>,<NODE2_PUB>,<NODE3_PUB>"
# Bootstrap multiaddrs для node2 и node3
NODE1_PEER="/ip4/1.2.3.11/tcp/4001/p2p/<NODE1_PEER_ID>"
NODE2_PEER="/ip4/1.2.3.12/tcp/4001/p2p/<NODE2_PEER_ID>"
```
## 5. Запуск нод
### Server A — node1 (genesis + validator + relay)
```bash
node \
--genesis \
--key /etc/dchain/node.json \
--db /var/lib/dchain/chain \
--mailbox-db /var/lib/dchain/mailbox \
--listen /ip4/0.0.0.0/tcp/4001 \
--announce /ip4/1.2.3.11/tcp/4001 \
--stats-addr :8080 \
--validators "$VALIDATORS" \
--heartbeat=true \
--register-relay \
--relay-fee 2000
```
### Server B — node2 (validator + relay)
```bash
node \
--key /etc/dchain/node.json \
--db /var/lib/dchain/chain \
--mailbox-db /var/lib/dchain/mailbox \
--listen /ip4/0.0.0.0/tcp/4001 \
--announce /ip4/1.2.3.12/tcp/4001 \
--stats-addr :8080 \
--validators "$VALIDATORS" \
--peers "$NODE1_PEER" \
--heartbeat=true \
--register-relay \
--relay-fee 1500
```
### Server C — node3 (validator + relay)
```bash
node \
--key /etc/dchain/node.json \
--db /var/lib/dchain/chain \
--mailbox-db /var/lib/dchain/mailbox \
--listen /ip4/0.0.0.0/tcp/4001 \
--announce /ip4/1.2.3.13/tcp/4001 \
--stats-addr :8080 \
--validators "$VALIDATORS" \
--peers "$NODE1_PEER,$NODE2_PEER" \
--heartbeat=true \
--register-relay \
--relay-fee 1000
```
## 6. systemd unit
Создайте `/etc/systemd/system/dchain.service` на каждом сервере:
```ini
[Unit]
Description=DChain Node
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=dchain
ExecStart=/usr/local/bin/node \
--key /etc/dchain/node.json \
--db /var/lib/dchain/chain \
--mailbox-db /var/lib/dchain/mailbox \
--listen /ip4/0.0.0.0/tcp/4001 \
--announce /ip4/YOUR_PUBLIC_IP/tcp/4001 \
--stats-addr :8080 \
--validators "V1_PUB,V2_PUB,V3_PUB" \
--peers "/ip4/SEED_IP/tcp/4001/p2p/SEED_PEER_ID" \
--heartbeat=true \
--register-relay \
--relay-fee 1000
Restart=on-failure
RestartSec=5s
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
```
```bash
# Применить
sudo systemctl daemon-reload
sudo systemctl enable --now dchain
# Логи
sudo journalctl -u dchain -f
```
## 7. Деплой контрактов
После запуска всех трёх нод:
```bash
# С любой машины имеющей client и ключ node1
export NODE_URL=http://1.2.3.11:8080
export KEY=/etc/dchain/node.json # или локальная копия
# Задеплоить username_registry
CONTRACT_ID=$(client deploy-contract \
--key $KEY \
--wasm contracts/username_registry/username_registry.wasm \
--abi contracts/username_registry/username_registry_abi.json \
--node $NODE_URL | grep contract_id | awk '{print $2}')
echo "username_registry: $CONTRACT_ID"
# Залинковать governance на всех трёх нодах
for NODE in http://1.2.3.11:8080 http://1.2.3.12:8080 http://1.2.3.13:8080; do
curl -sX POST "$NODE/api/governance/link" \
-H "Content-Type: application/json" \
-d "{\"governance\":\"$GOV_ID\"}"
done
```
## 8. Как работает сеть
### Bootstrap и discovery
```
node2 старт:
1. --peers → connectWithRetry("/ip4/1.2.3.11/tcp/4001/p2p/...")
Подключается к node1 (бесконечный retry с backoff 1→30s)
2. При connect → syncOnConnect()
Запрашивает все блоки которых нет у node2
3. Kademlia DHT bootstrap (через node1)
DHT узнаёт о node3 → DiscoverPeers() подключается
4. mDNS (только LAN/Docker) — игнорируется в интернете
5. connectWithRetry keep-alive: каждые 30s проверяет связь,
автоматически переподключает при обрыве
```
### Консенсус
PBFT 3-of-3, fault tolerance f=1:
- Для коммита блока нужны подписи **2 из 3** валидаторов
- Если одна нода упала → сеть продолжает работать
- Если упали две → сеть ждёт (не производит блоки)
### --announce и адреса
Без `--announce` libp2p рекламирует **все** адреса интерфейсов:
- `0.0.0.0` → раскрывается в loopback и внутренние адреса
- Другие ноды получают `127.0.0.1:4001` → не могут подключиться
С `--announce /ip4/1.2.3.11/tcp/4001`:
- Единственный рекламируемый адрес — публичный IP сервера
- `AddrStrings()` возвращает только этот адрес
- DHT propagates этот адрес другим нодам в сети
## 9. Firewall
```bash
# UFW
ufw allow 4001/tcp # P2P — обязательно
ufw allow 8080/tcp # HTTP API — опционально (для Explorer, деплоя контрактов)
# iptables
iptables -A INPUT -p tcp --dport 4001 -j ACCEPT
iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
```
## 10. Добавление новой ноды в сеть
Новый участник (не валидатор, только синхронизация и relay):
```bash
node \
--key /etc/dchain/node.json \
--db /var/lib/dchain/chain \
--mailbox-db /var/lib/dchain/mailbox \
--listen /ip4/0.0.0.0/tcp/4001 \
--announce /ip4/YOUR_IP/tcp/4001 \
--stats-addr :8080 \
--validators "$VALIDATORS" \
--peers "$NODE1_PEER" \
--heartbeat=false \
--register-relay \
--relay-fee 500
```
Нода автоматически:
1. Подключится к node1 через `--peers`
2. Синхронизирует всю историю блоков
3. Через DHT найдёт node2 и node3
4. Начнёт получать и пересылать relay-сообщения
Чтобы сделать её валидатором — нужна `ADD_VALIDATOR` транзакция от существующего валидатора.