Кратко
Аккаунты программ содержат исполняемый sBPF-код. Аккаунты данных хранят состояние и принадлежат программам. Системные аккаунты принадлежат System Program. Sysvars предоставляют состояние кластера, доступное по предопределённым адресам.
Поле executable определяет категорию
аккаунта:
- Аккаунты программ:
executable=true. Содержит исполняемый код. - Аккаунты данных:
executable=false. Хранит состояние или пользовательские данные.
Такое разделение кода и изменяемого состояния позволяет развернуть программу один раз и управлять любым количеством аккаунтов данных.
Аккаунты программ
Аккаунт программы хранит исполняемый код. Каждый аккаунт программы принадлежит загрузчику программ. Когда программа развёртывается, среда выполнения создаёт аккаунт программы для хранения её байткода.
Диаграмма аккаунта программы, его 4 компонентов и загрузчика.
Аккаунты данных программ
Программы, развёрнутые с помощью loader-v3 (см.
Загрузчики программ), не
хранят исполняемый байткод в собственном поле data. Вместо этого их data
указывает на отдельный аккаунт данных программы, который содержит код
программы. (См. диаграмму ниже.)
Аккаунт программы с данными. Данные указывают на отдельный аккаунт данных программы
Во время развёртывания или обновления программы используются буферные аккаунты для временной загрузки данных.
В следующем примере происходит получение аккаунта Token Program. Поле
executable имеет значение true, что подтверждает: это аккаунт программы.
import { Address, generateKeyPairSigner } from "@solana/kit";import { createClient } from "@solana/kit-client-rpc";const feePayer = await generateKeyPairSigner();const client = createClient({url: "https://api.mainnet.solana.com",payer: feePayer});const programId = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" as Address;const accountInfo = await client.rpc.getAccountInfo(programId, { encoding: "base64" }).send();console.log(accountInfo);
Аккаунты данных
Аккаунты данных не содержат исполняемого кода. Они хранят состояние, определяемое программой.
Аккаунт состояния программы
Программы хранят своё состояние в аккаунтах данных. Создание аккаунта состояния программы включает два шага:
- Вызвать System Program, чтобы создать аккаунт. System Program передаёт право собственности указанной программе.
- Владеющая программа инициализирует поле аккаунта
dataсогласно своим инструкциям.
Диаграмма аккаунта данных, принадлежащего program account
В следующем примере создаётся и запрашивается mint account токена, принадлежащий программе Token 2022.
import { generateKeyPairSigner } from "@solana/kit";import { createLocalClient } from "@solana/kit-client-rpc";import { systemProgram } from "@solana-program/system";import {getInitializeMintInstruction,getMintSize,TOKEN_2022_PROGRAM_ADDRESS,fetchMint} from "@solana-program/token-2022";const client = await createLocalClient().use(systemProgram());// Generate keypair to use as address of mintconst mint = await generateKeyPairSigner();// Get default mint account size (in bytes), no extensions enabledconst space = BigInt(getMintSize());// Get minimum balance for rent exemptionconst rent = await client.rpc.getMinimumBalanceForRentExemption(space).send();const transactionSignature = await client.sendTransaction([client.system.instructions.createAccount({newAccount: mint,lamports: rent,space,programAddress: TOKEN_2022_PROGRAM_ADDRESS}),getInitializeMintInstruction({mint: mint.address,decimals: 9,mintAuthority: client.payer.address})]);console.log("Mint Address:", mint.address);console.log("Transaction Signature:", transactionSignature.context.signature);const accountInfo = await client.rpc.getAccountInfo(mint.address).send();console.log(accountInfo);const mintAccount = await fetchMint(client.rpc, mint.address);console.log(mintAccount);
Системные аккаунты
Аккаунты, которые после создания остаются во владении System Program, называются системными аккаунтами. Отправка SOL на новый адрес впервые создаёт новый аккаунт по этому адресу, принадлежащий System Program.
Все кошельки являются системными аккаунтами. Плательщик комиссии в транзакции должен быть системным аккаунтом, так как только аккаунты, принадлежащие System Program, могут оплачивать комиссии за транзакции.
Кошелёк, принадлежащий System Program, содержащий 1 000 000 лампортов
В следующем примере создаётся новая keypair, пополняется SOL и запрашивается
аккаунт. Поле owner равно 11111111111111111111111111111111
(System Program).
import { generateKeyPairSigner, lamports } from "@solana/kit";import { createLocalClient } from "@solana/kit-client-rpc";const client = await createLocalClient();// Generate a new keypairconst keypair = await generateKeyPairSigner();console.log(`Public Key: ${keypair.address}`);// Funding an address with SOL automatically creates an accountconst signature = await client.airdrop(keypair.address,lamports(1_000_000_000n));const accountInfo = await client.rpc.getAccountInfo(keypair.address).send();console.log(accountInfo);
Системные аккаунты (Sysvar)
Системные аккаунты (Sysvar) — это специальные аккаунты по предопределённым адресам, которые предоставляют только для чтения доступ к данным состояния кластера. Они обновляются динамически каждый slot.
| Sysvar | Адрес | Назначение |
|---|---|---|
| Clock | SysvarC1ock11111111111111111111111111111111 | Текущий slot, epoch и Unix-временная метка |
| EpochSchedule | SysvarEpochSchedu1e111111111111111111111111 | Константы расписания epoch, заданные в genesis |
| EpochRewards | SysvarEpochRewards1111111111111111111111111 | Статус и прогресс распределения наград за epoch |
| Rent | SysvarRent111111111111111111111111111111111 | Ставка rent и порог освобождения |
| SlotHashes | SysvarS1otHashes111111111111111111111111111 | Последние хэши родительских банков slot |
| StakeHistory | SysvarStakeHistory1111111111111111111111111 | Активация и деактивация стейка по epoch |
| LastRestartSlot | SysvarLastRestartS1ot1111111111111111111111 | Последний slot перезапуска кластера |
| Instructions | Sysvar1nstructions1111111111111111111111111 | Сериализованные инструкции текущей транзакции |
| SlotHistory | SysvarS1otHistory11111111111111111111111111 | Запись о том, какие slot были произведены за последний epoch |
В следующем примере выполняется получение и десериализация системного аккаунта Clock.
import { generateKeyPairSigner } from "@solana/kit";import { createClient } from "@solana/kit-client-rpc";import { fetchSysvarClock, SYSVAR_CLOCK_ADDRESS } from "@solana/sysvars";const feePayer = await generateKeyPairSigner();const client = createClient({url: "https://api.mainnet.solana.com",payer: feePayer});const accountInfo = await client.rpc.getAccountInfo(SYSVAR_CLOCK_ADDRESS, { encoding: "base64" }).send();console.log(accountInfo);// Automatically fetch and deserialize the account dataconst clock = await fetchSysvarClock(client.rpc);console.log(clock);
Is this page helpful?