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
271 lines
11 KiB
YAML
271 lines
11 KiB
YAML
name: dchain
|
||
|
||
# ═══════════════════════════════════════════════════════════════════════════
|
||
# DChain — три полноценных ноды, симуляция работы в интернете
|
||
#
|
||
# Топология сети:
|
||
#
|
||
# ┌──────────────────────────────────────────────────────────────────────┐
|
||
# │ internet (172.30.0.0/24) │
|
||
# │ │
|
||
# │ node1 ── 172.30.0.11 validator + relay :4001 :8081 │
|
||
# │ node2 ── 172.30.0.12 validator + relay :4002 :8082 │
|
||
# │ node3 ── 172.30.0.13 validator + relay :4003 :8083 │
|
||
# │ │
|
||
# └──────────────────────────────────────────────────────────────────────┘
|
||
# │ │ │
|
||
# dc1 (172.31.1.0/24) dc2 (172.31.2.0/24) dc3 (172.31.3.0/24)
|
||
# internal — только internal — только internal — только
|
||
# для node1 для node2 для node3
|
||
#
|
||
# Правила:
|
||
# • Ноды общаются только через backbone «internet» по фиксированным IP.
|
||
# • Каждая dc-сеть изолирована (internal: true) — имитирует приватную
|
||
# LAN датацентра, недоступную для других нод напрямую.
|
||
# • P2P bootstrap — через IP backbone-сети, как в реальном интернете.
|
||
# • Все три ноды — полноценные валидаторы и relay-провайдеры.
|
||
# PBFT 3-of-3, fault tolerance f=1: сеть работает при падении одной.
|
||
#
|
||
# Идентичности (ключи вшиты в образ из testdata/):
|
||
# node1 pub: 26018d40e40514f38f799eee403f62da98cb5ac936e29049629f1873cbcb4070
|
||
# pid: 12D3KooWCNj2ugnjqoJFPdRuhGZHvGTbEiTMmHDimfsxmGYcjGo9
|
||
#
|
||
# node2 pub: bf3628d1a10fcf5a90d2cb31f387c8d1f2dac6a2c54c736c27d5ea04af9696a2
|
||
# pid: 12D3KooWNgmwMbaw5K7vDbGxb9zvcF8gur5GWXGoFEVfKzSNc9bf
|
||
#
|
||
# node3 pub: 6316e7427654cd2e300033c5e13b6182d595ec2c63bc8396b74183296112510c
|
||
# pid: 12D3KooWGVAnaq1EgH1dN49fQWvw1z71R5bZj7UmPkUeQkW4783V
|
||
#
|
||
# Быстрый старт:
|
||
# docker compose up --build -d
|
||
# docker compose --profile deploy run --rm deploy
|
||
# open http://localhost:8081
|
||
#
|
||
# Сброс данных:
|
||
# docker compose down -v && docker compose up --build -d
|
||
# ═══════════════════════════════════════════════════════════════════════════
|
||
|
||
# ── Сети ─────────────────────────────────────────────────────────────────────
|
||
|
||
networks:
|
||
|
||
# Общий backbone «интернет» — единственный путь между нодами
|
||
internet:
|
||
name: dchain_internet
|
||
driver: bridge
|
||
ipam:
|
||
driver: default
|
||
config:
|
||
- subnet: 172.30.0.0/24
|
||
gateway: 172.30.0.1
|
||
|
||
# Изолированные «датацентры» — нет маршрута до других нод и хоста
|
||
dc1:
|
||
name: dchain_dc1
|
||
driver: bridge
|
||
internal: true
|
||
ipam:
|
||
config:
|
||
- subnet: 172.31.1.0/24
|
||
|
||
dc2:
|
||
name: dchain_dc2
|
||
driver: bridge
|
||
internal: true
|
||
ipam:
|
||
config:
|
||
- subnet: 172.31.2.0/24
|
||
|
||
dc3:
|
||
name: dchain_dc3
|
||
driver: bridge
|
||
internal: true
|
||
ipam:
|
||
config:
|
||
- subnet: 172.31.3.0/24
|
||
|
||
# ── Тома ─────────────────────────────────────────────────────────────────────
|
||
|
||
volumes:
|
||
node1_data:
|
||
node2_data:
|
||
node3_data:
|
||
|
||
# ── Общие якоря ──────────────────────────────────────────────────────────────
|
||
|
||
x-node-base: &node-base
|
||
build: .
|
||
restart: unless-stopped
|
||
|
||
# Все три ноды — валидаторы (PBFT 3-of-3)
|
||
x-validators: &validators
|
||
VALIDATORS: "26018d40e40514f38f799eee403f62da98cb5ac936e29049629f1873cbcb4070,bf3628d1a10fcf5a90d2cb31f387c8d1f2dac6a2c54c736c27d5ea04af9696a2,6316e7427654cd2e300033c5e13b6182d595ec2c63bc8396b74183296112510c"
|
||
|
||
x-healthcheck: &healthcheck
|
||
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8080/api/netstats | grep -q total_blocks"]
|
||
interval: 5s
|
||
timeout: 3s
|
||
retries: 24
|
||
start_period: 8s
|
||
|
||
# ════════════════════════════════════════════════════════════════════════════
|
||
services:
|
||
|
||
# ── node1 — Лондон / server-1.dchain.local ──────────────────────────────
|
||
# Роль : genesis · validator · relay provider
|
||
# Backbone: 172.30.0.11 DC LAN: 172.31.1.10
|
||
# Relay fee: 2000 µT
|
||
# ────────────────────────────────────────────────────────────────────────
|
||
node1:
|
||
<<: *node-base
|
||
container_name: node1
|
||
hostname: server-1.dchain.local
|
||
networks:
|
||
internet:
|
||
ipv4_address: 172.30.0.11
|
||
dc1:
|
||
ipv4_address: 172.31.1.10
|
||
ports:
|
||
- "4001:4001" # libp2p P2P
|
||
- "8081:8080" # HTTP Explorer / REST API
|
||
volumes:
|
||
- node1_data:/data
|
||
environment:
|
||
<<: *validators
|
||
entrypoint:
|
||
- /bin/sh
|
||
- -c
|
||
- |
|
||
exec /usr/local/bin/node \
|
||
--genesis \
|
||
--db /data/chain \
|
||
--mailbox-db /data/mailbox \
|
||
--key /keys/node1.json \
|
||
--relay-key /data/relay.json \
|
||
--listen /ip4/0.0.0.0/tcp/4001 \
|
||
--announce /ip4/172.30.0.11/tcp/4001 \
|
||
--stats-addr :8080 \
|
||
--validators "$$VALIDATORS" \
|
||
--heartbeat=true \
|
||
--register-relay \
|
||
--relay-fee 2000
|
||
healthcheck: *healthcheck
|
||
|
||
# ── node2 — Нью-Йорк / server-2.dchain.local ────────────────────────────
|
||
# Роль : validator · relay provider
|
||
# Backbone: 172.30.0.12 DC LAN: 172.31.2.10
|
||
# Bootstrap → node1 (172.30.0.11) по backbone IP
|
||
# Relay fee: 1500 µT
|
||
# ────────────────────────────────────────────────────────────────────────
|
||
node2:
|
||
<<: *node-base
|
||
container_name: node2
|
||
hostname: server-2.dchain.local
|
||
networks:
|
||
internet:
|
||
ipv4_address: 172.30.0.12
|
||
dc2:
|
||
ipv4_address: 172.31.2.10
|
||
ports:
|
||
- "4002:4001"
|
||
- "8082:8080"
|
||
volumes:
|
||
- node2_data:/data
|
||
environment:
|
||
<<: *validators
|
||
NODE1_PEER: "/ip4/172.30.0.11/tcp/4001/p2p/12D3KooWCNj2ugnjqoJFPdRuhGZHvGTbEiTMmHDimfsxmGYcjGo9"
|
||
entrypoint:
|
||
- /bin/sh
|
||
- -c
|
||
- |
|
||
exec /usr/local/bin/node \
|
||
--db /data/chain \
|
||
--mailbox-db /data/mailbox \
|
||
--key /keys/node2.json \
|
||
--relay-key /data/relay.json \
|
||
--listen /ip4/0.0.0.0/tcp/4001 \
|
||
--announce /ip4/172.30.0.12/tcp/4001 \
|
||
--stats-addr :8080 \
|
||
--validators "$$VALIDATORS" \
|
||
--peers "$$NODE1_PEER" \
|
||
--heartbeat=true \
|
||
--register-relay \
|
||
--relay-fee 1500
|
||
depends_on:
|
||
node1:
|
||
condition: service_healthy
|
||
healthcheck: *healthcheck
|
||
|
||
# ── node3 — Токио / server-3.dchain.local ───────────────────────────────
|
||
# Роль : validator · relay provider
|
||
# Backbone: 172.30.0.13 DC LAN: 172.31.3.10
|
||
# Bootstrap → node1 + node2 по backbone IP
|
||
# Relay fee: 1000 µT (самый дешёвый)
|
||
# ────────────────────────────────────────────────────────────────────────
|
||
node3:
|
||
<<: *node-base
|
||
container_name: node3
|
||
hostname: server-3.dchain.local
|
||
networks:
|
||
internet:
|
||
ipv4_address: 172.30.0.13
|
||
dc3:
|
||
ipv4_address: 172.31.3.10
|
||
ports:
|
||
- "4003:4001"
|
||
- "8083:8080"
|
||
volumes:
|
||
- node3_data:/data
|
||
environment:
|
||
<<: *validators
|
||
NODE1_PEER: "/ip4/172.30.0.11/tcp/4001/p2p/12D3KooWCNj2ugnjqoJFPdRuhGZHvGTbEiTMmHDimfsxmGYcjGo9"
|
||
NODE2_PEER: "/ip4/172.30.0.12/tcp/4001/p2p/12D3KooWNgmwMbaw5K7vDbGxb9zvcF8gur5GWXGoFEVfKzSNc9bf"
|
||
entrypoint:
|
||
- /bin/sh
|
||
- -c
|
||
- |
|
||
exec /usr/local/bin/node \
|
||
--db /data/chain \
|
||
--mailbox-db /data/mailbox \
|
||
--key /keys/node3.json \
|
||
--relay-key /data/relay.json \
|
||
--listen /ip4/0.0.0.0/tcp/4001 \
|
||
--announce /ip4/172.30.0.13/tcp/4001 \
|
||
--stats-addr :8080 \
|
||
--validators "$$VALIDATORS" \
|
||
--peers "$$NODE1_PEER,$$NODE2_PEER" \
|
||
--heartbeat=true \
|
||
--register-relay \
|
||
--relay-fee 1000
|
||
depends_on:
|
||
node1:
|
||
condition: service_healthy
|
||
healthcheck: *healthcheck
|
||
|
||
# ── deploy — одноразовый деплой 4 production-контрактов ─────────────────
|
||
# Запуск: docker compose --profile deploy run --rm deploy
|
||
# Ждёт готовности всех трёх нод, затем деплоит контракты.
|
||
# ────────────────────────────────────────────────────────────────────────
|
||
deploy:
|
||
profiles: [deploy]
|
||
build: .
|
||
container_name: deploy
|
||
restart: "no"
|
||
networks:
|
||
- internet
|
||
volumes:
|
||
- ./scripts/deploy_contracts.sh:/scripts/deploy_contracts.sh:ro
|
||
entrypoint: ["/bin/sh", "/scripts/deploy_contracts.sh"]
|
||
environment:
|
||
# Backbone IP-адреса — без DNS, как будто это разные серверы в интернете
|
||
NODE1_URL: "http://172.30.0.11:8080"
|
||
NODE2_URL: "http://172.30.0.12:8080"
|
||
NODE3_URL: "http://172.30.0.13:8080"
|
||
depends_on:
|
||
node1:
|
||
condition: service_healthy
|
||
node2:
|
||
condition: service_healthy
|
||
node3:
|
||
condition: service_healthy
|