# SHiNE User PDA v1.0 ## 1. Назначение `SHiNE User PDA v1.0` — бинарный формат пользовательской записи в PDA Solana. Хранит: - логин; - ключи пользователя; - номер внутренней сети; - лимит (баланс); - серверные данные (опционально); - список серверов подключения; - данные восстановления; - связь с предыдущей версией через `prev_hash`; - подпись владельца `root_key`. Размер PDA фиксированный: `768 bytes` Полезная длина записи указывается в `record_len`. ## 2. Общие правила кодирования - Числа: `little-endian`. - Строки: `UTF-8` с префиксом длины `u8`. - Padding до 768 байт: нули `0x00`. - Padding не входит в `record_len`. ## 3. Структура записи - `magic` (5): `"SHiNE"` - `format_major` (1): `1` - `format_minor` (1): `0` - `record_len` (2): длина от `magic` до `signature` включительно - `created_at_ms` (8) - `updated_at_ms` (8) - `version` (4) - `prev_hash` (32) - `login_len` (1) - `login` (N) - `root_key` (32) - `blockchain_key` (32) - `device_key` (32) - `chain_number` (2) - `balance` (8) - `is_server` (1) - если `is_server=1`: - `server_key` (32) - `server_address_len` (1) - `server_address` (N) - `connection_servers_count` (1) - повтор `count` раз: - `server_login_len` (1) - `server_login` (N) - `trusted_count` (1) - `reserved` (5) = `0x00 0x00 0x00 0x00 0x00` - `signature` (64) - `padding` до 768 ## 4. Подпись (v1.0) В `v1.0` подписывается не сырой блок полей напрямую, а его SHA-256. 1. Формируется `unsigned_bytes`: - все поля от `magic` до `reserved` включительно; - поле `signature` не включается; - padding не включается. 2. Считается `msg_hash = SHA-256(unsigned_bytes)`. 3. `signature = Ed25519.sign(root_private_key, msg_hash)`. 4. Проверка: - `Ed25519.verify(root_key, msg_hash, signature)`. ## 5. Что входит в `prev_hash` Для связи версий: - `prev_hash = SHA-256(previous_unsigned_bytes)` Где `previous_unsigned_bytes` — предыдущая версия записи от `magic` до `reserved` включительно, без `signature` и без padding. Для первой версии: - `prev_hash = 32` нулевых байта. ## 6. Правила create/update в текущей реализации ### Create - PDA: seed `["login=", login]`. - Создаётся запись версии `0`. - `updated_at_ms = created_at_ms`. - Стартовый лимит: - `START_BONUS_LIMIT + additional_limit`. - Оплата: - регистрационная комиссия; - пополнение `additional_limit` по курсу; - рента PDA (плательщик транзакции). ### Update - Проверка подписи новой записи по `root_key`. - Проверка: - `magic`, `format_major`, `format_minor`; - корректного `record_len`; - `prev_hash` на соответствие предыдущей версии; - `version = old_version + 1`; - неизменяемых полей: `login`, `created_at_ms`, `root_key`. - `balance` не уменьшается: - `new_balance = old_balance + additional_limit`. - При `additional_limit > 0` берётся комиссия пополнения. ## 7. Параметры экономики/размера (settings) См. `programs/shine_users/src/settings.rs`: - `USER_PDA_SPACE = 768` - `REGISTRATION_FEE_RECEIVER` - `REGISTRATION_FEE_LAMPORTS` - `LIMIT_STEP` - `LAMPORTS_PER_LIMIT_STEP` - `START_BONUS_LIMIT` ## 8. Root Key Rotation (пока не включено) В `v1.0` `root_key` неизменяем. Варианты расширения: 1. **Dual-signature rotate tx**: - отдельный флаг операции rotate; - запись подписывается и старым, и новым root key; - контракт проверяет обе подписи. 2. **Two-step commit/confirm**: - шаг 1: proposal смены root (`old root` подпись); - шаг 2: confirm (`new root` подпись) в отдельной tx. 3. **Recovery guardians**: - отдельная PDA для доверенных лиц; - пороговая схема (например `m-of-n`) для восстановления root. Для v1.0 решение отложено, но изменение root_key в update запрещено.