# Архитектура DChain ## Обзор DChain — это L1-блокчейн для децентрализованного мессенджера + социальной ленты. Архитектура разделена на четыре слоя: ``` ┌─────────────────────────────────────────────────────────────┐ │ L3 Application — messaging, social feed, usernames, │ │ auctions, escrow │ │ (Smart contracts: username_registry, governance, auction, │ │ escrow; native feed events; deployed on-chain) │ ├─────────────────────────────────────────────────────────────┤ │ L2 Transport — relay mailbox (1:1 E2E) + │ │ feed mailbox (public posts + attachments)│ │ (relay/, media scrubber, GossipSub envelopes, RELAY_PROOF) │ ├─────────────────────────────────────────────────────────────┤ │ 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:` | JSON | Блоки по индексу | | `height` | uint64 JSON | Текущая высота | | `balance:` | uint64 JSON | Балансы токенов | | `id:` | JSON | Identity (RegisterKey payload) | | `validator:` | presence | Активный сет валидаторов | | `relay:` | JSON | Зарегистрированные relay-ноды | | `contract:` | JSON | ContractRecord (метаданные + WASM) | | `cstate::` | raw bytes | Состояние контракта | | `clog:::` | JSON | Логи контракта | | `rep:` | JSON | Репутация (blocks, relays, slashes) | | `contact_in::` | JSON | Входящие contact requests | | `mail:::` | 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: → ContractRecord{WASMBytes, ABI, ...} └── state: cstate::* — изначально пусто 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::: → 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 --- ## Социальная лента (v2.0.0) Публичные посты в Twitter/VK-стиле. Заменила channel-модель (каналы удалены полностью). Живёт гибридно — метаданные on-chain, тела в relay feed-mailbox: ``` Alice node1 (hosting relay) Bob │ │ │ │─ POST /feed/publish ──────▶│ │ │ (body + EXIF-scrub) │ │ │ │ store in feed-mailbox │ │ │ (TTL 30 days) │ │ │ │ │◀── response: content_hash, │ │ │ estimated_fee_ut, id │ │ │ │ │ │─ CREATE_POST tx ──────────▶│── PBFT commit ──────────▶ │ │ (fee = 1000 + size × 1) │ │ │ │ on-chain: post: │ │ │ │ │ │ │─ GET /feed/timeline │ │◀── merge followed authors │ (from chain) │ │ │ │ │── GET /feed/post/{id} ───▶│ │ │ (body from mailbox) │ ``` **Экономика:** - Автор платит `BasePostFee(1000) + size × PostByteFee(1)` µT - Вся плата уходит `hosting_relay` пубкею — компенсация за хранение - `MaxPostSize = 256 KiB` — hard cap, защищает мейлбокс от abuse **Метаданные:** - EXIF/GPS/camera-info удаляется обязательно на сервере (in-proc для изображений, через FFmpeg-сайдкар для видео) - Лайки / follows — on-chain транзакции (provable + anti-Sybil fee) - Просмотры — off-chain counter в relay (on-chain было бы абсурдно) - Хэштеги — авто-индекс при publish, inverted-index в BadgerDB Детали — [api/feed.md](api/feed.md). --- ## Динамические валидаторы Сет валидаторов хранится on-chain в `validator:`. Любой текущий валидатор может добавить или убрать другого (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 ```