SHA256
Переписать shine_users и shine_login_guard на чистый Rust
This commit is contained in:
@@ -10,10 +10,9 @@ import {
|
||||
const MAGIC = 'SHiNE';
|
||||
const LAST_BLOCK_STATE_PREFIX = 'SHiNE_LAST_BLOCK';
|
||||
const SHINE_PAYMENTS_INFLOW_VAULT_SEED = 'shine_payments_inflow_vault';
|
||||
const SHINE_USERS_USER_PDA_SEED_PREFIX = 'user_login=';
|
||||
const LIMIT_STEP = 10_000n;
|
||||
const BLOCKCHAIN_TYPE_MAIN_USER = 1;
|
||||
const CREATE_USER_PDA_DISCRIMINATOR = new Uint8Array([139, 157, 13, 41, 142, 174, 226, 214]);
|
||||
const UPDATE_USER_PDA_DISCRIMINATOR = new Uint8Array([42, 133, 114, 232, 38, 245, 167, 234]);
|
||||
const ED25519_PROGRAM_ID = 'Ed25519SigVerify111111111111111111111111111';
|
||||
const SYSVAR_INSTRUCTIONS_ID = 'Sysvar1nstructions1111111111111111111111111';
|
||||
|
||||
@@ -22,8 +21,8 @@ const BLOCK_TYPE_DEVICE_KEY = 2;
|
||||
const BLOCK_TYPE_BLOCKCHAIN_REGISTRY = 3;
|
||||
const BLOCK_TYPE_SERVER_PROFILE = 30;
|
||||
const BLOCK_TYPE_ACCESS_SERVERS = 40;
|
||||
const BLOCK_TYPE_SESSIONS = 55;
|
||||
const BLOCK_TYPE_TRUSTED_STATE = 50;
|
||||
const BLOCK_TYPE_SESSIONS = 50;
|
||||
const BLOCK_TYPE_TRUSTED_STATE = 70;
|
||||
const SESSIONS_MODE_MIXED = 1;
|
||||
const SESSION_TYPE_USER = 1;
|
||||
const SESSION_TYPE_SUBSERVER = 100;
|
||||
@@ -175,60 +174,88 @@ function buildEd25519IxData(sig64, pubkey32, msgHash32) {
|
||||
|
||||
function serializeCreateUserPdaArgs(args) {
|
||||
const buf = [];
|
||||
for (const x of CREATE_USER_PDA_DISCRIMINATOR) buf.push(x);
|
||||
pushStrU32(buf, args.login);
|
||||
buf.push(3);
|
||||
pushStrU8(buf, args.login);
|
||||
for (const x of args.rootKey32) buf.push(x);
|
||||
pushU64LE(buf, args.createdAtMs);
|
||||
pushU64LE(buf, 0n);
|
||||
pushU64LE(buf, BigInt(args.additionalLimitBytes || 0n));
|
||||
for (const x of args.deviceKey32) buf.push(x);
|
||||
for (const x of args.blockchainPublicKey32) buf.push(x);
|
||||
pushStrU32(buf, args.blockchainName);
|
||||
pushStrU8(buf, args.blockchainName);
|
||||
pushU64LE(buf, args.usedBytes);
|
||||
pushU32LE(buf, args.lastBlockNumber);
|
||||
pushVecU8(buf, args.lastBlockHash32);
|
||||
pushVecU8(buf, args.lastBlockSignature64);
|
||||
pushStrU32(buf, args.arweaveTxId);
|
||||
for (const x of args.lastBlockHash32) buf.push(x);
|
||||
for (const x of args.lastBlockSignature64) buf.push(x);
|
||||
pushStrU8(buf, args.arweaveTxId);
|
||||
buf.push(args.isServer ? 1 : 0);
|
||||
buf.push(Number(args.addressFormatType || 0) & 0xff);
|
||||
buf.push(Number(args.addressFormatVersion || 0) & 0xff);
|
||||
pushStrU32(buf, args.serverAddress);
|
||||
pushVecStrU32(buf, args.syncServers);
|
||||
pushVecStrU32(buf, args.accessServers);
|
||||
if (args.isServer) {
|
||||
buf.push(Number(args.addressFormatType || 0) & 0xff);
|
||||
buf.push(Number(args.addressFormatVersion || 0) & 0xff);
|
||||
pushStrU8(buf, args.serverAddress);
|
||||
const syncServers = Array.isArray(args.syncServers) ? args.syncServers : [];
|
||||
buf.push(syncServers.length & 0xff);
|
||||
for (const value of syncServers) pushStrU8(buf, value);
|
||||
}
|
||||
const accessServers = Array.isArray(args.accessServers) ? args.accessServers : [];
|
||||
buf.push(accessServers.length & 0xff);
|
||||
for (const value of accessServers) pushStrU8(buf, value);
|
||||
buf.push(Number(args.sessionsMode || SESSIONS_MODE_MIXED) & 0xff);
|
||||
pushSessionRecordsU32(buf, args.sessions);
|
||||
const sessions = Array.isArray(args.sessions) ? args.sessions : [];
|
||||
buf.push(sessions.length & 0xff);
|
||||
for (const session of sessions) {
|
||||
buf.push(Number(session?.sessionType || 0) & 0xff);
|
||||
buf.push(Number(session?.sessionVersion || 0) & 0xff);
|
||||
pushStrU8(buf, String(session?.sessionName || ''));
|
||||
const key = session?.sessionPubKey32 || new Uint8Array(32);
|
||||
for (const x of key) buf.push(x);
|
||||
}
|
||||
buf.push(Number(args.trustedCount || 0) & 0xff);
|
||||
pushVecU8(buf, args.rootSignature64);
|
||||
for (const x of args.rootSignature64) buf.push(x);
|
||||
return new Uint8Array(buf);
|
||||
}
|
||||
|
||||
function serializeUpdateUserPdaArgs(args) {
|
||||
const buf = [];
|
||||
for (const x of UPDATE_USER_PDA_DISCRIMINATOR) buf.push(x);
|
||||
pushStrU32(buf, args.login);
|
||||
buf.push(4);
|
||||
pushStrU8(buf, args.login);
|
||||
for (const x of args.rootKey32) buf.push(x);
|
||||
pushU64LE(buf, args.createdAtMs);
|
||||
pushU64LE(buf, args.updatedAtMs);
|
||||
pushU32LE(buf, args.version);
|
||||
pushVecU8(buf, args.prevHash32);
|
||||
for (const x of args.prevHash32) buf.push(x);
|
||||
pushU64LE(buf, args.additionalLimitBytes);
|
||||
for (const x of args.deviceKey32) buf.push(x);
|
||||
for (const x of args.blockchainPublicKey32) buf.push(x);
|
||||
pushStrU32(buf, args.blockchainName);
|
||||
pushStrU8(buf, args.blockchainName);
|
||||
pushU64LE(buf, args.usedBytes);
|
||||
pushU32LE(buf, args.lastBlockNumber);
|
||||
pushVecU8(buf, args.lastBlockHash32);
|
||||
pushVecU8(buf, args.lastBlockSignature64);
|
||||
pushStrU32(buf, args.arweaveTxId);
|
||||
for (const x of args.lastBlockHash32) buf.push(x);
|
||||
for (const x of args.lastBlockSignature64) buf.push(x);
|
||||
pushStrU8(buf, args.arweaveTxId);
|
||||
buf.push(args.isServer ? 1 : 0);
|
||||
buf.push(Number(args.addressFormatType || 0) & 0xff);
|
||||
buf.push(Number(args.addressFormatVersion || 0) & 0xff);
|
||||
pushStrU32(buf, args.serverAddress);
|
||||
pushVecStrU32(buf, args.syncServers);
|
||||
pushVecStrU32(buf, args.accessServers);
|
||||
if (args.isServer) {
|
||||
buf.push(Number(args.addressFormatType || 0) & 0xff);
|
||||
buf.push(Number(args.addressFormatVersion || 0) & 0xff);
|
||||
pushStrU8(buf, args.serverAddress);
|
||||
const syncServers = Array.isArray(args.syncServers) ? args.syncServers : [];
|
||||
buf.push(syncServers.length & 0xff);
|
||||
for (const value of syncServers) pushStrU8(buf, value);
|
||||
}
|
||||
const accessServers = Array.isArray(args.accessServers) ? args.accessServers : [];
|
||||
buf.push(accessServers.length & 0xff);
|
||||
for (const value of accessServers) pushStrU8(buf, value);
|
||||
buf.push(Number(args.sessionsMode || SESSIONS_MODE_MIXED) & 0xff);
|
||||
pushSessionRecordsU32(buf, args.sessions);
|
||||
const sessions = Array.isArray(args.sessions) ? args.sessions : [];
|
||||
buf.push(sessions.length & 0xff);
|
||||
for (const session of sessions) {
|
||||
buf.push(Number(session?.sessionType || 0) & 0xff);
|
||||
buf.push(Number(session?.sessionVersion || 0) & 0xff);
|
||||
pushStrU8(buf, String(session?.sessionName || ''));
|
||||
const key = session?.sessionPubKey32 || new Uint8Array(32);
|
||||
for (const x of key) buf.push(x);
|
||||
}
|
||||
buf.push(Number(args.trustedCount || 0) & 0xff);
|
||||
pushVecU8(buf, args.rootSignature64);
|
||||
for (const x of args.rootSignature64) buf.push(x);
|
||||
return new Uint8Array(buf);
|
||||
}
|
||||
|
||||
@@ -500,7 +527,7 @@ export function serializeUnsignedRecordFromState(stateLike) {
|
||||
pushU32LE(buf, state.recordNumber);
|
||||
for (const x of state.prevRecordHash) buf.push(x);
|
||||
pushStrU8(buf, state.login);
|
||||
buf.push(state.isServer ? 6 : 5);
|
||||
buf.push(state.isServer ? 7 : 6);
|
||||
|
||||
buf.push(BLOCK_TYPE_ROOT_KEY, 0);
|
||||
for (const x of state.rootKey) buf.push(x);
|
||||
@@ -569,7 +596,7 @@ export async function readShineUserPda({ login, solanaEndpoint }) {
|
||||
const connection = new solana.Connection(endpoint, 'confirmed');
|
||||
const usersProgram = new solana.PublicKey(SHINE_USERS_PROGRAM_ID);
|
||||
const enc = new TextEncoder();
|
||||
const [userPda] = solana.PublicKey.findProgramAddressSync([enc.encode('login='), enc.encode(cleanLogin)], usersProgram);
|
||||
const [userPda] = solana.PublicKey.findProgramAddressSync([enc.encode(SHINE_USERS_USER_PDA_SEED_PREFIX), enc.encode(cleanLogin)], usersProgram);
|
||||
const accountInfo = await connection.getAccountInfo(userPda, 'confirmed');
|
||||
if (!accountInfo?.data) throw new Error(`PDA не найдена для логина «${cleanLogin}»`);
|
||||
return {
|
||||
@@ -625,7 +652,7 @@ async function buildCreateContext({ login, keyBundle, solanaEndpoint }) {
|
||||
const sysvarInstructions = new solana.PublicKey(SYSVAR_INSTRUCTIONS_ID);
|
||||
const enc = new TextEncoder();
|
||||
|
||||
const [userPda] = solana.PublicKey.findProgramAddressSync([enc.encode('login='), enc.encode(cleanLogin)], usersProgram);
|
||||
const [userPda] = solana.PublicKey.findProgramAddressSync([enc.encode(SHINE_USERS_USER_PDA_SEED_PREFIX), enc.encode(cleanLogin)], usersProgram);
|
||||
const [economyConfigPda] = solana.PublicKey.findProgramAddressSync([enc.encode(SHINE_USERS_ECONOMY_CONFIG_SEED)], usersProgram);
|
||||
const [inflowVault] = solana.PublicKey.findProgramAddressSync([enc.encode(SHINE_PAYMENTS_INFLOW_VAULT_SEED)], paymentsProgram);
|
||||
|
||||
@@ -724,6 +751,7 @@ async function createShineUserPdaOnSolana({
|
||||
login: cleanLogin,
|
||||
rootKey32: ctx.rootKey32,
|
||||
createdAtMs,
|
||||
additionalLimitBytes: 0n,
|
||||
deviceKey32: ctx.deviceKey32,
|
||||
blockchainPublicKey32: ctx.blockchainKey32,
|
||||
blockchainName,
|
||||
@@ -851,7 +879,7 @@ export async function updateShineUserPdaOnSolana({
|
||||
const ed25519Program = new solana.PublicKey(ED25519_PROGRAM_ID);
|
||||
const sysvarInstructions = new solana.PublicKey(SYSVAR_INSTRUCTIONS_ID);
|
||||
const enc = new TextEncoder();
|
||||
const [userPda] = solana.PublicKey.findProgramAddressSync([enc.encode('login='), enc.encode(cleanLogin)], usersProgram);
|
||||
const [userPda] = solana.PublicKey.findProgramAddressSync([enc.encode(SHINE_USERS_USER_PDA_SEED_PREFIX), enc.encode(cleanLogin)], usersProgram);
|
||||
const [economyPda] = solana.PublicKey.findProgramAddressSync([enc.encode(SHINE_USERS_ECONOMY_CONFIG_SEED)], usersProgram);
|
||||
const [inflowVault] = solana.PublicKey.findProgramAddressSync([enc.encode(SHINE_PAYMENTS_INFLOW_VAULT_SEED)], paymentsProgram);
|
||||
const deviceSeed32 = extractSeed32FromPkcs8B64(devicePrivatePkcs8B64);
|
||||
|
||||
@@ -3,6 +3,6 @@ export const SOLANA_ENDPOINT_DEFAULT = 'https://api.devnet.solana.com';
|
||||
|
||||
// Программа регистрации пользователей SHiNE (shine_users), задеплоена в devnet.
|
||||
export const SHINE_USERS_PROGRAM_ID = 'FZS1YctoeEhCkZ5VTjsysUFAXR8CqxYztcLboXcg2Rpm';
|
||||
export const SHINE_USERS_ECONOMY_CONFIG_SEED = 'shine_users_economy_config';
|
||||
export const SHINE_USERS_ECONOMY_CONFIG_SEED = 'shine_users_economy_config_v2';
|
||||
export const SHINE_LOGIN_GUARD_PROGRAM_ID = '3xkopA7cXagxzMFrKdv3NCBfV6BKiRJCk69kr27M2sRo';
|
||||
export const SHINE_PAYMENTS_PROGRAM_ID = 'm48pWRGWrMj3TEHjuU4zsp5Gju4e7ZaPovk8RcVt7kR';
|
||||
|
||||
Reference in New Issue
Block a user