7.9 KiB
Solana user_pda: формат 1.2
Актуальный бинарный формат пользовательской PDA программы shine_users.
Формат пользовательских SHiNE-блоков и Arweave этим изменением не меняется.
Назначение
PDA 1.2 хранит идентичность и authority пользователя, append-only историю blockchain keys, оплаченный лимит и маршрутизацию. Состояние вершины пользовательского blockchain в Solana больше не хранится.
Из PDA 1.2 удалены RecoveryKeyBlock, SessionsBlock, TrustedStateBlock, ArchiveHeadBlock, sync_servers[], а также старые used_bytes, last_block_*, arweave_tx_id, blockchain_name/type.
Общие правила кодирования
- Little Endian;
Pubkey— 32 байта;- Ed25519 signature — 64 байта;
- hash — 32 байта;
- строка —
len:u8 + UTF-8 bytes; block_type:u8 + block_version:u8есть у каждого typed block;- фиксированные
RootKeyBlockиClientKeyBlockне содержат длину; - любой variable block:
block_type:u8 + block_version:u8 + payload_len:u16 + payload; - неизвестный variable block можно пропустить по
payload_len.
Все известные блоки PDA 1.2 имеют block_version = 0.
Header
magic: [u8;5] = "SHiNE"
format_major: u8 = 1
format_minor: u8 = 2
record_len: u16
created_at_ms: u64
updated_at_ms: u64
record_number: u32
prev_record_hash: [u8;32]
login_len: u8
login: [u8;login_len]
blocks_count: u8
blocks: TypedBlock[blocks_count]
signature: [u8;64]
record_len включает подпись и не включает padding Solana account.
record_number=0 на create и увеличивается программой на 1 после каждого успешного update.
prev_record_hash=0 на create; при update это hash unsigned-части предыдущей PDA.
Типы блоков
| type | блок | статус |
|---|---|---|
| 1 | RootKeyBlock |
обязательный |
| 2 | ClientKeyBlock |
обязательный |
| 3 | BlockchainRegistryBlock |
обязательный |
| 30 | ServerProfileBlock |
опциональный |
| 40 | AccessServersBlock |
опциональный |
RootKeyBlock
block_type: u8 = 1
block_version: u8 = 0
root_key: [u8;32]
root_key — холодный recovery authority. Blockchain authority не может изменить root. Root authority может изменить root и остальные поля.
ClientKeyBlock
block_type: u8 = 2
block_version: u8 = 0
client_key: [u8;32]
Client key не является authority PDA. Он может использоваться клиентским уровнем и как fee payer Solana-транзакции.
BlockchainRegistryBlock
block_type: u8 = 3
block_version: u8 = 0
payload_len: u16
fork_count: u16
forks[fork_count]:
blockchain_key: [u8;32]
created_at_ms: u64
paid_limit_bytes: u32
Одна fork-запись занимает 44 байта.
Правила:
fork_count >= 1;- последний fork — активный;
- старые fork-записи append-only: их нельзя удалить, переставить или изменить;
- один blockchain key нельзя добавить повторно;
paid_limit_bytesстарых fork неизменяем;- лимит можно пополнять только у последнего fork;
- новый fork наследует текущий лимит плюс оплаченный top-up;
- обычный blockchain authority может создать новый fork не раньше чем через 72 часа после
created_at_msактивного fork; - root recovery может создать fork без 72-часового ожидания.
created_at_ms передаёт клиент и включает в подписываемую PDA. Программа принимает его только если он отличается от Solana Clock не более чем на ±5 минут.
ServerProfileBlock
Блок отсутствует у обычного пользователя. Наличие блока означает, что PDA публикует SHiNE-server endpoint.
block_type: u8 = 30
block_version: u8 = 0
payload_len: u16
address_count: u8
addresses[address_count]:
address_format_type: u8
address_format_version: u8
address_len: u8
address: [u8;address_len]
PDA 1.2 разрешает ровно один адрес, если ServerProfileBlock присутствует. Массив/count сохранён для будущего увеличения лимита без изменения бинарной структуры.
address_format_type + address_format_version позволяют позже стандартизовать URL, IPv4, IPv6, Tor/I2P и другие адресные форматы.
AccessServersBlock
block_type: u8 = 40
block_version: u8 = 0
payload_len: u16
server_count: u8
servers[server_count]:
login_len: u8
login: [u8;login_len]
PDA 1.2 разрешает server_count = 0 или 1. Count оставлен для будущего расширения.
Authority и подпись
Новая PDA хранит signature[64] authority нового состояния по hash unsigned PDA:
- обычный update — активный blockchain key;
- новый fork — новый blockchain key;
- root-mode — root нового состояния;
- смена root — новый root.
На update программа дополнительно требует Ed25519-подпись authority предыдущего состояния по тому же hash нового unsigned state. Эта transition-подпись не хранится внутри PDA.
Blockchain-mode не может изменить root. Root-mode может изменить root и выполнить recovery. Одновременно менять root и добавлять blockchain fork одной транзакцией запрещено.
Create
Создаются только PDA 1.2.
record_number = 0
prev_record_hash = 0x00 * 32
fork_count = 1
fork[0].blockchain_key = initial blockchain key
fork[0].created_at_ms = created_at_ms
fork[0].paid_limit_bytes = start_bonus + paid top-up
Root доказывает владение recovery-key отдельной Ed25519 instruction, а signature[64] новой PDA делает initial blockchain key.
Legacy 1.0
Нормальные create/update/read flows нового клиента и сервера поддерживают только PDA 1.2.
Временно существует instruction close_legacy_pda для тестовых PDA 1.0. Она:
- принимает только PDA с
format_major=1,format_minor=0; - не может закрыть 1.2;
- закрывает старый program-owned account;
- переводит его lamports вызывающему signer.
Legacy migration в 1.2 отсутствует. После удаления тестовых PDA временную close-инструкцию можно удалить из программы.