Files
SHiNE-server/docs/Archive/03_DEPLOY_TEST_SERVER.md
T

16 KiB
Raw Blame History

Деплой SHiNE Archive Publisher v1.0 на тестовый сервер

Документ рассчитан на человека или автономного coding/deploy агента. Выполнять шаги по порядку. Не включать publisher до проверки Solana-программы и ключей.

0. Что именно меняется

Нужны изменения одновременно в:

  1. серверном Java-коде;
  2. PostgreSQL schema v23;
  3. Solana-программе shine_users (PDA block type 100 + backward-compatible update parser);
  4. Java/JS User PDA codecs.

Критично: новый серверный writer отправляет расширенный обычный update_user_pda. Если в целевом кластере работает старая shine_users, включать publisher нельзя.


1. Применить пакет к исходникам

ZIP из этой поставки содержит только новые/изменённые файлы с путями относительно корня репозитория.

Сделать backup текущего проекта, затем распаковать ZIP поверх рабочего дерева.

После распаковки удалить legacy-файлы из списка 05_PATCH_CONTENTS_AND_REMOVALS.md.

Проверить:

git status --short

или, если это не git checkout, сравнить список файлов с manifest из той же документации.


2. Обязательно обновить shine_users в нужном Solana-кластере

2.1. Проверить целевой кластер

Не деплоить вслепую. Сначала:

solana config get

и проверить RPC/кластер, upgrade authority и Program ID. В проекте shine_users использует Program ID:

SHiNEPr1APdAgNBteUyBXcNovaHctpSjUu8oH2ZJdN6

Если тестовый сервер использует mainnet RPC, обновляется именно mainnet-программа. Если тестовый контур использует devnet — сначала убедиться, что программа с нужным ID действительно существует в devnet.

2.2. Собрать Solana program

cd shine-solana/shine
anchor build

Минимальная host-проверка Rust, если Anchor/SBF toolchain временно недоступен:

cargo build -p shine_users

Но для реального deploy нужен SBF/Anchor build.

2.3. Обновить существующую программу

Использовать существующий project deploy/upgrade authority. Типовой вариант:

solana program deploy target/deploy/shine_users.so \
  --program-id target/deploy/shine_users-keypair.json \
  --upgrade-authority /PATH/TO/UPGRADE_AUTHORITY.json \
  --url <TARGET_RPC_URL>

Если в проекте используется рабочий Anchor deploy workflow, допустимо использовать его вместо прямого solana program deploy; главное — сохранить тот же Program ID.

После обновления:

solana program show SHiNEPr1APdAgNBteUyBXcNovaHctpSjUu8oH2ZJdN6 --url <TARGET_RPC_URL>

3. Собрать серверный JAR

Из корня репозитория:

./gradlew clean shadowJar

Ожидаемый файл:

SHiNE-server/build/libs/shine-server.jar

Если Gradle wrapper не может скачать зависимости, сборку выполнять на машине/CI с доступом к Maven/Gradle или с уже заполненным cache.


4. Подготовить PostgreSQL backup

Перед первым стартом версии со schema v23 сделать backup тестовой БД. Например:

pg_dump -Fc -d '<DATABASE_URL_OR_NAME>' -f shine-before-archive-v22.dump

Точная команда зависит от текущей схемы доступа PostgreSQL.

При старте сервер последовательно применит migration_v22.sql и migration_v23.sql, если это требуется текущей версии БД. Вручную migrations выполнять обычно не нужно.

После старта проверить:

SELECT * FROM db_schema_version WHERE id=1;

Ожидается:

schema_version = 23

И наличие:

SELECT to_regclass('public.archive_chain_cursor');
SELECT to_regclass('public.archive_publish_job');
SELECT to_regclass('public.archive_publish_job_chain');

5. Подготовить секреты на тестовом сервере

Пример:

sudo -u player mkdir -p /home/player/SHiNE/secrets
sudo chmod 700 /home/player/SHiNE/secrets

Положить:

/home/player/SHiNE/secrets/archive-arweave-wallet.json
/home/player/SHiNE/secrets/server-root.key
/home/player/SHiNE/secrets/server-client.key

Права:

