Сделал что бы запускалось. Поправил мелкие ошибки
This commit is contained in:
AidarKC
2025-12-31 21:10:05 +03:00
parent 62ea49d1fc
commit f17d077f25
56 changed files with 424 additions and 873 deletions
+17
View File
@@ -0,0 +1,17 @@
shine-server-bd — это библиотека реалезующая всю работу с БД:
хранит пользователей/сессии/параметры/кэш IP→гео и данные блокчейна (состояние + блоки), предоставляя единый SqliteDbController для соединений, набор DAO под каждую таблицу (Singleton, методы с Connection для транзакций и без Connection — сами открывают/закрывают), и простые entity-модели как контейнеры данных для маппинга ResultSet↔Java.
Логика структуры классов (в двух словах):
shine.db.SqliteDbController — один вход в БД: читает db.path, при отсутствии файла создаёт БД, выдаёт новые Connection и настраивает PRAGMA.
shine.db.DatabaseInitializer — разовая сборка схемы (таблицы + индексы).
shine.db.entities.* — POJO-модели строк таблиц (без логики, только поля/геттеры/сеттеры + иногда удобные методы вроде getDeviceKeyByte()).
shine.db.dao.* — DAO по таблицам: ActiveSessionsDAO, SolanaUsersDAO, UserParamsDAO, IpGeoCacheDAO, BlockchainStateDAO, BlocksDAO; плюс “сервисные” DAO:
UserCreateDAO — атомарная регистрация пользователя в транзакции (BEGIN IMMEDIATE + rollback/commit).
// Временное решение позволяющее регистрировать новых пользователей
// атомарно и добавляет запись и в solana_users и в BlockchainState
+85
View File
@@ -0,0 +1,85 @@
shine-server-blockchain — это библиотека, которая задаёт формат блока, правила парсинга/валидации тела, крипто-проверку (hash+Ed25519) и безопасную работу с файлами блокчейна (data/<name>.bch через временный .tmp_bch).
Как устроена структура и логика работы
1) “Блок” как центральный объект (ядро)
BchBlockEntry — единая модель блока “как лежит на диске/в сети”:
читает/собирает байты в формате RAW + signature64 + hash32
сразу парсит body через BodyRecordParser
сразу проверяет что lineIndex совпадает с тем, что ожидает конкретный тип body (expectedLineIndex())
То есть: всё, что считается “блоком”, обязано быть самодостаточно валидным уже на этапе создания объекта.
2) “Body” как плагины по типам (расширяемая часть) ! <-- Новые типы записей добавлть сюда !
BodyRecord — интерфейс контракта для всех тел:
type/version — идентификаторы формата
expectedLineIndex() — жёсткое правило “в какой линии может жить”
check() — логическая валидация содержимого
toBytes() — сериализация обратно в бинарь
BodyRecordParser — диспетчер: читает первые 4 байта (type+ver) и выбирает нужный класс:
HeaderBody (lineIndex=0)
TextBody (lineIndex=1)
ReactionBody (lineIndex=2)
Добавление нового типа = добавить новый класс XxxBody + кейс в BodyRecordParser.
3) Криптография как отдельный слой проверки
BchCryptoVerifier отвечает за “как получить хэш и как проверить подпись”:
строит preimage = "SHiNE" + login + prevGlobalHash32 + prevLineHash32 + rawBytes
считает sha256(preimage) и сравнивает с hash32 внутри блока
проверяет Ed25519 подпись над hash32
Важно: BchBlockEntry не проверяет подпись — он проверяет структуру блока и правильность body/lineIndex, а криптопроверка вынесена отдельно.
4) Утилиты вокруг имени и файлов
BlockchainNameUtil — извлекает login из blockchainName (отрезает 3 символа суффикса).
FileStoreUtil — безопасное файловое хранилище:
5) Объяснение структуры работы
Типичный сценарий: пришёл блок → проверить → принять
Шаг 0. Контекст (что у нас уже есть снаружи)
Снаружи библиотеки (в сервере) у тебя уже известны:
userLogin — владелец блокчейна
publicKey32 — публичный ключ пользователя
prevGlobalHash32 — хэш предыдущего блока по глобальной цепи
prevLineHash32 — хэш предыдущего блока по текущей линии
Библиотека не хранит это сама, она ожидает, что сервер это передаст.
Шаг 1. Парсинг блока (структура + логика)
BchBlockEntry block = new BchBlockEntry(fullBytes);
Что происходит здесь автоматически:
проверяется длина блока
проверяется recordSize
парсится RAW-заголовок
парсится body через BodyRecordParser
проверяется, что lineIndex соответствует типу body
(HEADER → line 0, TEXT → line 1, REACTION → line 2 и т.д.)
❗ На этом шаге никакой криптографии ещё нет — только структура и логика формата.
Если тут не упало исключение → блок структурно корректен.
Шаг 2. Подготовка данных для криптопроверки (они получаются просто из частей байтов полного блокас подписью)
byte[] rawBytes = block.getRawBytes();
byte[] signature64 = block.getSignature64();
byte[] hash32FromTail = block.getHash32();
Важно:
rawBytes — это ровно те байты, которые участвовали в хэшировании
hash32FromTail — это то, что автор блока положил внутрь блока
Шаг 3. Криптографическая проверка (ключевой вызов)
boolean ok = BchCryptoVerifier.verifyAll(
userLogin,
prevGlobalHash32,
prevLineHash32,
rawBytes,
signature64,
publicKey32,
hash32FromTail
);
@@ -0,0 +1,48 @@
Общая структура блока
Блок — это бинарная запись фиксированного формата:
[ RAW ][ signature64 ][ hash32 ]
RAW — данные блока (участвуют в хэшировании и подписи)
signature64 — Ed25519-подпись над hash32
hash32 — SHA-256 от preimage (привязан к цепочке и владельцу)
RAW-часть (BigEndian)
recordSize int32 — размер RAW (без signature+hash)
recordNumber int32 — глобальный номер блока
timestamp int64 — unix time (seconds)
lineIndex int16 — индекс линии
lineNumber int32 — номер блока внутри линии
bodyBytes bytes — тело блока (type+version+payload)
Общая структура блокчейна
Блокчейн — это:
линейная цепочка блоков (по recordNumber)
внутри неё — параллельные логические линии (lineIndex)
каждая линия имеет собственную нумерацию (lineNumber) и prevLineHash
вся цепочка связана ещё и prevGlobalHash
👉 Таким образом, каждый блок:
связан с предыдущим глобальным блоком
и с предыдущим блоком своей линии
Это даёт:
строгий порядок всей истории
и независимую валидацию логических потоков
Криптографический смысл блока
Хэш блока считается от:
"SHiNE" +
login +
prevGlobalHash32 +
prevLineHash32 +
RAW
Это означает:
блок жёстко привязан к владельцу (login)
блок невозможно перенести в другую цепочку
подмена предыдущего блока ломает всю цепь
Подпись Ed25519 делается над этим хэшем.
@@ -0,0 +1,36 @@
Формат и смысл существующих Body
1) HeaderBody (type=0, ver=1)
Линия: lineIndex = 0
Смысл:
Генезис-блок блокчейна, объявляет формат и владельца.
Содержит:
сигнатуру формата "SHiNE"
login владельца блокчейна
👉 Всегда первый блок, всегда в линии 0.
2) TextBody (type=1, ver=1)
Линия: lineIndex = 1
Смысл:
Основной контент — текстовые записи (посты, сообщения, дневник).
Содержит:
UTF-8 текст произвольной длины
👉 Это “основная история” блокчейна пользователя.
3) ReactionBody (type=2, ver=1)
Линия: lineIndex = 2
Смысл:
Связь с другим блокчейном или блоком (реакция, ответ, лайк, ссылка).
Содержит:
код реакции
имя целевого блокчейна
globalNumber целевого блока
hash32 целевого блока
👉 Это механизм межблокчейн-связей без изменения чужих цепочек.
+7
View File
@@ -0,0 +1,7 @@
shine-server-config
Минимальная библиотека конфигурации, предоставляющая потокобезопасный singleton-доступ к параметрам из application.properties.
Настройки:
server.port=7070 — порт запуска сервера
db.path=data/shine.sqlite — путь к SQLite базе данных
+8
View File
@@ -0,0 +1,8 @@
shine-server-crypto
О чём: базовые крипто-утилиты для SHA-256 и Ed25519 (BouncyCastle) + проверка подписи/хэша для .bch сущностей и маленький self-test.
Внешние методы, которые вызываются:
BchCryptoVerifier.verifyAll(), BchCryptoVerifier.buildPreimage(), Ed25519Util.generatePrivateKey(), Ed25519Util.generatePrivateKeyFromString(), Ed25519Util.derivePublicKey(), Ed25519Util.sign(), Ed25519Util.verify(), Ed25519Util.keyToBase64(), Ed25519Util.keyFromBase64(),
HashSHA256Util.sha256()
HashSHA256Util.loginToLoginId(), HashSHA256Util.loginIdFromLogin(),
+19
View File
@@ -0,0 +1,19 @@
shine-server-geo
Назначение: утилиты для получения “кто подключился” (IP/UA/язык) и геолокации по IP (с опциональным кэшем в БД).
Классы:
ClientInfoService — собирает строку UA/ch-ua/platform/mobile/remoteIP, вытаскивает реальный IP (приоритет: X-Forwarded-For → X-Real-IP → remoteAddress), парсит первый Accept-Language.
GeoLookupService — геолокация по IP через внешний API (ip-api.com), умеет вариант без кэша и с кэшем в таблице ip_geo_cache через IpGeoCacheDAO (пишет даже unknown), плюс метод получения внешнего IP через api.ipify.org.
GeoLookupTestMain — консольный тест: берёт IP из аргумента или определяет внешний, вызывает геолокацию и печатает результат + время.
Внешние (публично используемые) методы:
ClientInfoService.buildClientInfoString(Session) — формирует строку с User-Agent, client-hints и реальным IP клиента
ClientInfoService.extractClientIp(Session) — извлекает реальный IP (X-Forwarded-For / X-Real-IP / remoteAddress)
ClientInfoService.extractPreferredLanguageTag(Session) — возвращает основной язык клиента из Accept-Language
GeoLookupService.resolveCountryCityOrIp(String ip) — геолокация по IP без кэша (Country, City или unknown)
GeoLookupService.resolveCountryCityOrIpWithCache(String ip) — геолокация по IP с кэшированием в БД
GeoLookupService.fetchPublicIpOrDefault(String fallbackIp) — получение внешнего IP текущей машины
+10
View File
@@ -0,0 +1,10 @@
shine-log (BlockchainAdminNotifier)
Суть (1 предложение): единая точка для “красного” оповещения админа о критических проблемах консистентности, сейчас — через максимально заметный log.error, позже — через Telegram/email/webhook и т.п.
Структура (очень кратко):
BlockchainAdminNotifier (final utility)
BlockchainAdminNotifier.critical(String message)
BlockchainAdminNotifier.critical(String message, Throwable t)