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

254 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Архитектура 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](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
```