sudo chown player:player /home/player/SHiNE/secrets/*
sudo chmod 600 /home/player/SHiNE/secrets/*

Форматы root/client key

Поддерживаются:

  • raw seed 32 bytes;
  • raw keypair 64 bytes;
  • Solana JSON array на 32/64 байта;
  • Base58 seed на 32 байта или Solana secret key на 64 байта;
  • Base64 raw/PKCS8, где seed извлекается из последних 32 bytes.

Arweave wallet

Ожидается RSA JWK с полями n,e,d,p,q,dp,dq,qi. Кошелёк должен иметь достаточно AR для размера первого полного архива.


6. Настроить внешний application.properties

Сервер читает внешний application.properties из WorkingDirectory процесса и накладывает его поверх встроенного конфига. Сохранять существующие DB/Solana/server параметры и добавить archive-секцию.

Минимум:

archive.publish.enabled=true
archive.publish.time=00:00
archive.publish.zoneId=Europe/Warsaw
archive.workDir=data/archive
archive.maxFileBytes=4000000000

archive.arweave.gateway=https://arweave.net
archive.arweave.walletJwkPath=/home/player/SHiNE/secrets/archive-arweave-wallet.json
archive.arweave.minConfirmations=1
archive.arweave.confirmPollSeconds=30
archive.arweave.confirmTimeoutMinutes=180

archive.solana.rootKeyPath=/home/player/SHiNE/secrets/server-root.key
archive.solana.clientKeyPath=/home/player/SHiNE/secrets/server-client.key
archive.solana.confirmPollSeconds=5
archive.solana.confirmTimeoutMinutes=30
archive.solana.commitment=finalized

archive.publish.zoneId выбрать осознанно. Если оставить пустым, используется timezone JVM/машины. Для ежедневного запуска ровно в нужную локальную полночь лучше задать ZoneId явно.

Solana RPC

Отдельного archive RPC нет. Writer использует:

  1. solana.users.sync.rpcUrl, если он задан;
  2. иначе solana.rpcUrl.

Поэтому существующий рабочий RPC не дублировать в archive settings.


7. Убедиться, что server login соответствует ключам

server.SHiNE.login должен быть тем User PDA, чей archive head будет обновляться.

На startup SolanaArchiveHeadWriter проверяет:

derive(root private)   == UserPDA.root_key
derive(client private) == UserPDA.client_key

При несовпадении archive publisher не стартует.


8. Развернуть JAR

Можно использовать существующий deploy/scripts/deploy_server.sh. Он:

  • собирает shadowJar;
  • копирует JAR;
  • создаёт/обновляет systemd unit;
  • перезапускает сервис.

Типовой запуск задаётся уже существующими переменными проекта. Либо вручную заменить shine-server.jar в рабочей директории и перезапустить systemd service.

После deploy убедиться, что WorkingDirectory содержит внешний application.properties.


9. Первый startup

Смотреть лог:

sudo journalctl -u <SERVICE_NAME> -f

Ожидаемые события:

  1. DB migration до v22;
  2. обычный Solana users sync;
  3. обычный server-to-server blockchain sync;
  4. archive publisher preflight;
  5. строка примерно:
Archive publisher включён: login=... dir=data/archive dailyAt=00:00 zone=...
Следующая архивная публикация запланирована на ...

Если остался незавершённый job, он будет продолжен сразу после старта, не ожидая полуночи. Новый snapshot создаётся только по расписанию.


10. Что произойдёт в первую полночь

Если archive_chain_cursor пуст:

  • сервер проходит все локально известные blockchain_name;
  • для каждой берёт range 0..current_head;
  • создаёт первый big block #1;
  • для каждой blockchain создаёт максимум один UserBlockchainChunk;
  • внутри chunk лежат все её raw records из frozen range;
  • backlink первого chunk пустой (previous_big_block_ref = 0xFFFFFFFF);
  • создаёт локальный файл, например:
data/archive/archive01.00001.12.09.26.tmp.SHiNE-archive
  • загружает его в Arweave;
  • после успешной загрузки переименовывает тот же файл, например:
data/archive/archive01.00001.12.09.26.<REAL_TX_ID>.SHiNE-archive
  • ждёт confirmations;
  • обычным update_user_pda записывает block type 100;
  • ждёт Solana finalized;
  • только затем commit-ит cursors.

Если новых данных нет, пустой big block не создаётся.


11. Проверка результата

Локальные файлы

ls -lah data/archive/

После успешного upload .tmp.SHiNE-archive для завершённого job оставаться не должен; должен быть файл с реальным TX ID в имени.

Job DB

SELECT id, big_block_number, status, created_at_ms, local_archive_path,
       arweave_confirmations, solana_signature, error_text
FROM archive_publish_job
ORDER BY id DESC
LIMIT 10;

Успех:

status = CURSORS_COMMITTED

Cursors

SELECT blockchain_name,
       last_archived_source_block_number,
       last_archive_big_block_number,
       last_chunk_offset,
       last_chunk_size
FROM archive_chain_cursor
ORDER BY blockchain_name;

Локальная проекция User PDA

После очередной Solana sync:

SELECT login, record_number, archive_head_tx_id, archive_head_hash
FROM solana_user_pda_current
WHERE login = '<SERVER_LOGIN>';

archive_head_tx_id и archive_head_hash должны быть непустыми.

Arweave

TX берётся прямо из имени финального файла. Проверить:

curl -sS 'https://arweave.net/tx/<TX_ID>/status'

12. Быстрый тест до полуночи

Если не хочется ждать 00:00, на тестовом сервере временно установить archive.publish.time на ближайшие 5–10 минут в будущем в выбранной archive.publish.zoneId, затем перезапустить сервис.

После проверки вернуть:

archive.publish.time=00:00

Не использовать интервал в минутах: scheduler специально работает по календарному локальному времени один раз в сутки.


13. Откат / выключение

Самый безопасный функциональный rollback:

archive.publish.enabled=false

и рестарт сервера. Тогда обычная серверная работа продолжается, archive scheduler ничего не публикует.

Не удалять archive_chain_cursor/job таблицы без причины: они нужны, чтобы после повторного включения publisher продолжил дельту, а не загрузил всю историю заново.

Уже опубликованные Arweave данные являются постоянными и обычным rollback сервера не удаляются.


14. Наиболее вероятные ошибки

Root key archive publisher-а не совпадает с User PDA

Положен неправильный root key или неверный server.SHiNE.login.

Client key archive publisher-а не совпадает с User PDA

Неверный client key.

Недостаточно AR

Пополнить Arweave wallet. Первый архив может быть существенно больше ежедневных дельт.

Arweave upload прошёл, Solana update не прошёл

Не удалять локальный файл/job. После исправления RPC/program/key причины restart продолжит незавершённый job.

archive cursor hash не совпадает

Локальная blockchain изменилась относительно уже зафиксированного cursor. Не форсировать публикацию; сначала разобраться с resync/fork.

Старый shine_users

Если новый update payload отклоняется программой, проверить, что целевая Solana shine_users действительно обновлена этой версией.

Trusted archive importer

На обычном тестовом сервере publisher можно оставить выключенным, но разрешить импорт от конкретного архиватора:

archive.publish.enabled=false
archive.import.allowedPublishers=<LOGIN_ARCHIVE_SERVER>
archive.import.intervalMinutes=60
archive.import.workDir=data/archive-import

Несколько логинов:

archive.import.allowedPublishers=server-a,server-b

Пустая строка означает, что importer не запускается.

После старта проверить логи:

Archive importer включён. approvedPublishers=...

Если сервер подключается к publisher впервые, importer скачает head, прочитает FULL reference table и обработает все ещё не известные big blocks от старых к новым.

Проверка БД:

SELECT login, archive_head_tx_id, archive_imported, archive_last_imported_tx_id
FROM solana_user_pda_current
WHERE is_server=TRUE AND archive_head_tx_id<>''
ORDER BY login;

SELECT blockchain_name, publisher_login, arweave_tx_id,
       big_block_number, chunk_offset, chunk_size, source_last_block_number
FROM archive_blockchain_location
ORDER BY updated_at_ms DESC
LIMIT 20;

После деплоя UI файл должен быть доступен по:

https://<UI_HOST>/Blockchain-Viewer.html

В приложении: Настройки → Архив блокчейна.