Акаунти
Усі дані в мережі Solana зберігаються в акаунтах. Мережу Solana можна уявити як публічну базу даних з єдиною таблицею Акаунтів. Зв'язок між акаунтом та його адресою подібний до пари ключ-значення, де ключем є адреса, а значенням — акаунт.
Кожен акаунт має однакову базову структуру і може бути знайдений за його адресою.
Діаграма 3 акаунтів та їхніх адрес. Включає визначення структури акаунта.
Адреса акаунта
Адреса акаунта — це унікальний 32-байтовий ідентифікатор, який використовується для пошуку акаунта в блокчейні Solana. Адреси акаунтів часто відображаються як рядки, закодовані в base58. Більшість акаунтів використовують відкритий ключ Ed25519 як свою адресу, але це не обов'язково, оскільки Solana також підтримує програмно похідні адреси.
Акаунт з його адресою відкритого ключа, закодованою в base58
Відкритий ключ
Приклад нижче демонструє, як використовувати SDK Solana для створення keypair.
import { generateKeyPairSigner } from "@solana/kit";// Kit does not enable extractable private keysconst keypairSigner = await generateKeyPairSigner();console.log(keypairSigner);
Program derived address
Program derived address (PDA) — це адреса, яка детерміновано виводиться з використанням ідентифікатора програми та одного чи кількох необов'язкових вхідних даних (seeds). Приклад нижче демонструє, як використовувати SDK Solana для створення program derived address.
import { Address, getProgramDerivedAddress } from "@solana/kit";const programAddress = "11111111111111111111111111111111" as Address;const seeds = ["helloWorld"];const [pda, bump] = await getProgramDerivedAddress({programAddress,seeds});console.log(`PDA: ${pda}`);console.log(`Bump: ${bump}`);
Структура акаунта
Кожен
Account
має максимальний розмір
10MiB
і містить таку інформацію:
lamports: Кількість lamports в акаунтіdata: Дані акаунтаowner: Ідентифікатор програми, яка володіє акаунтомexecutable: Вказує, чи містить акаунт виконуваний бінарний кодrent_epoch: Застаріле поле epoch оренди
pub struct Account {/// lamports in the accountpub lamports: u64,/// data held in this account#[cfg_attr(feature = "serde", serde(with = "serde_bytes"))]pub data: Vec<u8>,/// the program that owns this account. If executable, the program that loads this account.pub owner: Pubkey,/// this account's data contains a loaded program (and is now read-only)pub executable: bool,/// the epoch at which this account will next owe rentpub rent_epoch: Epoch,}
Lamports
Баланс облікового запису в lamports.
Кожен обліковий запис повинен мати мінімальний баланс lamport, який називається rent, що дозволяє зберігати його дані в блокчейні. Rent пропорційний розміру облікового запису.
Хоча цей баланс називається rent, він працює більше як депозит, оскільки повний баланс можна повернути при закритті облікового запису. (Назва "rent" походить від тепер застарілого поля rent epoch.)
(Дивіться формулу мінімального балансу та відповідні константи.)
Дані
Це поле зазвичай називають "даними облікового запису". data у цьому полі
вважаються довільними, оскільки можуть містити будь-яку послідовність байтів.
Кожна програма визначає структуру даних, що зберігаються в цьому полі.
- Program accounts: Це поле містить або виконуваний код програми, або адресу program data account, який зберігає виконуваний код програми.
- Data accounts: Це поле зазвичай зберігає дані стану, призначені для читання.
Читання даних з облікового запису Solana включає два кроки:
- Отримання облікового запису за його адресою
- Десеріалізація поля
dataоблікового запису з необроблених байтів у відповідну структуру даних, як визначено програмою, яка володіє обліковим записом.
Власник
Це поле містить ідентифікатор програми власника облікового запису.
Кожен обліковий запис Solana має програму, призначену як
його власника. Власник облікового запису — це єдина програма, яка може змінювати
data облікового запису або знімати lamports, як зазначено в інструкціях
програми.
(У випадку program account, власником є його програма-завантажувач.)
Виконуваність
Це поле вказує, чи є акаунт program account або акаунтом даних
- Якщо
true: Акаунт є program account - Якщо
false: Акаунт є акаунтом даних
Епоха оренди
Поле rent_epoch застаріле.
Раніше це поле відстежувало, коли акаунт повинен був сплачувати rent. Однак цей механізм збору rent з того часу застарів.
Типи акаунтів
Існує дві основні категорії акаунтів:
- Program accounts: Акаунти, що містять виконуваний код
- Акаунти даних: Акаунти, що не містять виконуваного коду
Це розділення означає, що виконуваний код програми та її стан зберігаються в окремих акаунтах. (Подібно до операційних систем, які зазвичай мають окремі файли для програм та їхніх даних.)
Program accounts
Кожна програма належить програмі-завантажувачу, яка використовується для розгортання та управління акаунтом. Коли нова програма розгортається, створюється акаунт для зберігання її виконуваного коду. Це називається program account. (Для простоти можна вважати program account самою програмою.)
На діаграмі нижче ви можете побачити, як програма-завантажувач використовується
для розгортання program account. Поле data program account містить виконуваний
код програми.
Діаграма program account, його 4 компонентів та програми-завантажувача.
Акаунти даних програми
Програми, розгорнуті за допомогою loader-v3, не містять програмного коду в
своєму полі data. Натомість, їхнє поле data вказує на окремий акаунт даних
програми, який містить програмний код. (Дивіться діаграму нижче.)
Акаунт програми з даними. Дані вказують на окремий акаунт даних програми
Під час розгортання або оновлення програми буферні акаунти використовуються для тимчасового розміщення завантаження.
Приклад нижче отримує акаунт Token Program. Зверніть увагу, що поле executable
встановлено як true, що вказує на те, що акаунт є програмою.
import { Address, createSolanaRpc } from "@solana/kit";const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");const programId = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" as Address;const accountInfo = await rpc.getAccountInfo(programId, { encoding: "base64" }).send();console.log(accountInfo);
Акаунти даних
Акаунти даних не містять виконуваного коду. Натомість вони зберігають інформацію.
Акаунт стану програми
Програми використовують акаунти даних для підтримки свого стану. Для цього вони спочатку повинні створити новий акаунт даних. Процес створення акаунта стану програми часто абстрагується, але корисно розуміти основний процес.
Щоб керувати своїм станом, нова програма повинна:
- Викликати System Program для створення акаунта. (System Program потім передає право власності новій програмі.)
- Ініціалізувати дані акаунта, як визначено її інструкціями.
Діаграма акаунта даних, яким володіє акаунт програми
Приклад нижче створює та отримує акаунт Token Mint, яким володіє програма 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);
Системні акаунти
Не всі акаунти отримують нового власника після створення System Program. Акаунти, якими володіє System Program, називаються системними акаунтами. Усі гаманці є системними акаунтами, що дозволяє їм оплачувати комісії за транзакції.
Гаманець, яким володіє System Program, що містить 1 000 000 лампортів
Коли SOL вперше надсилається на нову адресу, на цій адресі створюється акаунт, яким володіє System Program.
У прикладі нижче створюється новий keypair і поповнюється SOL. Після виконання
коду ви можете побачити, що адреса owner облікового запису - це
11111111111111111111111111111111
(System Program).
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 існують за попередньо визначеними адресами і надають доступ до даних про стан кластера. Вони динамічно оновлюються даними про мережевий кластер. Перегляньте повний список облікових записів Sysvar.
У прикладі нижче отримуються та десеріалізуються дані з облікового запису Sysvar Clock.
import { createSolanaRpc } from "@solana/kit";import { fetchSysvarClock, SYSVAR_CLOCK_ADDRESS } from "@solana/sysvars";const rpc = createSolanaRpc("https://api.mainnet-beta.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?