Files
SHiNE-server/docs/Archive/02_IMPLEMENTATION_MAP.md

7.9 KiB
Raw Permalink Blame History

Карта реализации SHiNE Archive Publisher v1.0

Этот документ связывает протокол с конкретными файлами проекта. Он нужен, чтобы другой агент мог быстро понять, где искать каждую часть реализации.

1. Новый Java-модуль shine-server-archive

Путь: SHiNE-server/shine-server-archive/.

Основные классы:

  • ArchivePublisherScheduler — включает publisher только при archive.publish.enabled=true, сразу продолжает незавершённый job после рестарта и планирует новый snapshot один раз в сутки в archive.publish.time. Следующая дата вычисляется по ZoneId, а не как +24h, поэтому DST не сдвигает локальную полночь.
  • ArchivePublisherService — state machine: snapshot → локальный файл → Arweave → confirmations → User PDA → Solana finalized → cursor commit.
  • ArchivePublisherConfig — читает настройки. Для Solana RPC отдельного archive URL нет: используется solana.users.sync.rpcUrl, затем fallback на solana.rpcUrl.
  • ShineArchiveWriter — сериализует бинарный big block SHINE-ARCHIVE v1.0, FULL reference table, по одному chunk на blockchain_name, footer/hash/signature.
  • ArchiveFileNames — временное и финальное локальные имена.
  • ArweaveArchiveService + ArweaveMerkle — Arweave v2 transaction + chunk upload + polling confirmations.
  • SolanaArchiveHeadWriter — обычный update_user_pda: root signature + текущая last-block signature + client key fee payer, затем ожидание finalized.
  • ArchiveKeyLoader — читает Ed25519 seed/keypair из raw 32/64 bytes, Solana JSON 32/64 или Base64/PKCS8.

2. Локальное состояние PostgreSQL

Миграция: SHiNE-server/shine-server-db/src/main/resources/postgres/migration_v22.sql.

Таблицы:

archive_chain_cursor

Одна строка на blockchain_name. Хранит только последнее окончательно опубликованное состояние:

  • последний source block number/hash;
  • big block number/hash, где находится последний chunk;
  • offset/size последнего chunk.

Если blockchain не попала в новый big block, эта строка не меняется.

archive_publish_job

Crash-safe state одной большой публикации и путь к локальному файлу.

Основные состояния: SNAPSHOT_CREATED → FILE_BUILT → ARWEAVE_UPLOADED → ARWEAVE_CONFIRMED → SOLANA_SUBMITTED → SOLANA_FINALIZED → CURSORS_COMMITTED.

archive_publish_job_chain

Frozen range каждой blockchain текущего job + старые и новые координаты chunk. Пока job не finalized, archive_chain_cursor не двигается.

DatabaseInitializer автоматически применяет migration v22 при старте существующей БД. Новая БД создаётся уже со схемой v22.

3. Как считается первая дельта

ArchivePublisherService.createFrozenJob() проходит по BlockchainStateDAO.listAll().

  • Если cursor для blockchain_name отсутствует: from = 0, поэтому первый архив содержит всё локально известное состояние 0..head.
  • Если cursor существует: from = last_archived + 1.
  • Перед продолжением проверяется hash cursor-блока.

Папка data/archive сама по себе не является источником истины о том, был ли первый архив. Источник истины — БД cursor/job. Поэтому удаление локального файла не приводит к ошибочной повторной полной публикации.

4. Локальный lifecycle файла

До появления Arweave TX ID:

<login>.<00001>.<dd.MM.yy>.tmp.SHiNE-archive

После полной успешной загрузки transaction header + chunks в Arweave:

<login>.<00001>.<dd.MM.yy>.<ARWEAVE_TX_ID>.SHiNE-archive

Дата — реальная дата freeze snapshot в timezone archive publisher-а. Номер начинается с 00001. Пять цифр — минимальная ширина, а не лимит.

После rename файл остаётся локально. При crash после сохранения TX ID, но до rename, recovery переименует тот же файл и не загрузит его повторно.

5. User PDA block type 100

Содержимое:

u8        block_type = 100
u8        block_version = 0
bytes[32] archive_tx_id
bytes[32] archive_hash

Используется существующий update_user_pda; отдельной instruction нет.

Совместимость:

  • legacy update без archive extension должен сохранить старый archive head;
  • новый update может заменить/очистить block 100;
  • Java/JS codecs и PostgreSQL Solana sync умеют читать новый блок.

Ключевой Rust-файл: shine-solana/shine/programs/shine_users/src/lib.rs.

6. Startup сервера

WsServer после текущего Solana/users sync и inter-server blockchain sync вызывает ArchivePublisherScheduler.startOrLog().

При archive.publish.enabled=false scheduler пишет лог о выключенной функции и больше ничего не делает. Ключи/Arweave wallet на обычном сервере тогда не требуются.

7. Legacy TestFreeAvatar

Старый временный TestFreeAvatarArweaveService больше не является частью активного WS-протокола. Registry/API документация убраны. При наложении changed-files ZIP поверх старого дерева старые исходники физически останутся, поэтому их список для удаления находится в 05_PATCH_CONTENTS_AND_REMOVALS.md.

Trusted importer / location index / Viewer

Server importer:

shine-server-archive/src/main/java/server/archive/ArchiveImportConfig.java
shine-server-archive/src/main/java/server/archive/ArchiveImportScheduler.java
shine-server-archive/src/main/java/server/archive/ArchiveImportService.java
shine-server-archive/src/main/java/server/archive/ShineArchiveReader.java

Database:

shine-server-db/src/main/java/shine/db/dao/ArchiveImportDAO.java
shine-server-db/src/main/java/shine/db/archive/ArchiveBlockchainLocation.java
shine-server-db/src/main/java/shine/db/archive/ArchivePublisherHead.java
shine-server-db/src/main/resources/postgres/migration_v23.sql
shine-server-solana-users-sync/src/main/java/sync/storage/postgres/PostgresStorageRepository.java

PostgresStorageRepository сохраняет archive_imported=true при повторном sync того же head и автоматически сбрасывает флаг в false, если archive_head_tx_id или archive_head_hash изменились.

WS API:

GetArchiveBlockchainLocation

UI:

shine-UI/js/pages/blockchain-archive-view.js
shine-UI/Blockchain-Viewer.html

Blockchain-Viewer.html получает tx + offset + size + blockchain, идёт назад по PreviousBlockchainChunkRef и использует существующий parser каналов старого Viewer-а.