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
This commit is contained in:
vsecoder
2026-04-17 14:16:44 +03:00
commit 7e7393e4f8
196 changed files with 55947 additions and 0 deletions

270
docker-compose.yml Normal file
View File

@@ -0,0 +1,270 @@
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