Новый протокол Solana PDA 1.2

This commit is contained in:
AidarKC
2026-09-26 11:01:14 +03:00
parent 6e5b57fd7c
commit c997057a37
47 changed files with 2392 additions and 4480 deletions
+134 -2
View File
@@ -1538,7 +1538,7 @@ var solanaWeb3=function(exports){"use strict";function getDefaultExportFromCjs(x
};
}
function parseShineUserPda(dataBytes) {
function parseShineUserPdaLegacy(dataBytes) {
const bytes = dataBytes instanceof Uint8Array ? dataBytes : new Uint8Array(dataBytes || []);
const reader = makeReader(bytes);
const magic = new TextDecoder().decode(reader.readBytes(5));
@@ -1697,6 +1697,138 @@ var solanaWeb3=function(exports){"use strict";function getDefaultExportFromCjs(x
};
}
function parseShineUserPdaV12(dataBytes) {
const bytes = dataBytes instanceof Uint8Array ? dataBytes : new Uint8Array(dataBytes || []);
const reader = makeReader(bytes);
const magic = new TextDecoder().decode(reader.readBytes(5));
if (magic !== MAGIC) throw new Error('Некорректный формат PDA: magic не совпадает');
const formatMajor = reader.readU8();
const formatMinor = reader.readU8();
const recordLen = reader.readU16();
if (formatMajor !== 1 || formatMinor !== 2 || recordLen < 73 || recordLen > bytes.length) {
throw new Error('Некорректный формат PDA 1.2');
}
const createdAtMs = reader.readU64();
const updatedAtMs = reader.readU64();
const recordNumber = reader.readU32();
const prevRecordHash = reader.readBytes(32);
const login = reader.readStrU8();
const blocksCount = reader.readU8();
let rootKey = null;
let clientKey = null;
let forks = null;
let serverProfile = null;
let accessServers = [];
for (let index = 0; index < blocksCount; index += 1) {
const blockType = reader.readU8();
const blockVersion = reader.readU8();
if (blockType === BLOCK_TYPE_ROOT_KEY) {
if (blockVersion !== 0) throw new Error('Неизвестная версия RootKeyBlock');
rootKey = reader.readBytes(32);
continue;
}
if (blockType === BLOCK_TYPE_CLIENT_KEY) {
if (blockVersion !== 0) throw new Error('Неизвестная версия ClientKeyBlock');
clientKey = reader.readBytes(32);
continue;
}
const payloadLen = reader.readU16();
const payload = makeReader(reader.readBytes(payloadLen));
if (blockVersion !== 0) continue;
if (blockType === BLOCK_TYPE_BLOCKCHAIN_REGISTRY) {
const count = payload.readU16();
if (count < 1) throw new Error('BlockchainRegistry 1.2 пуст');
forks = [];
for (let j = 0; j < count; j += 1) {
forks.push({
blockchainKey: payload.readBytes(32),
paidLimitBytes: BigInt(payload.readU32()),
});
}
} else if (blockType === BLOCK_TYPE_SERVER_PROFILE) {
const count = payload.readU8();
const addresses = [];
for (let j = 0; j < count; j += 1) {
addresses.push({
addressFormatType: payload.readU8(),
addressFormatVersion: payload.readU8(),
address: payload.readStrU8(),
});
}
const first = addresses[0] || null;
serverProfile = first ? {
blockVersion,
addressFormatType: first.addressFormatType,
addressFormatVersion: first.addressFormatVersion,
serverAddress: first.address,
addresses,
syncServers: [],
} : null;
} else if (blockType === BLOCK_TYPE_ACCESS_SERVERS) {
const count = payload.readU8();
if (count > 1) throw new Error('PDA 1.2 допускает максимум один access server');
accessServers = [];
for (let j = 0; j < count; j += 1) accessServers.push(payload.readStrU8());
}
}
if (!rootKey || !clientKey || !forks || forks.length < 1) {
throw new Error('В PDA 1.2 отсутствуют обязательные блоки shine_users');
}
const active = forks[forks.length - 1];
const blockchain = {
blockchainType: 1,
blockchainName: `${String(login).toLowerCase()}-${String(forks.length).padStart(3, '0')}`,
blockchainPublicKey: active.blockchainKey,
paidLimitBytes: active.paidLimitBytes,
usedBytes: 0n,
lastBlockNumber: 0,
lastBlockHash: new Uint8Array(32),
lastBlockSignature: new Uint8Array(64),
arweaveTxId: '',
};
const signature = bytes.slice(recordLen - 64, recordLen);
return {
formatMajor,
formatMinor,
recordLen,
createdAtMs,
updatedAtMs,
recordNumber,
prevRecordHash,
login,
blocksCount,
recoveryKey: null,
rootKey,
clientKey,
forks,
blockchain,
serverProfile,
accessServers,
sessionsMode: DEFAULT_SESSIONS_MODE,
sessions: [],
trustedCount: 0,
signature,
};
}
function parseShineUserPda(dataBytes) {
const bytes = dataBytes instanceof Uint8Array ? dataBytes : new Uint8Array(dataBytes || []);
if (bytes.length < 9) throw new Error('Повреждённый формат PDA');
const magic = new TextDecoder().decode(bytes.slice(0, 5));
if (magic !== MAGIC) throw new Error('Некорректный формат PDA: magic не совпадает');
const formatMajor = bytes[5];
const formatMinor = bytes[6];
if (formatMajor === 1 && formatMinor === 2) return parseShineUserPdaV12(bytes);
if (formatMajor === 1 && formatMinor === 0) return parseShineUserPdaLegacy(bytes);
throw new Error(`Неподдерживаемый формат PDA ${formatMajor}.${formatMinor}`);
}
async function digestSha256(bytes) {
const input = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes || []);
const hash = await crypto.subtle.digest('SHA-256', input);
@@ -2377,7 +2509,7 @@ var solanaWeb3=function(exports){"use strict";function getDefaultExportFromCjs(x
signatureHex: bytesToHex(parsed.signature),
},
keys: {
recoveryKeyBase58: bytesToBase58(parsed.recoveryKey),
recoveryKeyBase58: parsed.recoveryKey ? bytesToBase58(parsed.recoveryKey) : '',
rootKeyBase58: bytesToBase58(parsed.rootKey),
clientKeyBase58: bytesToBase58(parsed.clientKey),
},