Files
dchain/docs/architecture.md
vsecoder 1a8731f479 docs: update README + api docs + architecture for v2.0.0 feed
README
  - Mention social feed in the one-line description and feature bullets
  - Add relay + feed endpoint tables to the API overview (was
    previously empty on messaging)
  - List media/ package in the repo structure

docs/api/
  - New docs/api/feed.md: full reference for /feed/publish, fetch,
    stats, view, author, timeline, trending, foryou, hashtag; all
    on-chain CREATE_POST / DELETE_POST / FOLLOW / LIKE payloads;
    fee economics; server-side scrubbing contract.
  - docs/api/relay.md rewritten: /relay/broadcast is now the primary
    E2E path with a complete envelope schema; /relay/send kept but
    flagged ⚠ NOT E2E; DELETE /relay/inbox/{id} documented with the
    new Ed25519 signed-auth body.
  - docs/api/README.md index: added feed.md row.

docs/architecture.md
  - L2 Transport layer description updated to include the feed
    mailbox alongside the 1:1 relay mailbox.
  - New "Социальная лента (v2.0.0)" section right after the 1:1
    message flow: ASCII diagram of publish + on-chain commit +
    timeline fetch, economic summary, metadata-scrub summary.

docs/node/README.md
  - Removed stale chan:/chan-member: keys from the BadgerDB schema
    reference; replaced with the v2.0.0 feed keys (post:,
    postbyauthor:, follow:, followin:, like:, likecount:).

docs/update-system.md
  - Example features[] array updated to match the actual node output
    (channels_v1 removed, feed_v2 / media_scrub / relay_broadcast added).

Node feature flags
  - api_well_known_version.go: dropped channels_v1 tag (the
    /api/channels/:id endpoint was removed in the feed refactor);
    added feed_v2, media_scrub, relay_broadcast so clients can
    feature-detect the v2.0.0 surface.
  - Comment example updated channels_v2/v1 → feed_v3/v2.

Client
  - CLIENT_REQUIRED_FEATURES expanded to include the v2.0.0 feature
    flags the client now depends on (feed_v2, media_scrub,
    relay_broadcast); checkNodeVersion() will flag older nodes as
    unsupported and surface an upgrade prompt.

All 7 Go test packages green; tsc --noEmit clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 22:06:06 +03:00

13 KiB
Raw Permalink Blame History

Архитектура 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:<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

Социальная лента (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:<id>     │
  │                            │                           │
  │                            │                           │─ 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.


Динамические валидаторы

Сет валидаторов хранится 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