Runtime degli account

Riepilogo

Prima dell'esecuzione, il runtime carica gli account, convalida il pagatore delle commissioni, verifica l'esenzione dall'affitto e serializza i dati degli account in un layout di memoria accessibile ai programmi.

Questa pagina tratta gli aspetti interni del runtime. La maggior parte degli sviluppatori non necessita di queste informazioni per creare programmi. Consulta Struttura degli account per la visione orientata agli sviluppatori.

Caricamento degli account

Prima dell'esecuzione di una transazione, il runtime carica tutti gli account referenziati tramite load_transaction_accounts(). Questo processo esegue diverse convalide:

  1. Convalida del pagatore delle commissioni: il pagatore delle commissioni (primo account) deve esistere, essere un account di sistema o un account nonce e avere abbastanza lamport per coprire le commissioni (validate_fee_payer()). Dopo aver pagato le commissioni, l'account deve rimanere esente dall'affitto oppure arrivare esattamente a 0 lamport. Non può terminare con un valore compreso tra 0 e il minimo per l'esenzione dall'affitto. Gli account nonce devono sempre mantenere abbastanza lamport per rimanere esenti dall'affitto. Se il pagatore non è né un account di sistema né un account nonce, la transazione fallisce con TransactionError::InvalidAccountForFee.

  2. Limite di dimensione dei dati caricati: la dimensione totale di tutti gli account caricati (incluso un TRANSACTION_ACCOUNT_BASE_SIZE di 64 byte per account) non deve superare MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES (64 MiB). Il superamento di questo limite produce TransactionError::MaxLoadedAccountsDataSizeExceeded.

  3. Convalida del program account: ogni programma invocato da un'istruzione deve esistere ed essere di proprietà di un loader valido: uno dei PROGRAM_OWNERS (BPF Loader Upgradeable, BPF Loader, BPF Loader Deprecated, Loader V4) o il loader nativo. Se il program account non esiste, la transazione fallisce con TransactionError::ProgramAccountNotFound. Se esiste ma ha un proprietario non valido, la transazione fallisce con TransactionError::InvalidProgramForExecution.

  4. Account non esistenti: gli account che non esistono on-chain vengono caricati come account predefiniti (0 lamport, dati vuoti, di proprietà del system program) con rent_epoch impostato su u64::MAX.

Formato di serializzazione BPF

Quando un programma viene invocato, il runtime serializza gli account in un buffer di memoria contiguo e lo passa alla BPF VM. Il formato di serializzazione (per il formato allineato standard utilizzato da tutti i loader tranne il loader-v1 deprecato) è definito in serialize_parameters_aligned().

Il buffer inizia con un u64 (8 byte, little-endian) contenente il numero di account. Quindi, per ogni account nell'istruzione, il buffer contiene:

OffsetDimensioneCampoTipo
01marcatore duplicatou8 (0xFF = unico, indice = duplicato di quell'account)
11is_signeru8 (0 o 1)
21is_writableu8 (0 o 1)
31executableu8 (0 o 1)
44original_data_len (riservato, sempre 0)[0u8; 4]
832keyPubkey
4032ownerPubkey
728lamportsu64 (little-endian)
808data_lenu64 (little-endian)
88data_lendata[u8]
88 + data_len10240 + paddingspazio realloc + allineamentoRiempito di zeri fino a MAX_PERMITTED_DATA_INCREASE (10 KiB) + padding per allineare a BPF_ALIGN_OF_U128 (8 byte)
...8rent_epochu64 (little-endian)

Dopo tutti gli account, il buffer aggiunge:

DimensioneCampo
8instruction_data_len (u64, little-endian)
instruction_data_leninstruction_data
32program_id (Pubkey)

Per gli account duplicati, viene scritto solo 1 byte (il marcatore di duplicazione con l'indice dell'originale) più 7 byte di padding.

Deduplicazione degli account

Quando la stessa chiave pubblica dell'account appare più volte nell'array accounts di un'istruzione, il runtime li deduplica. Ogni voce nell'elenco degli account dell'istruzione ottiene la propria struttura InstructionAccount, ma le voci che si riferiscono allo stesso account a livello di transazione puntano agli stessi dati sottostanti.

Il metodo is_instruction_account_duplicate determina se un dato indice di account dell'istruzione è la prima occorrenza o un duplicato cercando l'indice dell'account a livello di transazione e trovando il primo indice a livello di istruzione che vi corrisponde:

  • Se l'indice corrente dell'account dell'istruzione è uguale al primo indice mappato, non è un duplicato (restituisce None).
  • Altrimenti, restituisce Some(first_index), dove first_index è l'indice della prima occorrenza.

Poiché tutti i riferimenti allo stesso account condividono lo stesso AccountSharedData sottostante, le modifiche attraverso qualsiasi riferimento sono immediatamente visibili attraverso tutti gli altri riferimenti. Tuttavia, può essere mantenuto un solo prestito mutabile alla volta. Il tentativo di prendere in prestito lo stesso account in modo mutabile attraverso due indici di account dell'istruzione diversi contemporaneamente restituisce InstructionError::AccountBorrowFailed. I programmi devono rilasciare un prestito prima di acquisirne un altro sullo stesso account sottostante.

Dopo l'esecuzione del programma, il runtime deserializza il buffer (deserialize_parameters_aligned()) e applica eventuali modifiche a lamports, data (incluse le modifiche di lunghezza fino a MAX_PERMITTED_DATA_INCREASE), e owner.

Is this page helpful?

Indice dei contenuti

Modifica pagina

Gestito da

© 2026 Solana Foundation.
Tutti i diritti riservati.
Resta connesso