145 lines
4.7 KiB
Markdown
145 lines
4.7 KiB
Markdown
# 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 запрещено.
|