shine_users: switch user record to v1.0 status-key layout and login<=25

This commit is contained in:
AidarKC 2026-05-16 15:33:20 +03:00
parent 61fcfd0e3b
commit 8ce804eb77
2 changed files with 27 additions and 2 deletions

View File

@ -69,7 +69,7 @@
10. `login`
Размер: `login_len` байт (UTF-8).
Назначение: логин пользователя.
Текущие ограничения: от 1 до 20 символов, только `a-z`, `0-9`, `_`.
Текущие ограничения: от 1 до 25 символов, только `a-z`, `0-9`, `_`.
11. `root_key_status`
Размер: 1 байт (`u8`).

View File

@ -14,6 +14,7 @@ use std::str::FromStr;
const MAGIC: &[u8; 5] = b"SHiNE";
const FORMAT_MAJOR: u8 = 1;
const FORMAT_MINOR: u8 = 0;
const KEY_STATUS_CREATED: u8 = 0;
const RESERVED_BYTES: [u8; 5] = [0, 0, 0, 0, 0];
const ZERO_HASH: [u8; 32] = [0; 32];
@ -58,8 +59,11 @@ pub struct UserRecord {
pub version: u32,
pub prev_hash: [u8; 32],
pub login: String,
pub root_key_status: u8,
pub root_key: Pubkey,
pub blockchain_key_status: u8,
pub blockchain_key: Pubkey,
pub device_key_status: u8,
pub device_key: Pubkey,
pub chain_number: u16,
pub balance: u64,
@ -133,8 +137,11 @@ pub fn create_user_pda(ctx: Context<CreateUserPda>, args: CreateUserPdaArgs) ->
version: 0,
prev_hash: ZERO_HASH,
login: args.login.clone(),
root_key_status: KEY_STATUS_CREATED,
root_key: args.root_key,
blockchain_key_status: KEY_STATUS_CREATED,
blockchain_key: args.fields.blockchain_key,
device_key_status: KEY_STATUS_CREATED,
device_key: args.fields.device_key,
chain_number: args.fields.chain_number,
balance: start_balance,
@ -226,6 +233,12 @@ pub fn update_user_pda(ctx: Context<UpdateUserPda>, args: UpdateUserPdaArgs) ->
args.root_key,
ErrCode::ImmutableFieldChanged
);
require!(
old_record.root_key_status == KEY_STATUS_CREATED
&& old_record.blockchain_key_status == KEY_STATUS_CREATED
&& old_record.device_key_status == KEY_STATUS_CREATED,
ErrCode::InvalidRecordData
);
require!(
args.version == old_record.version.saturating_add(1),
ErrCode::InvalidVersion
@ -250,8 +263,11 @@ pub fn update_user_pda(ctx: Context<UpdateUserPda>, args: UpdateUserPdaArgs) ->
version: args.version,
prev_hash: provided_prev_hash,
login: old_record.login.clone(),
root_key_status: old_record.root_key_status,
root_key: old_record.root_key,
blockchain_key_status: old_record.blockchain_key_status,
blockchain_key: args.fields.blockchain_key,
device_key_status: old_record.device_key_status,
device_key: args.fields.device_key,
chain_number: args.fields.chain_number,
balance: new_balance,
@ -320,8 +336,11 @@ fn serialize_unsigned_record(record: &UserRecord) -> Result<Vec<u8>> {
out.push(login_bytes.len() as u8);
out.extend_from_slice(login_bytes);
out.push(record.root_key_status);
out.extend_from_slice(record.root_key.as_ref());
out.push(record.blockchain_key_status);
out.extend_from_slice(record.blockchain_key.as_ref());
out.push(record.device_key_status);
out.extend_from_slice(record.device_key.as_ref());
out.extend_from_slice(&record.chain_number.to_le_bytes());
@ -384,8 +403,11 @@ fn deserialize_record_from_pda(raw: &[u8]) -> Result<UserRecord> {
let prev_hash = read_fixed_32(useful, &mut cursor)?;
let login = read_len_prefixed_string(useful, &mut cursor)?;
let root_key_status = read_u8(useful, &mut cursor)?;
let root_key = Pubkey::new_from_array(read_fixed_32(useful, &mut cursor)?);
let blockchain_key_status = read_u8(useful, &mut cursor)?;
let blockchain_key = Pubkey::new_from_array(read_fixed_32(useful, &mut cursor)?);
let device_key_status = read_u8(useful, &mut cursor)?;
let device_key = Pubkey::new_from_array(read_fixed_32(useful, &mut cursor)?);
let chain_number = read_u16(useful, &mut cursor)?;
@ -423,8 +445,11 @@ fn deserialize_record_from_pda(raw: &[u8]) -> Result<UserRecord> {
version,
prev_hash,
login,
root_key_status,
root_key,
blockchain_key_status,
blockchain_key,
device_key_status,
device_key,
chain_number,
balance,
@ -551,7 +576,7 @@ fn le_u16(data: &[u8], offset: usize) -> Result<u16> {
fn validate_login(login: &str) -> Result<()> {
require!(!login.is_empty(), ErrCode::InvalidLogin);
require!(login.len() <= 30, ErrCode::InvalidLogin);
require!(login.len() <= 25, ErrCode::InvalidLogin);
for ch in login.chars() {
if !(ch.is_ascii_lowercase() || ch.is_ascii_digit() || ch == '_') {
return Err(error!(ErrCode::InvalidLogin));