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:
207
docs/architecture.md
Normal file
207
docs/architecture.md
Normal file
@@ -0,0 +1,207 @@
|
||||
# Архитектура DChain
|
||||
|
||||
## Обзор
|
||||
|
||||
DChain — это L1-блокчейн для децентрализованного мессенджера. Архитектура разделена на четыре слоя:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ L3 Application — messaging, usernames, auctions, escrow │
|
||||
│ (Smart contracts: username_registry, governance, auction, │
|
||||
│ escrow; deployed on-chain via DEPLOY_CONTRACT) │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ L2 Transport — relay mailbox, E2E NaCl encryption │
|
||||
│ (relay/, mailbox, GossipSub envelopes, RELAY_PROOF tx) │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ L1 Chain — PBFT consensus, WASM VM, BadgerDB │
|
||||
│ (blockchain/, consensus/, vm/, identity/) │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ L0 Network — libp2p, GossipSub, DHT, mDNS │
|
||||
│ (p2p/) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Консенсус (PBFT)
|
||||
|
||||
**Алгоритм:** Practical Byzantine Fault Tolerance, кворум 2/3.
|
||||
|
||||
**Фазы:**
|
||||
```
|
||||
Leader Validator-2 Validator-3
|
||||
│── PRE-PREPARE ──▶│ │
|
||||
│── PRE-PREPARE ────────────────────────▶ │
|
||||
│◀─ PREPARE ───────│ │
|
||||
│◀─ PREPARE ────────────────────────────── │
|
||||
│── COMMIT ────────▶│ │
|
||||
│── COMMIT ──────────────────────────────▶ │
|
||||
│◀─ COMMIT ────────│ │
|
||||
│◀─ COMMIT ────────────────────────────── │
|
||||
AddBlock()
|
||||
```
|
||||
|
||||
**Свойства:**
|
||||
- Safety при ≤ f Byzantine нодах где N ≥ 3f+1
|
||||
- Текущий testnet: N=2 валидатора, f=0 (узел node3 — relay-only observer)
|
||||
- View-change при недоступном лидере: таймаут 10 секунд
|
||||
|
||||
**Блок-производство:**
|
||||
- Fast ticker (500 ms) — при наличии транзакций в mempool
|
||||
- Idle ticker (5 s) — пустые блоки для heartbeat и синхронизации
|
||||
|
||||
**Ключевые файлы:**
|
||||
```
|
||||
consensus/engine.go — PBFT engine
|
||||
consensus/msg.go — ConsensusMsg типы (PRE-PREPARE, PREPARE, COMMIT, VIEW-CHANGE)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Хранилище (BadgerDB)
|
||||
|
||||
Весь state хранится в BadgerDB (LSM-дерево, pure Go).
|
||||
|
||||
**Пространства ключей:**
|
||||
|
||||
| Префикс | Тип | Описание |
|
||||
|---------|-----|---------|
|
||||
| `block:<index_20d>` | JSON | Блоки по индексу |
|
||||
| `height` | uint64 JSON | Текущая высота |
|
||||
| `balance:<pubkey>` | uint64 JSON | Балансы токенов |
|
||||
| `id:<pubkey>` | JSON | Identity (RegisterKey payload) |
|
||||
| `validator:<pubkey>` | presence | Активный сет валидаторов |
|
||||
| `relay:<pubkey>` | JSON | Зарегистрированные relay-ноды |
|
||||
| `contract:<id>` | JSON | ContractRecord (метаданные + WASM) |
|
||||
| `cstate:<id>:<key>` | raw bytes | Состояние контракта |
|
||||
| `clog:<id>:<height_20d>:<seq_05d>` | JSON | Логи контракта |
|
||||
| `rep:<pubkey>` | JSON | Репутация (blocks, relays, slashes) |
|
||||
| `contact_in:<to>:<from>` | JSON | Входящие contact requests |
|
||||
| `mail:<x25519>:<ts>:<id>` | JSON | Relay mailbox (TTL 7 дней) |
|
||||
|
||||
**Две отдельные БД:**
|
||||
- `--db ./chaindata` — chain state (consensus state machine)
|
||||
- `--mailbox-db ./mailboxdata` — relay mailbox (отдельная изоляция)
|
||||
|
||||
---
|
||||
|
||||
## P2P сеть (libp2p)
|
||||
|
||||
**Компоненты:**
|
||||
- **Transport:** TCP `/ip4/0.0.0.0/tcp/4001`
|
||||
- **Identity:** Ed25519 peer key (вывод из node identity)
|
||||
- **Discovery:** mDNS (локалка) + Kademlia DHT (WAN)
|
||||
- **Pub/Sub:** GossipSub с тремя топиками:
|
||||
|
||||
| Топик | Содержимое |
|
||||
|-------|-----------|
|
||||
| `dchain/tx/v1` | Транзакции (gossip) |
|
||||
| `dchain/blocks/v1` | Готовые блоки (gossip от лидера) |
|
||||
| `dchain/relay/v1` | Relay envelopes (зашифрованные сообщения) |
|
||||
|
||||
- **Direct streams:** PBFT consensus messages (pre-prepare/prepare/commit/view-change) идут напрямую между валидаторами через `/dchain/consensus/1.0.0` протокол
|
||||
- **Sync:** block range sync по `/dchain/sync/1.0.0` при подключении нового пира
|
||||
|
||||
---
|
||||
|
||||
## WASM Virtual Machine
|
||||
|
||||
**Runtime:** wazero v1.7.3, interpreter mode (детерминированный на всех платформах).
|
||||
|
||||
**Жизненный цикл контракта:**
|
||||
|
||||
```
|
||||
DEPLOY_CONTRACT tx
|
||||
├── validate: wazero.CompileModule() — если ошибка, tx отклоняется
|
||||
├── contractID = hex(sha256(deployerPubKey || wasmBytes))[:16]
|
||||
├── BadgerDB: contract:<id> → ContractRecord{WASMBytes, ABI, ...}
|
||||
└── state: cstate:<id>:* — изначально пусто
|
||||
|
||||
CALL_CONTRACT tx
|
||||
├── ABI validation: метод существует, число аргументов совпадает
|
||||
├── pre-charge: tx.Fee + gasLimit × gasPrice
|
||||
├── vm.Call(contractID, wasmBytes, method, argsJSON, gasLimit, hostEnv)
|
||||
│ ├── compile (cached) + instrument (gas_tick в loop headers)
|
||||
│ ├── register "env" host module (14 функций)
|
||||
│ ├── [optional] wasi_snapshot_preview1 (для TinyGo контрактов)
|
||||
│ └── fn.Call(ctx) → gasUsed, error
|
||||
├── refund: (gasLimit - gasUsed) × gasPrice → обратно sender
|
||||
└── logs: clog:<id>:<height>:<seq> → BadgerDB
|
||||
```
|
||||
|
||||
**Gas модель:** каждый вызов функции (WASM или host) = 100 gas units.
|
||||
`gasCost (µT) = gasUsed × gasPrice` (gasPrice управляется governance или константа 1 µT).
|
||||
|
||||
**Типы контрактов:**
|
||||
- **Binary WASM** — написаны на Go через кодогенераторы (`contracts/*/gen/main.go`)
|
||||
- **TinyGo WASM** — написаны на Go, компилируются с `tinygo -target wasip1`
|
||||
|
||||
---
|
||||
|
||||
## Экономика
|
||||
|
||||
**Supply:** Фиксированный. Genesis-блок минтит **21 000 000 T** на ключ node1. Последующей эмиссии нет.
|
||||
|
||||
**Unit:** µT (микро-токен). 1 T = 1 000 000 µT.
|
||||
|
||||
**Доходы валидаторов:** только комиссии из транзакций блока (`TotalFees`). Без блок-реварда.
|
||||
|
||||
**Комиссии:**
|
||||
| Операция | Минимальная fee |
|
||||
|---------|----------------|
|
||||
| Все транзакции | 1 000 µT (MinFee) |
|
||||
| CONTACT_REQUEST | tx.Amount → recipient (anti-spam) |
|
||||
| DEPLOY_CONTRACT | 10 000 µT |
|
||||
| CALL_CONTRACT | MinFee + gasUsed × gasPrice |
|
||||
| RELAY_PROOF | sender → relay node (произвольно) |
|
||||
|
||||
**Governance:** gas_price, relay_fee и другие параметры можно менять on-chain через governance-контракт без хардфорка.
|
||||
|
||||
---
|
||||
|
||||
## Relay (E2E мессенджер)
|
||||
|
||||
**Шифрование:** NaCl box (X25519 Diffie-Hellman + XSalsa20 + Poly1305).
|
||||
|
||||
**Ключи:** каждый Identity имеет два ключа:
|
||||
- Ed25519 (подпись транзакций, chain identity)
|
||||
- X25519 (вывод из Ed25519 seed, шифрование сообщений)
|
||||
|
||||
**Поток сообщения:**
|
||||
```
|
||||
Alice node1 (relay) Bob
|
||||
│ │ │
|
||||
│── seal(msg, bob.X25519) ──▶ │ │
|
||||
│ POST /relay/broadcast │ │
|
||||
│ │── gossip envelope ──▶ │
|
||||
│ │ store mailbox │
|
||||
│ │ (TTL 7 days) │
|
||||
│ │ │
|
||||
│ │◀── GET /relay/inbox ──│
|
||||
│ │ │── open(envelope)
|
||||
│ │ │ → plaintext
|
||||
```
|
||||
|
||||
**Anti-spam:**
|
||||
- Первый контакт — платный (CONTACT_REQUEST tx, fee идёт получателю)
|
||||
- Envelope: max 64 KB, max 500 envelopes на получателя (FIFO)
|
||||
- RELAY_PROOF: подписанное доказательство доставки, fee снимается со sender и кредитуется relay
|
||||
|
||||
---
|
||||
|
||||
## Динамические валидаторы
|
||||
|
||||
Сет валидаторов хранится on-chain в `validator:<pubkey>`. Любой текущий валидатор может добавить или убрать другого (ADD_VALIDATOR / REMOVE_VALIDATOR tx). После commit такого блока PBFT-движок перезагружает сет без рестарта ноды.
|
||||
|
||||
**Ключевые файлы:**
|
||||
```
|
||||
blockchain/chain.go — state machine, applyTx, VMHostEnv
|
||||
consensus/engine.go — PBFT, UpdateValidators()
|
||||
vm/vm.go — wazero runtime, NewVM()
|
||||
vm/host.go — host module "env" (14 функций)
|
||||
vm/gas.go — gas counter, Remaining()
|
||||
relay/mailbox.go — BadgerDB TTL mailbox
|
||||
relay/crypto.go — NaCl seal/open
|
||||
p2p/host.go — libp2p host, GossipSub
|
||||
node/api_routes.go — HTTP API routing
|
||||
```
|
||||
Reference in New Issue
Block a user