Resumo
Contas de programa contêm código sBPF executável. Contas de dados armazenam estado, pertencentes a programas. Contas de sistema são pertencentes ao System Program. Sysvars fornecem estado do cluster acessível em endereços predefinidos.
O campo executable determina a
categoria de uma conta:
- Contas de programa:
executable=true. Contém código executável. - Contas de dados:
executable=false. Armazena estado ou dados do utilizador.
Esta separação de código do estado mutável significa que um programa é implementado uma vez e pode gerir qualquer número de contas de dados.
Contas de programa
Uma conta de programa armazena código executável. Cada conta de programa é pertencente a um programa carregador. Quando um programa é implementado, o runtime cria uma conta de programa para conter o seu bytecode.
Diagrama de uma conta de programa, os seus 4 componentes e o seu programa carregador.
Contas de dados de programa
Programas implementados usando loader-v3 (consulte
Programas carregadores)
não armazenam bytecode executável no seu próprio campo data. Em vez disso, o
seu data aponta para uma conta de dados de programa separada que contém o
código do programa. (Consulte o diagrama abaixo.)
Uma conta de programa com dados. Os dados apontam para uma conta de dados de programa separada
Durante a implementação ou atualizações do programa, contas de buffer são usadas para temporariamente preparar o carregamento.
O exemplo seguinte obtém a conta do Token Program. O campo executable é
true, confirmando que é uma conta de programa.
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);
Contas de dados
As contas de dados não contêm código executável. Elas armazenam o estado definido pelo programa.
Conta de estado do programa
Os programas armazenam o seu estado em contas de dados. Criar uma conta de estado do programa envolve dois passos:
- Invocar o System Program para criar a conta. O System Program transfere a propriedade para o programa especificado.
- O programa proprietário inicializa o campo
datada conta de acordo com as suas instruções.
Diagrama de uma conta de dados pertencente a uma program account
O exemplo seguinte cria e obtém uma mint account de token pertencente ao programa 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);
Contas do sistema
As contas que permanecem sob propriedade do System Program após a criação são chamadas de contas do sistema. Enviar SOL para um novo endereço pela primeira vez cria uma nova conta nesse endereço pertencente ao System Program.
Todas as contas de carteira são contas do sistema. O pagador de taxas numa transação deve ser uma conta do sistema, porque apenas as contas pertencentes ao System Program podem pagar taxas de transação.
Uma carteira pertencente ao System Program contendo 1.000.000 de lamports
O exemplo seguinte gera um novo keypair, financia-o com SOL e obtém a conta. O
campo owner é 11111111111111111111111111111111 (o
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);
Contas Sysvar
Contas Sysvar são contas especiais em endereços predefinidos que fornecem acesso somente leitura aos dados de estado do cluster. Elas são atualizadas dinamicamente a cada slot.
| Sysvar | Endereço | Finalidade |
|---|---|---|
| Clock | SysvarC1ock11111111111111111111111111111111 | Slot atual, epoch e timestamp Unix |
| EpochSchedule | SysvarEpochSchedu1e111111111111111111111111 | Constantes de agendamento de epoch definidas no genesis |
| EpochRewards | SysvarEpochRewards1111111111111111111111111 | Estado e progresso da distribuição de recompensas de epoch |
| Rent | SysvarRent111111111111111111111111111111111 | Taxa de rent e limite de isenção |
| SlotHashes | SysvarS1otHashes111111111111111111111111111 | Hashes mais recentes dos bancos pai do slot |
| StakeHistory | SysvarStakeHistory1111111111111111111111111 | Ativações e desativações de stake por epoch |
| LastRestartSlot | SysvarLastRestartS1ot1111111111111111111111 | Último slot de reinício do cluster |
| Instructions | Sysvar1nstructions1111111111111111111111111 | Instruções serializadas da transação atual |
| SlotHistory | SysvarS1otHistory11111111111111111111111111 | Registo de quais slots foram produzidos durante o último epoch |
O exemplo a seguir obtém e desserializa a conta 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?