Three related UX fixes on the client. 1. Participants count on profile DMs always have exactly two participants (you and the contact) so a "Участников: 1" row was confusing — either it's obviously the other person or it's wrong depending on how you count. Removed for direct conversations; the row still appears for group chats (and shows an em-dash until v2.1.0 gives groups a real member list). 2. Dev feed seed now activates on network / 404 errors The seed was only surfaced when the real API returned an EMPTY array. If the node was down (Network request failed) or the endpoint replied 404, the catch block quietly set posts to [] and the list stayed blank — defeating the point of the seed. Now both the empty- response path AND the network-error path fall back to getDevSeedFeed(), so scrolling / like-toggling works even without a running node. Also made the __DEV__ lookup more defensive: use `globalThis.__DEV__` at runtime instead of the typed global. Some bundler configurations have the TS type but not the runtime binding, or vice-versa — the runtime lookup always agrees with Metro. 3. Back from profile → previous screen instead of tab root Root cause: AnimatedSlot rendered <Slot>, which is stack-less. When /chats/xyz pushed /profile/abc (cross-group), the chats group unmounted. Hitting Back then re-entered chats at its root (/chats list) rather than /chats/xyz. Replaced <Slot> with <Stack> in AnimatedSlot. Tab switching still stays flat because NavBar uses router.replace (which maps to navigation.replace on the Stack — no history accumulation). Cross-group pushes (post author tap from feed, avatar tap from chat header, compose modal) now live in the outer Stack's history, so Back pops correctly to the caller. The nested Stacks (chats/_layout.tsx, feed/_layout.tsx, profile/_layout.tsx) still handle intra-group navigation as before. The PanResponder-based swipe-right-to-back was removed since the native Stack now provides iOS edge-swipe natively; Android uses the system back button. animation: 'none' keeps the visual swap instant — matches the prior Slot look so nothing flashes slide-animations that weren't there before. Sub-group layouts can opt into slide_from_right themselves (profile/_layout.tsx and feed/_layout.tsx already do). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
DChain
Блокчейн-стек для децентрализованного мессенджера:
- PBFT консенсус с multi-sig validator governance и equivocation slashing
- Native Go контракты рядом с WASM (wazero) — нулевая задержка для
системных сервисов типа
username_registry - WebSocket push API — клиент не опрашивает, все события прилетают на соединение
- E2E-шифрованный relay mailbox на libp2p gossipsub с TTL live-detection
- Система обновлений: build-time версия →
/api/well-known-version, peer-version gossip,/api/update-checkпротив Gitea releases,update.shс semver guard - Prometheus
/metrics, Caddy auto-HTTPS, observer mode, load-test
Содержание
Быстрый старт
Одна нода в Docker, HTTP API на localhost:8080, Explorer UI и Swagger
открыты:
# 1. Собираем prod-образ
docker build -t dchain-node-slim -f deploy/prod/Dockerfile.slim .
# 2. Ключ ноды (один раз)
mkdir -p keys
docker run --rm --entrypoint /usr/local/bin/client \
-v "$PWD/keys:/out" dchain-node-slim \
keygen --out /out/node.json
# 3. Запуск (genesis-валидатор)
docker run -d --name dchain --restart unless-stopped \
-p 4001:4001 -p 8080:8080 \
-v dchain_data:/data \
-v "$PWD/keys:/keys:ro" \
-e DCHAIN_GENESIS=true \
-e DCHAIN_ANNOUNCE=/ip4/127.0.0.1/tcp/4001 \
dchain-node-slim \
--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
# 4. Проверка
open http://localhost:8080/ # Explorer
open http://localhost:8080/swagger # Swagger UI
curl -s http://localhost:8080/api/well-known-version | jq .
3-node dev-кластер (для тестов PBFT кворума, slashing, federation): docker compose up --build -d — см. docs/quickstart.md.
Продакшен деплой
Два варианта, по масштабу.
🔸 Single-node (deploy/single/)
Рекомендуется для личного/первого узла. Один узел + Caddy TLS +
опциональный Prometheus. Полный runbook с 6 сценариями (публичная с UI,
headless, полностью приватная, genesis, joiner, auto-update) — в
deploy/single/README.md.
Модели доступа
| Режим | DCHAIN_API_TOKEN |
DCHAIN_API_PRIVATE |
Поведение |
|---|---|---|---|
| Public (default) | не задан | — | Все могут читать и писать |
| Token writes | задан | false |
Читать — любой; submit tx — только с токеном |
| Fully private | задан | true |
Всё требует Authorization: Bearer <token> |
UI / Swagger — включать или нет?
| Нужно | DCHAIN_DISABLE_UI |
DCHAIN_DISABLE_SWAGGER |
Открыто |
|---|---|---|---|
| Публичная с эксплорером + docs | не задано | не задано | / Explorer, /swagger, /api/*, /metrics |
| Headless API-нода с OpenAPI | true |
не задано | /swagger, /api/*, /metrics |
| Личная hardened | true |
true |
/api/* + /metrics |
Флаги читаются и из CLI (--disable-ui, --disable-swagger), и из env.
/api/* JSON-поверхность регистрируется всегда — отключить её можно
только на уровне Caddy / firewall.
Auto-update
# node.env — когда проект в Gitea
DCHAIN_UPDATE_SOURCE_URL=https://gitea.example.com/api/v1/repos/OWNER/REPO/releases/latest
UPDATE_ALLOW_MAJOR=false
# Hourly systemd timer с 15-мин jitter
sudo cp deploy/single/systemd/dchain-update.{service,timer} /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now dchain-update.timer
Подробно: docs/update-system.md + deploy/UPDATE_STRATEGY.md.
🔹 Multi-validator (deploy/prod/)
3 validator'а в PBFT-кворуме, Caddy с ip_hash для WS-стикинесса и
least-conn для REST. Для федераций / консорциумов — см.
deploy/prod/README.md и
docs/node/multi-server.md.
Архитектура
┌────────────┐ libp2p ┌────────────┐ libp2p ┌────────────┐
│ node-A │◄─────pubsub──►│ node-B │◄─────pubsub──►│ node-C │
│ validator │ │ validator │ │ validator │
│ + relay │ │ + relay │ │ + relay │
└─────┬──────┘ └─────┬──────┘ └─────┬──────┘
│ │ │
│ HTTPS / wss (via Caddy) │ │
▼ ▼ ▼
mobile / web / CLI clients (ip_hash для WS, least-conn для REST)
Четыре слоя: network → chain → transport → app. Детали — в
docs/architecture.md.
Основные пакеты:
| Путь | Роль |
|---|---|
blockchain/ |
Блочная машина, applyTx, native-контракты, schema-migrations |
consensus/ |
PBFT (Pre-prepare → Prepare → Commit), мемпул, equivocation |
p2p/ |
libp2p host, gossipsub, sync протокол, peer-version gossip |
node/ |
HTTP + WS API, SSE, metrics, access control |
node/version/ |
Build-time version metadata (ldflags-инжектимый) |
vm/ |
wazero runtime для WASM-контрактов + gas model |
relay/ |
E2E mailbox с NaCl-envelopes |
identity/ |
Ed25519 + X25519 keypair, tx signing |
economy/ |
Fee model, rewards |
wallet/ |
Optional payout wallet (отдельный ключ) |
REST / WebSocket API
Обзор (полный reference — docs/api/README.md):
Chain + stats
| Endpoint | Описание |
|---|---|
GET /api/netstats |
height, total_txs, supply, validator_count |
GET /api/network-info |
chain_id, genesis, peers, validators, contracts |
GET /api/blocks?limit=N / /api/block/{index} |
Блоки |
GET /api/tx/{id} / /api/txs/recent?limit=N |
Транзакции |
GET /api/address/{pub_or_addr} |
Баланс + история |
GET /api/validators |
Validator set |
GET /api/peers |
Connected peers + их версии |
POST /api/tx |
Submit signed tx (rate-limited, size-capped) |
Discovery + update
| Endpoint | Описание |
|---|---|
GET /api/well-known-version |
{node_version, build{}, protocol_version, features[], chain_id} |
GET /api/well-known-contracts |
{name → contract_id} map |
GET /api/update-check |
Diff с Gitea release (см. docs/update-system.md) |
Real-time
GET /api/ws— WebSocket (recommended). Ops:auth,subscribe,unsubscribe,submit_tx,typing,ping. Push:block,tx,inbox,typing,submit_ack.GET /api/events— SSE legacy one-way.
Scoped WS-топики (addr:, inbox:, typing:) требуют auth через
Ed25519-nonce; публичные (blocks, tx, contract_log) — без.
Docs / UI
GET /swagger— Swagger UI (рендерится через swagger-ui-dist).GET /swagger/openapi.json— сырая OpenAPI 3.0 спека.GET /— block-explorer HTML (выключаетсяDCHAIN_DISABLE_UI=true).
CLI
client keygen --out key.json
client --version # → dchain-client vX.Y.Z (commit=... date=...)
client balance --key key.json --node URL
client transfer --key key.json --to <pub> --amount <µT> --node URL
client call-contract --key key.json --contract native:username_registry \
--method register --arg alice --amount 10000 \
--node URL
client add-validator --key key.json --target <pub> --cosigs pub:sig,pub:sig
client admit-sign --key validator.json --target <candidate-pub>
client deploy-contract --key key.json --wasm ./my.wasm --abi ./my_abi.json --node URL
# полный список — `client` без аргументов, или в docs/cli/README.md
Все флаги node — в docs/node/README.md, либо
node --help.
Мониторинг
Prometheus endpoint /metrics на каждой ноде. Ключевые метрики:
dchain_blocks_total # committed blocks count
dchain_txs_total # tx count
dchain_tx_submit_accepted_total
dchain_tx_submit_rejected_total
dchain_ws_connections # current WS sockets
dchain_peer_count_live # live libp2p peer count
dchain_max_missed_blocks # worst validator liveness gap
dchain_block_commit_seconds # histogram of AddBlock time
Grafana + Prometheus поднимаются вместе с нодой через
docker compose --profile monitor up -d (см. deploy/single/docker-compose.yml).
Тесты
# Unit + integration
go test ./... # blockchain + consensus + identity + relay + vm
go vet ./... # static checks
# End-to-end load (3-node dev cluster должен быть поднят):
docker compose up --build -d
go run ./cmd/loadtest \
--node http://localhost:8081 \
--funder testdata/node1.json \
--clients 50 --duration 60s
Документация
Полный справочник в docs/ — см. docs/README.md как
оглавление. Ключевые документы:
| Документ | О чём |
|---|---|
docs/quickstart.md |
Три пути: локально, single-node prod, федерация |
docs/architecture.md |
4 слоя, consensus, storage, gas model |
docs/update-system.md |
Versioning + update-check + semver guard |
docs/api/README.md |
REST + WebSocket reference |
docs/cli/README.md |
CLI команды и флаги |
docs/node/README.md |
Запуск ноды (native + Docker) |
docs/contracts/README.md |
Системные + WASM контракты |
docs/development/README.md |
SDK для своих контрактов |
deploy/single/README.md |
Single-node operator runbook |
deploy/prod/README.md |
Multi-validator federation |
deploy/UPDATE_STRATEGY.md |
Forward-compat design (4 слоя) |