Résumé
Les comptes de programme contiennent du code sBPF exécutable. Les comptes de données stockent l'état, détenus par les programmes. Les comptes système sont détenus par le System Program. Les sysvars fournissent un état à l'échelle du cluster accessible à des adresses prédéfinies.
Le champ executable détermine la
catégorie d'un compte :
- Comptes de programme :
executable=true. Contient du code exécutable. - Comptes de données :
executable=false. Stocke l'état ou les données utilisateur.
Cette séparation du code et de l'état mutable signifie qu'un programme est déployé une seule fois et peut gérer un nombre illimité de comptes de données.
Comptes de programme
Un compte de programme stocke du code exécutable. Chaque compte de programme est détenu par un programme chargeur. Lorsqu'un programme est déployé, le runtime crée un compte de programme pour contenir son bytecode.
Diagramme d'un compte de programme, ses 4 composants et son programme chargeur.
Comptes de données de programme
Les programmes déployés avec loader-v3 (voir
Programmes chargeurs) ne
stockent pas le bytecode exécutable dans leur propre champ data. Au lieu de
cela, leur data pointe vers un compte de données de programme séparé qui
contient le code du programme. (Voir le diagramme ci-dessous.)
Un compte de programme avec des données. Les données pointent vers un compte de données de programme séparé
Pendant le déploiement ou les mises à niveau du programme, des comptes tampons sont utilisés pour préparer temporairement le téléchargement.
L'exemple suivant récupère le compte du Token Program. Le champ executable est
true, confirmant qu'il s'agit d'un compte de programme.
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);
Comptes de données
Les comptes de données ne contiennent pas de code exécutable. Ils stockent l'état défini par le programme.
Compte d'état de programme
Les programmes stockent leur état dans des comptes de données. La création d'un compte d'état de programme implique deux étapes :
- Invoquer le System Program pour créer le compte. Le System Program transfère la propriété au programme spécifié.
- Le programme propriétaire initialise le champ
datadu compte selon ses instructions.
Diagramme d'un compte de données détenu par un program account
L'exemple suivant crée et récupère un mint account de jeton détenu par le programme 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);
Comptes système
Les comptes qui restent détenus par le System Program après leur création sont appelés comptes système. L'envoi de SOL vers une nouvelle adresse pour la première fois crée un nouveau compte à cette adresse détenu par le System Program.
Tous les comptes de portefeuille sont des comptes système. Le payeur de frais d'une transaction doit être un compte système, car seuls les comptes détenus par le System Program peuvent payer les frais de transaction.
Un portefeuille détenu par le System Program contenant 1 000 000 lamports
L'exemple suivant génère une nouvelle keypair, la finance avec des SOL et
récupère le compte. Le champ owner est 11111111111111111111111111111111 (le
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);
Comptes sysvar
Les comptes sysvar sont des comptes spéciaux à des adresses prédéfinies qui fournissent un accès en lecture seule aux données d'état du cluster. Ils se mettent à jour dynamiquement à chaque slot.
| Sysvar | Adresse | Objectif |
|---|---|---|
| Clock | SysvarC1ock11111111111111111111111111111111 | Slot actuel, epoch et horodatage Unix |
| EpochSchedule | SysvarEpochSchedu1e111111111111111111111111 | Constantes de planification d'epoch définies dans la genèse |
| EpochRewards | SysvarEpochRewards1111111111111111111111111 | Statut et progression de la distribution des récompenses d'epoch |
| Rent | SysvarRent111111111111111111111111111111111 | Taux de rent et seuil d'exonération |
| SlotHashes | SysvarS1otHashes111111111111111111111111111 | Hachages les plus récents des banques parentes du slot |
| StakeHistory | SysvarStakeHistory1111111111111111111111111 | Activations et désactivations de stake par epoch |
| LastRestartSlot | SysvarLastRestartS1ot1111111111111111111111 | Dernier slot de redémarrage du cluster |
| Instructions | Sysvar1nstructions1111111111111111111111111 | Instructions sérialisées de la transaction en cours |
| SlotHistory | SysvarS1otHistory11111111111111111111111111 | Enregistrement des slots produits au cours du dernier epoch |
L'exemple suivant récupère et désérialise le compte 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?