SHA256
Перенести документацию в docs и добавить социальный граф
This commit is contained in:
@@ -0,0 +1 @@
|
||||
Данная документация местами устарела и не соответствует реальному коду
|
||||
@@ -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-модели строк таблиц (без логики, только поля/геттеры/сеттеры + иногда удобные методы вроде getClientKeyByte()).
|
||||
shine.db.dao.* — DAO по таблицам: ActiveSessionsDAO, SolanaUsersDAO, UserParamsDAO, IpGeoCacheDAO, BlockchainStateDAO, BlocksDAO; плюс “сервисные” DAO:
|
||||
|
||||
UserCreateDAO — атомарная регистрация пользователя в транзакции (BEGIN IMMEDIATE + rollback/commit).
|
||||
// Временное решение позволяющее регистрировать новых пользователей
|
||||
// атомарно и добавляет запись и в solana_users и в BlockchainState
|
||||
|
||||
@@ -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 целевого блока
|
||||
👉 Это механизм межблокчейн-связей без изменения чужих цепочек.
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
shine-server-config
|
||||
|
||||
Минимальная библиотека конфигурации, предоставляющая потокобезопасный singleton-доступ к параметрам из application.properties.
|
||||
|
||||
Настройки:
|
||||
server.port=7070 — порт запуска сервера
|
||||
db.path=data/shine.sqlite — путь к SQLite базе данных
|
||||
@@ -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(),
|
||||
@@ -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 текущей машины
|
||||
@@ -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)
|
||||
@@ -0,0 +1,52 @@
|
||||
shine-server-protocol
|
||||
Библиотека JSON-протокол поверх WebSocket для взаимодействия с клиентами.
|
||||
|
||||
|
||||
|
||||
Всё общение — JSON поверх WebSocket
|
||||
Формат всегда один:
|
||||
|
||||
request: op + requestId + payload
|
||||
response: op + requestId + status + payload
|
||||
|
||||
|
||||
Net_Event / Net_Request / Net_Response
|
||||
Базовые классы протокола.
|
||||
requestId связывает запрос и ответ, status = результат.
|
||||
|
||||
Хэндлер = логика операции
|
||||
Каждый op обрабатывается своим JsonMessageHandler.
|
||||
|
||||
Entities (Request / Response)
|
||||
DTO-классы для Jackson:
|
||||
|
||||
Net_Xxx_Request — что приходит от клиента
|
||||
|
||||
Net_Xxx_Response — что уходит клиенту
|
||||
|
||||
JsonHandlerRegistry
|
||||
Связывает:
|
||||
|
||||
op → RequestClass
|
||||
op → Handler
|
||||
|
||||
|
||||
JsonInboundProcessor
|
||||
Единая точка входа:
|
||||
парсит JSON → маппит payload → вызывает handler → собирает ответ JSON.
|
||||
|
||||
Папки по темам
|
||||
|
||||
auth/ — авторизация и сессии
|
||||
(AuthChallenge → CreateAuthSession → Refresh / List / Close)
|
||||
|
||||
blockchain/ — AddBlock
|
||||
|
||||
tempToTest/ — AddUser (временный, потом уйдёт в блокчейн-логику)
|
||||
|
||||
ConnectionContext
|
||||
Состояние одного WebSocket-подключения (login, session, authStatus).
|
||||
|
||||
ActiveConnectionsRegistry
|
||||
Глобальный реестр активных авторизованных соединений
|
||||
(нужно для закрытия других сессий).
|
||||
Reference in New Issue
Block a user