Files
dchain/docs/update-system.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

8.3 KiB
Raw Permalink Blame History

Система обновлений и версионирование

DChain поставляется с полноценной системой update-detection, которая включает пять слоёв: build-time версия в бинаре, HTTP-эндпоинты для обнаружения, peer-gossip версий соседей, update-check от Gitea, и rolling-restart скрипт. Ниже — как это работает и как использовать.

Слой 1. Build-time версия

Бинарь хранит 4 поля, инжектимые через -ldflags -X:

  • Tag — человекочитаемый тег, обычно git describe --tags --always --dirty
  • Commit — полный 40-символьный SHA коммита
  • Date — RFC 3339 timestamp сборки (UTC)
  • Dirty"true" если сборка была из грязного worktree

Печать:

node --version
# dchain-node v0.0.1 (commit=abc1234 date=2026-04-17T10:00:00Z dirty=false)

client --version
# тот же формат

Все 4 образа (Dockerfile и deploy/prod/Dockerfile.slim) принимают эти значения через --build-arg VERSION_TAG=… и т.д. update.sh вычисляет их автоматически перед ребилдом.

Слой 2. /api/well-known-version

curl -s http://localhost:8080/api/well-known-version | jq .
{
  "node_version": "v0.0.1",
  "build": {
    "tag":    "v0.0.1",
    "commit": "abc1234…",
    "date":   "2026-04-17T10:00:00Z",
    "dirty":  "false"
  },
  "protocol_version": 1,
  "features": [
    "access_token", "chain_id", "contract_logs",
    "fan_out", "feed_v2", "identity_registry", "media_scrub",
    "native_username_registry", "onboarding_api", "payment_channels",
    "relay_broadcast", "relay_mailbox", "ws_submit_tx"
  ],
  "chain_id": "dchain-ddb9a7e37fc8"
}

Клиент использует это для feature-detection: зная features[], он знает какие экраны/флоу рендерить. Пример в client-app/lib/api.ts — функция checkNodeVersion().

Protocol version — отдельная ось от node_version. Меняется только при несовместимых изменениях wire-протокола (новый формат PBFT-message, breaking change в tx encoding). Клиент, который ожидает protocol_version: 1, не должен работать с нодой protocol_version: 2.

Слой 3. Peer-gossip версий

Каждая нода публикует своё {peer_id, tag, commit, protocol_version, timestamp} в gossipsub-топик dchain/version/v1 раз в 60 секунд. Другие ноды эту информацию получают, хранят 15 минут, и отдают через /api/peers:

curl -s http://localhost:8080/api/peers | jq .
{
  "peers": [
    {
      "id": "12D3KooW…",
      "addrs": ["/ip4/…/tcp/4001/p2p/12D3KooW…"],
      "version": {
        "tag": "v0.0.1",
        "commit": "abc1234…",
        "protocol_version": 1,
        "timestamp": 1745000000,
        "received_at": "2026-04-17T10:01:00Z"
      }
    }
  ]
}

Зачем это:

  • Operator видит «какая версия у моих соседей» одним запросом.
  • Client видит «стоит ли переключиться на другую ноду».
  • Feature-flag activation (например, EventChannelBan) можно запускать только когда ≥80% сети на новой версии.

Слой 4. /api/update-check

Оператор настраивает DCHAIN_UPDATE_SOURCE_URL на ссылку вида:

https://<your-gitea>/api/v1/repos/<owner>/<repo>/releases/latest

Нода опрашивает этот URL (15 мин cache, 5 сек timeout) и возвращает:

curl -s http://localhost:8080/api/update-check | jq .
{
  "current":          { "tag": "v0.0.1", "commit": "…", "date": "…", "dirty": "false" },
  "latest":           { "tag": "v0.0.2", "commit": "…", "url": "https://…", "published_at": "…" },
  "update_available": true,
  "checked_at":       "2026-04-17T11:00:00Z",
  "source":           "https://git.vsecoder.vodka/api/v1/repos/vsecoder/dchain/releases/latest"
}
  • 503 — не настроен DCHAIN_UPDATE_SOURCE_URL.
  • 502 — upstream (Gitea) недоступен или ответил non-2xx.
  • update_available: false — либо HEAD совпадает, либо Gitea вернула draft/prerelease (оба игнорируются).

Токен для приватного репо: DCHAIN_UPDATE_SOURCE_TOKEN=<Gitea PAT> (scope: read:repository достаточно).

Слой 5. update.sh + systemd timer

Скрипт в deploy/single/update.sh. Флоу:

  1. Если DCHAIN_UPDATE_SOURCE_URL задан — сначала спрашивает /api/update-check. Если update_available: false — выход с кодом 0.
  2. git fetch --tags.
  3. Semver guard: если UPDATE_ALLOW_MAJOR != true и major-версия меняется (v1.x → v2.y) — блокирует обновление с exit code 4.
  4. git checkout <tag> (в detached HEAD) или ff-merge на origin/main.
  5. Ребилд образа с правильными --build-arg VERSION_*.
  6. Smoke-test: docker run --rm … node --version — должен напечатать новую версию без ошибок.
  7. docker compose up -d --force-recreate node.
  8. Polling /api/netstats до 60 сек — если не ожил, exit 1.

Systemd-интеграция — в deploy/single/systemd/:

sudo cp deploy/single/systemd/dchain-update.{service,timer} /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now dchain-update.timer

Таймер: OnUnitActiveSec=1h + RandomizedDelaySec=15min — чтобы федерация не рестартовала вся одновременно и не уронила PBFT quorum.

Schema migrations (BadgerDB)

Отдельный слой, относящийся к on-disk формату данных. См. blockchain/schema_migrations.go:

  • CurrentSchemaVersion — const в Go-коде, bumpается с каждой миграцией.
  • schemaMetaKey = "schema:ver" — ключ в BadgerDB хранит фактическую версию данных.
  • runMigrations(db) вызывается при NewChain(), применяет каждый шаг форвард-миграций атомарно (data rewrite + version bump в одной badger.Update транзакции).
  • Если stored version > CurrentSchemaVersion — ошибка (запускаете старый бинарь на новом DB). Fix: обновите бинарь или восстановите из бэкапа.

На текущий релиз CurrentSchemaVersion = 0, миграций нет — scaffold живёт и готов к первому реальному изменению формата.

Forward-compat для EventType

В blockchain/chain.goapplyTx() добавлен default: case для неизвестных EventType:

  • Fee дебитуется с отправителя (не спам-вектор).
  • Tx применяется как no-op.
  • В логе warning «unknown event type … — binary is older than this tx».

Это значит: новую EventType можно подать в сеть, она будет обработана на новых нодах и проигнорирована на старых, без split'а консенсуса. Full design — deploy/UPDATE_STRATEGY.md → §5.1.

Checklist при релизе

  1. В Git git tag -a vX.Y.Z -m "release notes" + git push origin vX.Y.Z.
  2. В Gitea UI: Releases → New Release → Tag: vX.Y.Z → Publish.
  3. На всех нодах с настроенным update.sh:
    • systemd-таймер подхватит через ~1 час (± 15 мин jitter).
    • Operator может форсить: sudo systemctl start dchain-update.service.
  4. Проверка:
    curl -s https://<node>/api/well-known-version | jq .build.tag
    # должно вернуть vX.Y.Z