Підсумок
Програмні облікові записи містять виконуваний sBPF-код. Облікові записи даних зберігають стан, що належить програмам. Системні облікові записи належать System Program. Sysvars надають стан кластера, доступний за попередньо визначеними адресами.
Поле executable визначає категорію
облікового запису:
- Програмні облікові записи:
executable=true. Містить виконуваний код. - Облікові записи даних:
executable=false. Зберігає стан або дані користувача.
Це розділення коду від змінюваного стану означає, що програма розгортається один раз і може керувати будь-якою кількістю облікових записів даних.
Програмні облікові записи
Програмний обліковий запис зберігає виконуваний код. Кожен програмний обліковий запис належить програмі-завантажувачу. Коли програма розгортається, середовище виконання створює програмний обліковий запис для зберігання її байт-коду.
Diagram of a program account, its 4 components and its loader program.
Облікові записи даних програми
Програми, розгорнуті за допомогою loader-v3 (див.
Програми-завантажувачі),
не зберігають виконуваний байт-код у власному полі data. Натомість їхнє поле
data вказує на окремий обліковий запис даних програми, що містить код
програми. (Див. діаграму нижче.)
A program account with data. The data points to a separate program data account
Під час розгортання або оновлення програми буферні облікові записи використовуються для тимчасового етапного завантаження.
Наступний приклад отримує обліковий запис Token Program. Поле executable
дорівнює true, що підтверджує, що це програмний обліковий запис.
import { Address, createSolanaRpc } from "@solana/kit";const rpc = createSolanaRpc("https://api.mainnet.solana.com");const programId = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" as Address;const accountInfo = await rpc.getAccountInfo(programId, { encoding: "base64" }).send();console.log(accountInfo);
Акаунти даних
Акаунти даних не містять виконуваного коду. Вони зберігають стан, визначений програмою.
Акаунт стану програми
Програми зберігають свій стан в акаунтах даних. Створення акаунта стану програми включає два кроки:
- Викликати системну програму, щоб створити акаунт. Системна програма передає право власності вказаній програмі.
- Програма-власник ініціалізує поле
dataакаунта відповідно до своїх інструкцій.
Діаграма акаунта даних, що належить program account
Наступний приклад створює та отримує mint account токена, що належить програмі Token 2022.
import {airdropFactory,appendTransactionMessageInstructions,createSolanaRpc,createSolanaRpcSubscriptions,createTransactionMessage,generateKeyPairSigner,getSignatureFromTransaction,lamports,pipe,sendAndConfirmTransactionFactory,setTransactionMessageFeePayerSigner,setTransactionMessageLifetimeUsingBlockhash,signTransactionMessageWithSigners} from "@solana/kit";import { getCreateAccountInstruction } from "@solana-program/system";import {getInitializeMintInstruction,getMintSize,TOKEN_2022_PROGRAM_ADDRESS,fetchMint} from "@solana-program/token-2022";// Create Connection, local validator in this exampleconst rpc = createSolanaRpc("http://localhost:8899");const rpcSubscriptions = createSolanaRpcSubscriptions("ws://localhost:8900");// Generate keypairs for fee payerconst feePayer = await generateKeyPairSigner();// Fund fee payerawait airdropFactory({ rpc, rpcSubscriptions })({recipientAddress: feePayer.address,lamports: lamports(1_000_000_000n),commitment: "confirmed"});// 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 rpc.getMinimumBalanceForRentExemption(space).send();// Instruction to create new account for mint (token 2022 program)// Invokes the system programconst createAccountInstruction = getCreateAccountInstruction({payer: feePayer,newAccount: mint,lamports: rent,space,programAddress: TOKEN_2022_PROGRAM_ADDRESS});// Instruction to initialize mint account data// Invokes the token 2022 programconst initializeMintInstruction = getInitializeMintInstruction({mint: mint.address,decimals: 9,mintAuthority: feePayer.address});const instructions = [createAccountInstruction, initializeMintInstruction];// Get latest blockhash to include in transactionconst { value: latestBlockhash } = await rpc.getLatestBlockhash().send();// Create transaction messageconst transactionMessage = pipe(createTransactionMessage({ version: 0 }), // Create transaction message(tx) => setTransactionMessageFeePayerSigner(feePayer, tx), // Set fee payer(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx), // Set transaction blockhash(tx) => appendTransactionMessageInstructions(instructions, tx) // Append instructions);// Sign transaction message with required signers (fee payer and mint keypair)const signedTransaction =await signTransactionMessageWithSigners(transactionMessage);// Send and confirm transactionawait sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(signedTransaction,{ commitment: "confirmed" });// Get transaction signatureconst transactionSignature = getSignatureFromTransaction(signedTransaction);console.log("Mint Address:", mint.address);console.log("Transaction Signature:", transactionSignature);const accountInfo = await rpc.getAccountInfo(mint.address).send();console.log(accountInfo);const mintAccount = await fetchMint(rpc, mint.address);console.log(mintAccount);
Системні акаунти
Акаунти, які залишаються у власності системної програми після створення, називаються системними акаунтами. Надсилання SOL на нову адресу вперше створює новий акаунт за цією адресою, що належить системній програмі.
Усі акаунти гаманців є системними акаунтами. Платник комісії в транзакції має бути системним акаунтом, оскільки лише акаунти, що належать системній програмі, можуть сплачувати комісії за транзакції.
Гаманець, що належить системній програмі, містить 1 000 000 lamports
Наступний приклад генерує нову keypair, поповнює її SOL і отримує акаунт. Поле
owner має значення 11111111111111111111111111111111
(системна програма).
import {airdropFactory,createSolanaRpc,createSolanaRpcSubscriptions,generateKeyPairSigner,lamports} from "@solana/kit";// Create a connection to Solana clusterconst rpc = createSolanaRpc("http://localhost:8899");const rpcSubscriptions = createSolanaRpcSubscriptions("ws://localhost:8900");// Generate a new keypairconst keypair = await generateKeyPairSigner();console.log(`Public Key: ${keypair.address}`);// Funding an address with SOL automatically creates an accountconst signature = await airdropFactory({ rpc, rpcSubscriptions })({recipientAddress: keypair.address,lamports: lamports(1_000_000_000n),commitment: "confirmed"});const accountInfo = await 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 |
Наступний приклад отримує та десеріалізує обліковий запис Sysvar Clock.
import { createSolanaRpc } from "@solana/kit";import { fetchSysvarClock, SYSVAR_CLOCK_ADDRESS } from "@solana/sysvars";const rpc = createSolanaRpc("https://api.mainnet.solana.com");const accountInfo = await rpc.getAccountInfo(SYSVAR_CLOCK_ADDRESS, { encoding: "base64" }).send();console.log(accountInfo);// Automatically fetch and deserialize the account dataconst clock = await fetchSysvarClock(rpc);console.log(clock);
Is this page helpful?