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

View File

@@ -0,0 +1,129 @@
name: dchain-single
# ══════════════════════════════════════════════════════════════════════════
# Single-node DChain deployment.
#
# One validator (or observer) + Caddy TLS edge + optional
# Prometheus/Grafana. Intended for:
# - Personal nodes: operator runs their own, optionally private.
# - Tail of a larger network: joins via --join, participates / observes.
# - First node of a brand-new network: starts with --genesis.
#
# Quick start:
# cp node.env.example node.env # edit DOMAIN / API_TOKEN / JOIN
# docker compose up -d # node + Caddy
# docker compose --profile monitor up -d
#
# For a multi-validator cluster see deploy/prod/ (3-of-3 PBFT setup).
# ══════════════════════════════════════════════════════════════════════════
networks:
dchain:
name: dchain_single
driver: bridge
volumes:
node_data:
caddy_data:
caddy_config:
prom_data:
grafana_data:
services:
# ── The node ──────────────────────────────────────────────────────────
# One process does everything: consensus (if validator), relay, HTTP,
# WebSocket, metrics. Three knobs are worth knowing before first boot:
#
# 1. DCHAIN_GENESIS=true → creates block 0 with THIS node's key as sole
# validator. Use only once, on the very first node of a fresh chain.
# Drop the flag on subsequent restarts (no-op but noisy).
# 2. DCHAIN_JOIN=http://...,http://... → fetch /api/network-info from
# the listed seeds, auto-populate --peers / --validators, sync chain.
# Use this when joining an existing network instead of --genesis.
# 3. DCHAIN_API_TOKEN=... → if set, gates POST /api/tx (and WS submit).
# With DCHAIN_API_PRIVATE=true, gates reads too. Empty = public.
node:
build:
context: ../..
dockerfile: deploy/prod/Dockerfile.slim
container_name: dchain_node
restart: unless-stopped
env_file: ./node.env
networks: [dchain]
volumes:
- node_data:/data
- ./keys/node.json:/keys/node.json:ro
# 4001 → libp2p P2P (MUST be publicly routable for federation)
# 8080 → HTTP + WebSocket, only exposed internally to Caddy by default
ports:
- "4001:4001"
expose:
- "8080"
cap_drop: [ALL]
read_only: true
tmpfs: [/tmp]
security_opt: [no-new-privileges:true]
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8080/api/netstats >/dev/null || exit 1"]
interval: 10s
timeout: 3s
retries: 6
start_period: 15s
command:
- "--db=/data/chain"
- "--mailbox-db=/data/mailbox"
- "--key=/keys/node.json"
- "--relay-key=/data/relay.json"
- "--listen=/ip4/0.0.0.0/tcp/4001"
- "--stats-addr=:8080"
# All other config comes via DCHAIN_* env vars from node.env.
# ── TLS edge ──────────────────────────────────────────────────────────
caddy:
image: caddy:2.8-alpine
container_name: dchain_caddy
restart: unless-stopped
networks: [dchain]
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
environment:
DOMAIN: ${DOMAIN:-localhost}
ACME_EMAIL: ${ACME_EMAIL:-admin@example.com}
depends_on:
node: { condition: service_healthy }
# ── Observability (opt-in) ────────────────────────────────────────────
prometheus:
profiles: [monitor]
image: prom/prometheus:v2.53.0
container_name: dchain_prometheus
restart: unless-stopped
networks: [dchain]
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prom_data:/prometheus
command:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--storage.tsdb.retention.time=30d"
grafana:
profiles: [monitor]
image: grafana/grafana:11.1.0
container_name: dchain_grafana
restart: unless-stopped
networks: [dchain]
ports:
- "3000:3000"
depends_on: [prometheus]
environment:
GF_SECURITY_ADMIN_USER: admin
GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_ADMIN_PW:-change-me}
GF_USERS_ALLOW_SIGN_UP: "false"
volumes:
- grafana_data:/var/lib/grafana