SHA256
Добавить импорт архивов с доверенных серверов
This commit is contained in:
@@ -1617,3 +1617,31 @@ BigBlock #100
|
||||
- PDA обновляется обычным `update_user_pda`;
|
||||
- Arweave используется как долговременное хранилище;
|
||||
- публикация считается завершённой только после Arweave confirmation + Solana finalized + cursor commit.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Trusted archive reader / importer
|
||||
|
||||
Бинарный формат v1.0 не меняется. Обычный сервер MAY использовать archive head из User PDA для восстановления недостающих SHiNE-блоков, но SHOULD принимать архивы только от явно разрешённых server logins.
|
||||
|
||||
Рекомендуемая политика v1:
|
||||
|
||||
```text
|
||||
publisher login ∈ local whitelist
|
||||
AND UserPDA.is_server = true
|
||||
AND SHA256(file) == UserPDA.archive_head_hash / reference hash
|
||||
AND creator_login == closer_login == publisher login
|
||||
AND Ed25519 archive signature valid for publisher root key
|
||||
AND every raw SHiNE block passes normal AddBlock validation
|
||||
```
|
||||
|
||||
FULL reference table head-блока позволяет поздно подключившемуся серверу импортировать всю неизвестную историю publisher-а от старых big blocks к новым.
|
||||
|
||||
Для быстрого пользовательского доступа сервер SHOULD поддерживать локальный индекс:
|
||||
|
||||
```text
|
||||
blockchain_name -> arweave_tx_id + chunk_offset + chunk_size
|
||||
```
|
||||
|
||||
Он указывает на последний известный `UserBlockchainChunk`. Backlink внутри chunk делает эту одну ссылку достаточной для обхода всей архивной истории конкретной blockchain.
|
||||
|
||||
@@ -96,3 +96,42 @@ bytes[32] archive_hash
|
||||
## 7. Legacy TestFreeAvatar
|
||||
|
||||
Старый временный `TestFreeAvatarArweaveService` больше не является частью активного WS-протокола. Registry/API документация убраны. При наложении changed-files ZIP поверх старого дерева старые исходники физически останутся, поэтому их список для удаления находится в `05_PATCH_CONTENTS_AND_REMOVALS.md`.
|
||||
|
||||
|
||||
## Trusted importer / location index / Viewer
|
||||
|
||||
Server importer:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
GetArchiveBlockchainLocation
|
||||
```
|
||||
|
||||
UI:
|
||||
|
||||
```text
|
||||
shine-UI/js/pages/blockchain-archive-view.js
|
||||
shine-UI/Blockchain-Viewer.html
|
||||
```
|
||||
|
||||
`Blockchain-Viewer.html` получает `tx + offset + size + blockchain`, идёт назад по `PreviousBlockchainChunkRef` и использует существующий parser каналов старого Viewer-а.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
Нужны изменения одновременно в:
|
||||
|
||||
1. серверном Java-коде;
|
||||
2. PostgreSQL schema v22;
|
||||
2. PostgreSQL schema v23;
|
||||
3. Solana-программе `shine_users` (PDA block type `100` + backward-compatible update parser);
|
||||
4. Java/JS User PDA codecs.
|
||||
|
||||
@@ -107,7 +107,7 @@ SHiNE-server/build/libs/shine-server.jar
|
||||
|
||||
# 4. Подготовить PostgreSQL backup
|
||||
|
||||
Перед первым стартом версии со schema v22 сделать backup тестовой БД. Например:
|
||||
Перед первым стартом версии со schema v23 сделать backup тестовой БД. Например:
|
||||
|
||||
```bash
|
||||
pg_dump -Fc -d '<DATABASE_URL_OR_NAME>' -f shine-before-archive-v22.dump
|
||||
@@ -115,7 +115,7 @@ pg_dump -Fc -d '<DATABASE_URL_OR_NAME>' -f shine-before-archive-v22.dump
|
||||
|
||||
Точная команда зависит от текущей схемы доступа PostgreSQL.
|
||||
|
||||
При старте сервер сам применит `migration_v22.sql`, если `db_schema_version < 22`. Вручную migration выполнять обычно не нужно.
|
||||
При старте сервер последовательно применит `migration_v22.sql` и `migration_v23.sql`, если это требуется текущей версии БД. Вручную migrations выполнять обычно не нужно.
|
||||
|
||||
После старта проверить:
|
||||
|
||||
@@ -126,7 +126,7 @@ SELECT * FROM db_schema_version WHERE id=1;
|
||||
Ожидается:
|
||||
|
||||
```text
|
||||
schema_version = 22
|
||||
schema_version = 23
|
||||
```
|
||||
|
||||
И наличие:
|
||||
@@ -413,3 +413,54 @@ archive.publish.enabled=false
|
||||
|
||||
### Старый `shine_users`
|
||||
Если новый update payload отклоняется программой, проверить, что целевая Solana `shine_users` действительно обновлена этой версией.
|
||||
|
||||
|
||||
## Trusted archive importer
|
||||
|
||||
На обычном тестовом сервере publisher можно оставить выключенным, но разрешить импорт от конкретного архиватора:
|
||||
|
||||
```properties
|
||||
archive.publish.enabled=false
|
||||
archive.import.allowedPublishers=<LOGIN_ARCHIVE_SERVER>
|
||||
archive.import.intervalMinutes=60
|
||||
archive.import.workDir=data/archive-import
|
||||
```
|
||||
|
||||
Несколько логинов:
|
||||
|
||||
```properties
|
||||
archive.import.allowedPublishers=server-a,server-b
|
||||
```
|
||||
|
||||
Пустая строка означает, что importer не запускается.
|
||||
|
||||
После старта проверить логи:
|
||||
|
||||
```text
|
||||
Archive importer включён. approvedPublishers=...
|
||||
```
|
||||
|
||||
Если сервер подключается к publisher впервые, importer скачает head, прочитает FULL reference table и обработает все ещё не известные big blocks от старых к новым.
|
||||
|
||||
Проверка БД:
|
||||
|
||||
```sql
|
||||
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 файл должен быть доступен по:
|
||||
|
||||
```text
|
||||
https://<UI_HOST>/Blockchain-Viewer.html
|
||||
```
|
||||
|
||||
В приложении: `Настройки → Архив блокчейна`.
|
||||
|
||||
@@ -84,3 +84,30 @@ archive.publish.enabled=false
|
||||
```
|
||||
|
||||
Сервер должен запускаться без Arweave/root/client archive key files и не создавать `archive_publish_job`.
|
||||
|
||||
|
||||
## Проверка trusted importer
|
||||
|
||||
1. На принимающем сервере указать только тестовый publisher:
|
||||
|
||||
```properties
|
||||
archive.import.allowedPublishers=<publisher-login>
|
||||
```
|
||||
|
||||
2. Перезапустить сервер.
|
||||
3. Дождаться Solana PDA sync и цикла importer-а.
|
||||
4. Проверить, что у publisher в `solana_user_pda_current` после успешного цикла `archive_imported=true`, а `archive_last_imported_tx_id=archive_head_tx_id`.
|
||||
5. Проверить `archive_blockchain_location`.
|
||||
6. Для blockchain, которой локально не хватало блоков, убедиться, что `blockchain_state.last_block_number` вырос.
|
||||
7. Для уже существующих блоков importer должен пропускать совпадающий hash, а не создавать дубликат.
|
||||
8. Временно удалить publisher из whitelist и убедиться, что новые archive heads больше не скачиваются.
|
||||
|
||||
### Проверка Viewer
|
||||
|
||||
Открыть `Настройки → Архив блокчейна`, получить ссылку и проверить:
|
||||
|
||||
- `tx`, `offset`, `size`, `blockchain` присутствуют;
|
||||
- Viewer собирает несколько chunks по backlink;
|
||||
- неправильный `blockchain` в URL приводит к ошибке проверки;
|
||||
- `channel` открывает нужный канал;
|
||||
- `message` прокручивает к нужному block number.
|
||||
|
||||
@@ -1,60 +1,38 @@
|
||||
# Состав patch-пакета и удаление legacy-файлов
|
||||
# Состав текущего patch-пакета
|
||||
|
||||
ZIP `SHINE_archive_changed_files_with_docs.zip` предназначен для распаковки **поверх исходного дерева той версии сервера, из которой он был сделан**. Внутри находятся только новые и изменённые файлы, пути сохранены относительно корня репозитория.
|
||||
Этот этап рассчитан **поверх последнего рабочего ZIP**, присланного после успешного запуска archive publisher.
|
||||
|
||||
## Важное ограничение ZIP-overlay
|
||||
Пакет этого этапа добавляет:
|
||||
|
||||
Распаковка ZIP может добавить/заменить файлы, но не удалит старые. Поэтому после распаковки нужно удалить legacy test-free-avatar исходники ниже. Они больше не зарегистрированы в `JsonHandlerRegistry`, однако физическое удаление сохраняет дерево в точном состоянии новой версии и не оставляет старый тестовый Arweave-код рядом с production archive publisher.
|
||||
- trusted archive importer;
|
||||
- whitelist publisher-ов через настройки сервера;
|
||||
- строгую проверку больших `SHINE-ARCHIVE`;
|
||||
- импорт недостающих raw SHiNE blocks через обычный validator `AddBlock`;
|
||||
- локальные поля состояния импорта в `solana_user_pda_current` и таблицу `archive_blockchain_location`;
|
||||
- schema migration v23;
|
||||
- WS API `GetArchiveBlockchainLocation`;
|
||||
- экран `Настройки → Архив блокчейна`;
|
||||
- `shine-UI/Blockchain-Viewer.html`;
|
||||
- документацию importer/viewer.
|
||||
|
||||
## Удалить после распаковки
|
||||
## Удаления
|
||||
|
||||
```text
|
||||
SHiNE-server/shine-server-db/src/main/java/shine/db/dao/TestFreeAvatarUploadsDAO.java
|
||||
SHiNE-server/shine-server-db/src/main/java/shine/db/entities/TestFreeAvatarUploadEntry.java
|
||||
SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/Net_TestGetFreeAvatarQuota_Handler.java
|
||||
SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/Net_TestUploadFreeAvatar_Handler.java
|
||||
SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/TestFreeAvatarArweaveService.java
|
||||
SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/entyties/Net_TestGetFreeAvatarQuota_Request.java
|
||||
SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/entyties/Net_TestGetFreeAvatarQuota_Response.java
|
||||
SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/entyties/Net_TestUploadFreeAvatar_Request.java
|
||||
SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/entyties/Net_TestUploadFreeAvatar_Response.java
|
||||
docs/API/14_Test_Free_Avatar_Upload_API.md
|
||||
```
|
||||
В **этом** обновлении удалять файлы не требуется.
|
||||
|
||||
Linux-команда из корня репозитория:
|
||||
Старые test/free-avatar исходники, если они всё ещё физически присутствуют в рабочем дереве, этим patch-пакетом не затрагиваются. Они не относятся к trusted archive importer и не должны удаляться автоматически при наложении этого обновления.
|
||||
|
||||
```bash
|
||||
rm -f \
|
||||
'SHiNE-server/shine-server-db/src/main/java/shine/db/dao/TestFreeAvatarUploadsDAO.java' \
|
||||
'SHiNE-server/shine-server-db/src/main/java/shine/db/entities/TestFreeAvatarUploadEntry.java' \
|
||||
'SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/Net_TestGetFreeAvatarQuota_Handler.java' \
|
||||
'SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/Net_TestUploadFreeAvatar_Handler.java' \
|
||||
'SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/TestFreeAvatarArweaveService.java' \
|
||||
'SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/entyties/Net_TestGetFreeAvatarQuota_Request.java' \
|
||||
'SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/entyties/Net_TestGetFreeAvatarQuota_Response.java' \
|
||||
'SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/entyties/Net_TestUploadFreeAvatar_Request.java' \
|
||||
'SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/entyties/Net_TestUploadFreeAvatar_Response.java' \
|
||||
'docs/API/14_Test_Free_Avatar_Upload_API.md'
|
||||
```
|
||||
## Как накладывать ZIP changed-files
|
||||
|
||||
## Что пакет принципиально добавляет
|
||||
ZIP содержит только новые/изменённые файлы с путями от корня репозитория.
|
||||
|
||||
- новый Gradle module `shine-server-archive`;
|
||||
- migration/schema v22;
|
||||
- archive state DAO/entities;
|
||||
- server startup scheduler;
|
||||
- Arweave chunk uploader;
|
||||
- Solana User PDA writer;
|
||||
- PDA block type `100` в Rust/Java/JS;
|
||||
- обновлённую документацию формата User PDA;
|
||||
- отдельную папку `docs/Archive/` с полным protocol/deploy/runbook.
|
||||
Распаковать поверх той рабочей версии, из которой сделан пакет, с заменой совпадающих файлов.
|
||||
|
||||
## После overlay + удаления
|
||||
|
||||
Минимально проверить:
|
||||
После наложения:
|
||||
|
||||
```bash
|
||||
./gradlew shadowJar
|
||||
```
|
||||
|
||||
И отдельно собрать/задеплоить изменённую Solana `shine_users` согласно `03_DEPLOY_TEST_SERVER.md`.
|
||||
Если Gradle wrapper ещё не установлен локально, сначала обеспечить доступ к уже используемой версии Gradle/кэшу.
|
||||
|
||||
При старте сервер сам должен поднять schema с v22 до v23.
|
||||
|
||||
@@ -1,73 +1,50 @@
|
||||
# Manifest changed/new files
|
||||
|
||||
Основа сравнения: последний исходный ZIP пользователя, на который рассчитан этот пакет.
|
||||
Основа сравнения: последний присланный рабочий ZIP `3d14e34c-4249-4e11-8042-3f3349c8e9fd.zip`.
|
||||
|
||||
- Изменённых файлов: 20
|
||||
- Новых файлов до добавления этого manifest: 25
|
||||
- Удаляемых legacy-файлов: 10
|
||||
- Изменённых файлов: 19
|
||||
- Новых файлов: 14
|
||||
- Удаляемых файлов: 0
|
||||
|
||||
## Изменённые файлы
|
||||
|
||||
- `SHiNE-server/shine-server-config/src/main/java/utils/config/AppConfig.java`
|
||||
- `SHiNE-server/shine-server-archive/src/main/java/server/archive/ArchivePublisherService.java`
|
||||
- `SHiNE-server/shine-server-db/src/main/java/shine/db/DatabaseInitializer.java`
|
||||
- `SHiNE-server/shine-server-db/src/main/resources/postgres/schema_v1.sql`
|
||||
- `SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/JsonHandlerRegistry.java`
|
||||
- `SHiNE-server/shine-server-solana-users-sync/src/main/java/sync/codec/ShineUsersCodec.java`
|
||||
- `SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/blockchain/Net_AddBlock_Handler.java`
|
||||
- `SHiNE-server/shine-server-solana-users-sync/src/main/java/sync/storage/postgres/PostgresStorageRepository.java`
|
||||
- `SHiNE-server/src/main/java/server/ws/WsServer.java`
|
||||
- `SHiNE-server/src/main/resources/application.properties`
|
||||
- `build.gradle`
|
||||
- `docs/API/09_Operations_Index.md`
|
||||
- `docs/SHINE_ARCHIVE_PROTOCOL_v1.0_RU.md`
|
||||
- `docs/SHINE_ARCHIVE_PROTOCOL_v1.0_RU_FINAL.md`
|
||||
- `docs/Solana/user_pda/README.md`
|
||||
- `docs/Solana_Architecture/details/shine_users.md`
|
||||
- `settings.gradle`
|
||||
- `shine-UI/js/services/auth-service.js`
|
||||
- `shine-UI/js/services/shine-user-pda-service.js`
|
||||
- `shine-solana/shine/doc/formats/shine-user-pda-format-v.1.0.md`
|
||||
- `shine-solana/shine/doc/programs/shine_users.md`
|
||||
- `shine-solana/shine/programs/shine_users/src/lib.rs`
|
||||
|
||||
## Новые файлы
|
||||
|
||||
- `SHiNE-server/shine-server-archive/build.gradle`
|
||||
- `SHiNE-server/shine-server-archive/src/main/java/server/archive/ArchiveFileNames.java`
|
||||
- `SHiNE-server/shine-server-archive/src/main/java/server/archive/ArchiveKeyLoader.java`
|
||||
- `SHiNE-server/shine-server-archive/src/main/java/server/archive/ArchivePublisherConfig.java`
|
||||
- `SHiNE-server/shine-server-archive/src/main/java/server/archive/ArchivePublisherScheduler.java`
|
||||
- `SHiNE-server/shine-server-archive/src/main/java/server/archive/ArchivePublisherService.java`
|
||||
- `SHiNE-server/shine-server-archive/src/main/java/server/archive/ArweaveArchiveService.java`
|
||||
- `SHiNE-server/shine-server-archive/src/main/java/server/archive/ArweaveMerkle.java`
|
||||
- `SHiNE-server/shine-server-archive/src/main/java/server/archive/ShineArchiveWriter.java`
|
||||
- `SHiNE-server/shine-server-archive/src/main/java/server/archive/SolanaArchiveHeadWriter.java`
|
||||
- `SHiNE-server/shine-server-archive/src/test/java/server/archive/ArchiveFileNamesTest.java`
|
||||
- `SHiNE-server/shine-server-archive/src/test/java/server/archive/ShineArchiveWriterTest.java`
|
||||
- `SHiNE-server/shine-server-db/src/main/java/shine/db/archive/ArchiveBigBlockRef.java`
|
||||
- `SHiNE-server/shine-server-db/src/main/java/shine/db/archive/ArchiveChainCursor.java`
|
||||
- `SHiNE-server/shine-server-db/src/main/java/shine/db/archive/ArchivePublishJob.java`
|
||||
- `SHiNE-server/shine-server-db/src/main/java/shine/db/archive/ArchivePublishJobChain.java`
|
||||
- `SHiNE-server/shine-server-db/src/main/java/shine/db/dao/ArchivePublicationDAO.java`
|
||||
- `SHiNE-server/shine-server-db/src/main/resources/postgres/migration_v22.sql`
|
||||
- `docs/Archive/01_PROTOCOL_v1.0.md`
|
||||
- `docs/Archive/02_IMPLEMENTATION_MAP.md`
|
||||
- `docs/Archive/03_DEPLOY_TEST_SERVER.md`
|
||||
- `docs/Archive/04_TEST_AND_OPERATIONS.md`
|
||||
- `docs/Archive/05_PATCH_CONTENTS_AND_REMOVALS.md`
|
||||
- `docs/Archive/06_FILE_MANIFEST.md`
|
||||
- `docs/Archive/README.md`
|
||||
- `docs/Archive/archive-publisher.example.properties`
|
||||
- `shine-UI/js/app.js`
|
||||
- `shine-UI/js/pages/settings-view.js`
|
||||
- `shine-UI/js/services/auth-service.js`
|
||||
|
||||
## Legacy-файлы, которые ZIP сам не удаляет
|
||||
## Новые файлы
|
||||
|
||||
- `SHiNE-server/shine-server-db/src/main/java/shine/db/dao/TestFreeAvatarUploadsDAO.java`
|
||||
- `SHiNE-server/shine-server-db/src/main/java/shine/db/entities/TestFreeAvatarUploadEntry.java`
|
||||
- `SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/Net_TestGetFreeAvatarQuota_Handler.java`
|
||||
- `SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/Net_TestUploadFreeAvatar_Handler.java`
|
||||
- `SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/TestFreeAvatarArweaveService.java`
|
||||
- `SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/entyties/Net_TestGetFreeAvatarQuota_Request.java`
|
||||
- `SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/entyties/Net_TestGetFreeAvatarQuota_Response.java`
|
||||
- `SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/entyties/Net_TestUploadFreeAvatar_Request.java`
|
||||
- `SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/entyties/Net_TestUploadFreeAvatar_Response.java`
|
||||
- `docs/API/14_Test_Free_Avatar_Upload_API.md`
|
||||
- `SHiNE-server/shine-server-archive/src/main/java/server/archive/ArchiveImportConfig.java`
|
||||
- `SHiNE-server/shine-server-archive/src/main/java/server/archive/ArchiveImportScheduler.java`
|
||||
- `SHiNE-server/shine-server-archive/src/main/java/server/archive/ArchiveImportService.java`
|
||||
- `SHiNE-server/shine-server-archive/src/main/java/server/archive/ShineArchiveReader.java`
|
||||
- `SHiNE-server/shine-server-db/src/main/java/shine/db/archive/ArchiveBlockchainLocation.java`
|
||||
- `SHiNE-server/shine-server-db/src/main/java/shine/db/archive/ArchivePublisherHead.java`
|
||||
- `SHiNE-server/shine-server-db/src/main/java/shine/db/dao/ArchiveImportDAO.java`
|
||||
- `SHiNE-server/shine-server-db/src/main/resources/postgres/migration_v23.sql`
|
||||
- `SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/blockchain/Net_GetArchiveBlockchainLocation_Handler.java`
|
||||
- `SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/blockchain/entyties/Net_GetArchiveBlockchainLocation_Request.java`
|
||||
- `SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/blockchain/entyties/Net_GetArchiveBlockchainLocation_Response.java`
|
||||
- `docs/Archive/07_ARCHIVE_IMPORT_AND_VIEWER.md`
|
||||
- `shine-UI/Blockchain-Viewer.html`
|
||||
- `shine-UI/js/pages/blockchain-archive-view.js`
|
||||
|
||||
Подробная команда удаления находится в `05_PATCH_CONTENTS_AND_REMOVALS.md`.
|
||||
## Удаления
|
||||
|
||||
На этом этапе файлов для удаления нет.
|
||||
|
||||
@@ -0,0 +1,303 @@
|
||||
# Импорт доверенных SHINE-ARCHIVE и Blockchain Viewer
|
||||
|
||||
Этот документ описывает вторую половину архивной системы: как обычный SHiNE-сервер узнаёт о новых archive head других серверов, кому доверяет, как импортирует недостающие SHiNE-блоки и как UI получает ссылку на историю конкретной `blockchain_name`.
|
||||
|
||||
## 1. Источник archive head
|
||||
|
||||
Archive importer **не делает отдельные Solana RPC-запросы**.
|
||||
|
||||
Уже существующий Solana Users Sync разбирает User PDA block type `100` и копирует его в локальную таблицу:
|
||||
|
||||
```text
|
||||
solana_user_pda_current.archive_head_tx_id
|
||||
solana_user_pda_current.archive_head_hash
|
||||
```
|
||||
|
||||
Для локального состояния importer v23 добавляет туда же:
|
||||
|
||||
```text
|
||||
archive_imported BOOLEAN
|
||||
archive_last_imported_tx_id TEXT
|
||||
```
|
||||
|
||||
Это локальные поля сервера, в Solana они не записываются.
|
||||
|
||||
Когда обычный Solana Users Sync видит тот же archive head повторно, `archive_imported` сохраняется как есть.
|
||||
|
||||
Когда `archive_head_tx_id` или `archive_head_hash` изменился:
|
||||
|
||||
```text
|
||||
archive_imported = false
|
||||
```
|
||||
|
||||
а `archive_last_imported_tx_id` сохраняет последнюю успешно обработанную точку и позволяет продолжить после сбоя.
|
||||
|
||||
## 2. Whitelist доверенных publisher-ов
|
||||
|
||||
В `application.properties` задаётся список логинов серверов, архивы которых разрешено принимать:
|
||||
|
||||
```properties
|
||||
archive.import.allowedPublishers=archive-server-1,archive-server-2
|
||||
archive.import.intervalMinutes=60
|
||||
archive.import.workDir=data/archive-import
|
||||
```
|
||||
|
||||
Правила:
|
||||
|
||||
- логины разделяются запятыми;
|
||||
- сравнение без учёта регистра;
|
||||
- пустое `archive.import.allowedPublishers=` полностью выключает importer;
|
||||
- принимаются только строки `solana_user_pda_current` с `is_server=true`;
|
||||
- whitelist является только первым фильтром, криптографические проверки всё равно обязательны.
|
||||
|
||||
## 3. Периодическая проверка
|
||||
|
||||
После запуска сервера importer делает первую проверку примерно через 10 секунд, затем по умолчанию раз в 60 минут.
|
||||
|
||||
Каждый цикл — дешёвый запрос только к локальной PostgreSQL:
|
||||
|
||||
```text
|
||||
approved publisher
|
||||
AND is_server=true
|
||||
AND archive_head_tx_id != ''
|
||||
AND archive_imported=false
|
||||
```
|
||||
|
||||
Если таких строк нет, Arweave не вызывается.
|
||||
|
||||
## 4. Проверки archive block
|
||||
|
||||
Для каждого pending publisher сервер проверяет:
|
||||
|
||||
1. publisher находится в whitelist;
|
||||
2. `archive_head_tx_id/archive_head_hash` уже пришли через обычный User PDA sync;
|
||||
3. SHA-256 скачанного файла совпадает с `archive_head_hash`;
|
||||
4. `creator_login == closer_login == publisher login`;
|
||||
5. Ed25519 archive signature проверяется root key publisher-а из User PDA;
|
||||
6. каждый вложенный raw SHiNE block проходит обычную SHiNE-проверку через существующий `AddBlock` path.
|
||||
|
||||
Подпись большого архива защищает контейнер и навигацию, а подписи обычных SHiNE blocks защищают сами пользовательские данные.
|
||||
|
||||
## 5. Как определяется, что head новый
|
||||
|
||||
Отдельная таблица обработанных TX для основной логики не нужна.
|
||||
|
||||
Текущий User PDA snapshot уже содержит:
|
||||
|
||||
```text
|
||||
archive_head_tx_id
|
||||
archive_head_hash
|
||||
archive_imported
|
||||
archive_last_imported_tx_id
|
||||
```
|
||||
|
||||
Пример:
|
||||
|
||||
```text
|
||||
archive_head_tx_id = TX100
|
||||
archive_imported = false
|
||||
archive_last_imported_tx_id = TX97
|
||||
```
|
||||
|
||||
Это означает: Solana уже объявила `TX100` текущей головой publisher-а, но локальный сервер успел импортировать только до `TX97`.
|
||||
|
||||
После полной успешной обработки `TX100`:
|
||||
|
||||
```text
|
||||
archive_imported = true
|
||||
archive_last_imported_tx_id = TX100
|
||||
```
|
||||
|
||||
При следующем новом PDA head Users Sync сам сбросит `archive_imported=false`.
|
||||
|
||||
## 6. Догон пропущенных больших блоков
|
||||
|
||||
Если сервер был выключен и вместо `TX97` сразу увидел `TX100`, он скачивает и проверяет `TX100`, читает его FULL reference table и находит `TX97`.
|
||||
|
||||
После этого импортирует только:
|
||||
|
||||
```text
|
||||
TX98
|
||||
TX99
|
||||
TX100
|
||||
```
|
||||
|
||||
После каждого полностью импортированного большого блока `archive_last_imported_tx_id` сдвигается вперёд.
|
||||
|
||||
Если сервер впервые видит publisher и `archive_last_imported_tx_id` пустой, импортируются все previous refs от старых к новым, затем текущий head.
|
||||
|
||||
Если непустой `archive_last_imported_tx_id` отсутствует в FULL history текущего head, importer останавливается: это рассматривается как возможная смена/fork archive chain, а не как повод молча забыть старый cursor.
|
||||
|
||||
## 7. Crash recovery
|
||||
|
||||
Если процесс упал после `TX98`, но до `TX100`:
|
||||
|
||||
```text
|
||||
archive_imported = false
|
||||
archive_last_imported_tx_id = TX98
|
||||
```
|
||||
|
||||
Следующий часовой цикл продолжит с `TX99`.
|
||||
|
||||
Если процесс успел импортировать head и записать `archive_last_imported_tx_id = TX100`, но упал до установки `archive_imported=true`, следующий цикл просто завершит отметку без повторной загрузки всей цепочки.
|
||||
|
||||
Все cursor updates выполняются условно по ожидаемому `archive_head_tx_id`. Если обычный Solana Users Sync успел заменить head во время импорта, старый процесс не сможет пометить новый head импортированным.
|
||||
|
||||
## 8. Импорт `UserBlockchainChunk`
|
||||
|
||||
Для каждого chunk:
|
||||
|
||||
1. берётся lock этой `blockchain_name`;
|
||||
2. если локального `blockchain_state` нет, identity создаётся по синхронизированному User PDA;
|
||||
3. raw records разбираются как обычные `BchBlockEntry`;
|
||||
4. уже существующий block допускается только при совпадении hash;
|
||||
5. новый block должен идти строго `localLast + 1`;
|
||||
6. новый block добавляется существующим validator/write path;
|
||||
7. конфликт hash или gap останавливает импорт этой archive chain.
|
||||
|
||||
## 9. Индекс последнего archive chunk
|
||||
|
||||
Таблица:
|
||||
|
||||
```text
|
||||
archive_blockchain_location
|
||||
```
|
||||
|
||||
содержит для каждой `blockchain_name`:
|
||||
|
||||
```text
|
||||
blockchain_name
|
||||
publisher_login
|
||||
arweave_tx_id
|
||||
archive_hash
|
||||
big_block_number
|
||||
chunk_offset
|
||||
chunk_size
|
||||
source_last_block_number
|
||||
updated_at_ms
|
||||
```
|
||||
|
||||
Если blockchain встретилась в новом archive block, её location обновляется. Если не встретилась — старая ссылка остаётся.
|
||||
|
||||
Эту таблицу заполняют как trusted importer, так и локальный archive publisher.
|
||||
|
||||
## 10. API для UI
|
||||
|
||||
WS operation:
|
||||
|
||||
```text
|
||||
GetArchiveBlockchainLocation
|
||||
```
|
||||
|
||||
Request:
|
||||
|
||||
```json
|
||||
{
|
||||
"op": "GetArchiveBlockchainLocation",
|
||||
"blockchainName": "alice-001"
|
||||
}
|
||||
```
|
||||
|
||||
Response содержит:
|
||||
|
||||
```text
|
||||
blockchainName
|
||||
publisherLogin
|
||||
arweaveTxId
|
||||
archiveHash
|
||||
bigBlockNumber
|
||||
chunkOffset
|
||||
chunkSize
|
||||
sourceLastBlockNumber
|
||||
```
|
||||
|
||||
## 11. UI и ссылка Viewer
|
||||
|
||||
В настройках пользователя есть экран `Архив блокчейна`.
|
||||
|
||||
Viewer-файл:
|
||||
|
||||
```text
|
||||
shine-UI/Blockchain-Viewer.html
|
||||
```
|
||||
|
||||
Основные параметры ссылки:
|
||||
|
||||
```text
|
||||
/Blockchain-Viewer.html
|
||||
?tx=<ARWEAVE_TX_ID>
|
||||
&offset=<CHUNK_OFFSET>
|
||||
&size=<CHUNK_SIZE>
|
||||
&blockchain=<BLOCKCHAIN_NAME>
|
||||
```
|
||||
|
||||
Дополнительно:
|
||||
|
||||
```text
|
||||
&channel=<CHANNEL_NAME>
|
||||
&message=<BLOCK_NUMBER>
|
||||
```
|
||||
|
||||
`blockchain` используется также для проверки: если загруженный chunk имеет другое имя blockchain, Viewer прекращает обработку.
|
||||
|
||||
`channel` открывает нужный канал, а `message` прокручивает к указанному сообщению/block number и выделяет его.
|
||||
|
||||
## 12. Как Viewer собирает всю цепочку
|
||||
|
||||
Viewer начинает с последнего `TX + offset + size`:
|
||||
|
||||
```text
|
||||
последний UserBlockchainChunk
|
||||
↓
|
||||
PreviousBlockchainChunkRef
|
||||
↓
|
||||
FULL reference table текущего big block
|
||||
↓
|
||||
TX предыдущего big block
|
||||
↓
|
||||
Range предыдущего chunk
|
||||
↓
|
||||
следующий backlink
|
||||
↓
|
||||
до NO_REFERENCE
|
||||
```
|
||||
|
||||
Чужие chunks скачивать не требуется.
|
||||
|
||||
## 13. Минимальная настройка принимающего сервера
|
||||
|
||||
```properties
|
||||
archive.publish.enabled=false
|
||||
archive.import.allowedPublishers=server-a,server-b
|
||||
archive.import.intervalMinutes=60
|
||||
archive.import.workDir=data/archive-import
|
||||
```
|
||||
|
||||
Если импорт архивов не нужен:
|
||||
|
||||
```properties
|
||||
archive.import.allowedPublishers=
|
||||
```
|
||||
|
||||
Тогда importer вообще не запускается.
|
||||
|
||||
## 14. Диагностика PostgreSQL
|
||||
|
||||
Pending archive heads:
|
||||
|
||||
```sql
|
||||
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;
|
||||
```
|
||||
|
||||
Последние известные пользовательские chunks:
|
||||
|
||||
```sql
|
||||
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;
|
||||
```
|
||||
+15
-1
@@ -9,7 +9,8 @@
|
||||
3. `03_DEPLOY_TEST_SERVER.md` — полный порядок установки на тестовый сервер, включая обязательный апгрейд `shine_users`, конфиг, ключи, сборку и запуск.
|
||||
4. `04_TEST_AND_OPERATIONS.md` — что проверять до полуночи, после полуночи и при сбоях.
|
||||
5. `05_PATCH_CONTENTS_AND_REMOVALS.md` — какие файлы содержит пакет и какие legacy test-free-avatar файлы нужно удалить при наложении ZIP поверх старого исходника.
|
||||
6. `archive-publisher.example.properties` — минимальный конфиг архиватора.
|
||||
6. `07_ARCHIVE_IMPORT_AND_VIEWER.md` — whitelist доверенных publisher-ов, импорт archive chain, индекс последнего chunk, UI и `Blockchain-Viewer.html`.
|
||||
7. `archive-publisher.example.properties` — пример конфигурации publisher + importer.
|
||||
|
||||
## Коротко
|
||||
|
||||
@@ -26,3 +27,16 @@
|
||||
## Важно перед тестом
|
||||
|
||||
Изменён формат/парсер `shine_users`. **Нельзя просто заменить серверный JAR и включить archive publisher, если целевая Solana-программа `shine_users` ещё не обновлена кодом из этого пакета.** Сначала обновить программу на нужном кластере, затем сервер.
|
||||
|
||||
|
||||
## Импорт архивов других серверов
|
||||
|
||||
Импорт по умолчанию также выключен. Настройка:
|
||||
|
||||
```properties
|
||||
archive.import.allowedPublishers=
|
||||
```
|
||||
|
||||
Пустой список означает: не доверять архивам ни одного внешнего сервера. Для разрешения перечислить логины через запятую. Подробности — `07_ARCHIVE_IMPORT_AND_VIEWER.md`.
|
||||
|
||||
Текущая схема БД: **v23**. `v22` добавила publisher, `v23` добавляет локальные `archive_imported/archive_last_imported_tx_id`, trusted importer и универсальный `archive_blockchain_location`.
|
||||
|
||||
@@ -21,3 +21,13 @@ archive.solana.clientKeyPath=/home/player/SHiNE/secrets/server-client.key
|
||||
archive.solana.confirmPollSeconds=5
|
||||
archive.solana.confirmTimeoutMinutes=30
|
||||
archive.solana.commitment=finalized
|
||||
|
||||
|
||||
# =============================================================
|
||||
# Trusted archive import (independent from publisher)
|
||||
# Empty = do not import archives from any external server.
|
||||
# Comma-separated SHiNE server logins, case-insensitive.
|
||||
# =============================================================
|
||||
archive.import.allowedPublishers=
|
||||
archive.import.intervalMinutes=60
|
||||
archive.import.workDir=data/archive-import
|
||||
|
||||
Reference in New Issue
Block a user