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

View File

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