Resumen
Las cuentas de programa contienen código ejecutable sBPF. Las cuentas de datos almacenan estado, propiedad de los programas. Las cuentas del sistema son propiedad del System Program. Los sysvars proporcionan estado del clúster accesible en direcciones predefinidas.
El campo executable determina la
categoría de una cuenta:
- Cuentas de programa:
executable=true. Contiene código ejecutable. - Cuentas de datos:
executable=false. Almacena estado o datos de usuario.
Esta separación del código del estado mutable significa que un programa se despliega una vez y puede gestionar cualquier número de cuentas de datos.
Cuentas de programa
Una cuenta de programa almacena código ejecutable. Cada cuenta de programa es propiedad de un programa cargador. Cuando un programa se despliega, el runtime crea una cuenta de programa para contener su bytecode.
Diagrama de una cuenta de programa, sus 4 componentes y su programa cargador.
Cuentas de datos de programa
Los programas desplegados usando loader-v3 (ver
Programas cargadores) no
almacenan bytecode ejecutable en su propio campo data. En su lugar, su data
apunta a una cuenta de datos de programa separada que contiene el código del
programa. (Ver el diagrama a continuación.)
Una cuenta de programa con datos. Los datos apuntan a una cuenta de datos de programa separada
Durante el despliegue o las actualizaciones del programa, se utilizan cuentas de búfer para preparar temporalmente la carga.
El siguiente ejemplo obtiene la cuenta del Token Program. El campo executable
es true, confirmando que es una cuenta 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);
Cuentas de datos
Las cuentas de datos no contienen código ejecutable. Almacenan el estado definido por el programa.
Cuenta de estado del programa
Los programas almacenan su estado en cuentas de datos. Crear una cuenta de estado del programa implica dos pasos:
- Invocar el System Program para crear la cuenta. El System Program transfiere la propiedad al programa especificado.
- El programa propietario inicializa el campo
datade la cuenta según sus instrucciones.
Diagrama de una cuenta de datos propiedad de una cuenta de programa
El siguiente ejemplo crea y obtiene una mint account de token propiedad del 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);
Cuentas del sistema
Las cuentas que permanecen propiedad del System Program después de su creación se llaman cuentas del sistema. Enviar SOL a una nueva dirección por primera vez crea una nueva cuenta en esa dirección propiedad del System Program.
Todas las cuentas de billetera son cuentas del sistema. El pagador de comisiones en una transacción debe ser una cuenta del sistema, porque solo las cuentas propiedad del System Program pueden pagar comisiones de transacción.
Una billetera propiedad del System Program que contiene 1 000 000 lamports
El siguiente ejemplo genera un nuevo keypair, lo financia con SOL y obtiene la
cuenta. El campo owner es 11111111111111111111111111111111 (el
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);
Cuentas sysvar
Las cuentas sysvar son cuentas especiales en direcciones predefinidas que proporcionan acceso de solo lectura a los datos del estado del clúster. Se actualizan dinámicamente cada slot.
| Sysvar | Dirección | Propósito |
|---|---|---|
| Clock | SysvarC1ock11111111111111111111111111111111 | Slot actual, epoch y marca de tiempo Unix |
| EpochSchedule | SysvarEpochSchedu1e111111111111111111111111 | Constantes de programación de epoch establecidas en génesis |
| EpochRewards | SysvarEpochRewards1111111111111111111111111 | Estado y progreso de la distribución de recompensas de epoch |
| Rent | SysvarRent111111111111111111111111111111111 | Tasa de rent y umbral de exención |
| SlotHashes | SysvarS1otHashes111111111111111111111111111 | Hashes más recientes de los bancos padre del slot |
| StakeHistory | SysvarStakeHistory1111111111111111111111111 | Activaciones y desactivaciones de stake por epoch |
| LastRestartSlot | SysvarLastRestartS1ot1111111111111111111111 | Último slot de reinicio del clúster |
| Instructions | Sysvar1nstructions1111111111111111111111111 | Instrucciones serializadas de la transacción actual |
| SlotHistory | SysvarS1otHistory11111111111111111111111111 | Registro de qué slots se produjeron durante el último epoch |
El siguiente ejemplo obtiene y deserializa la cuenta 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?