Files
SHiNE-server/docs/Blockchain/17_ANS104_Arweave_Transport.md
T

7.3 KiB

ANS-104 / Arweave transport для пользовательских блоков SHiNE

Цель

Каждый пользовательский блок SHiNE уже на клиенте является самостоятельным подписанным ANS-104 DataItem. Сервер проверяет и хранит точно эти signed bytes и может публиковать их одним из двух транспортов: через Turbo по одному DataItem либо через прямую Arweave L1-транзакцию в составе стандартного большого ANS-104 bundle.

Способ публикации — локальная политика конкретного сервера. Формат пользовательского блока и импорт от него не зависят.

User DataItem tags

Для тестового контура обязательно:

App=test5590

Для блоков конкретного канала дополнительно:

c_test5590=<canonical_channel_slug>

Теги входят в ANS-104 подпись пользователя. Старый тестовый тег c новым кодом не создаётся и не принимается как channel tag.

Publisher modes

Настройка:

arweave.blocks.publish.mode=turbo | arweave | none

turbo

blocks.arweave_publish_pending=true
        ↓
готовый signed user DataItem из blocks.block_bytes
        ↓
POST в Turbo как application/octet-stream
        ↓
Turbo bundling / Arweave

DataItem не переподписывается сервером. Его data_item_id = SHA-256(user signature) до и после загрузки должен оставаться тем же.

Для Turbo можно задать публичный payer address напрямую:

arweave.blocks.publish.turbo.paidByAddress=...

либо путь к серверному Arweave JWK:

arweave.blocks.publish.turbo.walletJwkPath=/path/to/server-turbo-wallet.json

Из JWK локально вычисляется только публичный Arweave address для x-paid-by; приватный ключ Turbo upload endpoint не получает.

Важно: если upload уже требует оплаты, а signed DataItem принадлежит другому signer, Turbo Credits серверного кошелька используются через Credit Share Approval в пользу signer-адреса. Для маленьких DataItem, попадающих под действующий free tier Turbo, payer может не понадобиться. Код не должен рассчитывать на вечное существование free tier: HTTP 402 считается ошибкой оплаты и блок остаётся pending.

arweave

Сохраняется прежний fallback:

pending user DataItems
        ↓
standard ANS-104 binary bundle
        ↓
server Arweave RSA/JWK signature
        ↓
Arweave L1

Root transaction содержит только стандартные bundle tags:

Bundle-Format=binary
Bundle-Version=2.0.0
Content-Type=application/octet-stream

Специальный App=test5590-batch больше не используется. Важны вложенные user DataItems, у которых уже есть App=test5590.

none

Сервер принимает и хранит блоки локально, но publisher не отправляет их в Arweave/Turbo. Importer при этом может работать независимо.

Состояние публикации в БД

После успешной публикации:

  • arweave_publish_pending=false;
  • заполняется arweave_published_at_ms.

arweave_root_tx_id больше не хранится: один и тот же пользовательский DataItem может быть физически упакован разными bundler-ами, а стабильным сетевым идентификатором SHiNE является именно data_item_id.

Importer: только individual DataItems

Importer всегда выполняет один discovery-запрос:

App=test5590

Он не ищет root bundles и не зависит от publish.mode.

Это одинаково работает для:

  • DataItem, отправленного через Turbo;
  • DataItem, находящегося внутри большого direct-Arweave ANS-104 bundle сервера.

После того как AR.IO gateway распаковал/indexed bundle, child DataItem присутствует в GraphQL как отдельная сущность со своим id и собственными tags.

Получение полного signed DataItem

Обычная выдача DataItem по gateway URL может представлять только payload, а SHiNE для криптографической проверки нужны полные serialized ANS-104 bytes.

Поэтому importer:

  1. получает data_item_id через GraphQL App=test5590;
  2. запрашивает GET /ar-io/offsets/{data_item_id};
  3. получает rootTxId, rootOffset, size;
  4. делает range-read GET /raw/{rootTxId} ровно по этому диапазону;
  5. разбирает полученные bytes как Ans104DataItem;
  6. проверяет, что SHA-256(signature) == data_item_id;
  7. проверяет Ed25519 ANS-104 signature;
  8. определяет пользователя по owner;
  9. импортирует через обычную логику AddBlock без повторной публикации.

Если GraphQL уже увидел DataItem, но gateway ещё не подготовил offsets, checkpoint не продвигается за этот height и DataItem будет повторён в следующем цикле.

Очередь и порядок блоков

arweave_block_import_queue хранит:

  • data_item_id;
  • block_height;
  • полный raw_data_item;
  • status/error/timestamps.

root_tx_id очереди больше не нужен.

Если block N+1 увиден раньше N, он остаётся PENDING; после появления предыдущего блока очередь повторно проигрывается.

Дедупликация

blocks.data_item_id уникален. Один signed DataItem остаётся одним логическим SHiNE-блоком независимо от того, сколько серверов или bundler-ов физически включили его в Arweave.

Импортированный блок записывается через AddBlock с отключённой повторной публикацией, поэтому серверы не создают цикл переархивирования.

Локальное хранение

Полный serialized signed DataItem хранится в blocks.block_bytes PostgreSQL. Пользовательские .bch-файлы не являются источником истины.