6.5 KiB
Карта реализации 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 blockSHINE-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.