Transazioni
Per interagire con la rete Solana, devi inviare una transazione. Puoi pensare a una transazione come a una busta che contiene diversi moduli. Ogni modulo è un'istruzione che dice alla rete cosa fare. Inviare la transazione è come spedire la busta affinché i moduli possano essere elaborati.
L'esempio seguente mostra una versione semplificata di due transazioni. Quando la prima transazione viene elaborata, eseguirà una singola istruzione. Quando la seconda transazione viene elaborata, eseguirà tre istruzioni in ordine sequenziale: prima l'istruzione 1, seguita dall'istruzione 2, seguita dall'istruzione 3.
Le transazioni sono atomiche: se una singola istruzione fallisce, l'intera transazione fallirà e non avverrà alcuna modifica.
Un diagramma semplificato che mostra due transazioni
Una
Transaction
consiste nelle seguenti informazioni:
signatures: Un array di firmemessage: Informazioni sulla transazione, inclusa la lista di istruzioni da elaborare
Transaction
pub struct Transaction {#[wasm_bindgen(skip)]#[serde(with = "short_vec")]pub signatures: Vec<Signature>,#[wasm_bindgen(skip)]pub message: Message,}
Diagramma che mostra le due parti di una transazione
Le transazioni hanno un limite di dimensione totale di
1232
byte. Questo limite include sia l'array signatures che la
struttura message.
Questo limite deriva dalla dimensione dell'unità massima di trasmissione (MTU) IPv6 di 1280 byte, meno 48 byte per le intestazioni di rete (40 byte IPv6 + 8 byte di intestazione).
Diagramma che mostra il formato della transazione e i limiti di dimensione
Firme
L'array signatures della transazione contiene strutture Signature. Ogni
Signature
è di 64 byte e viene creata firmando il Message della transazione con la
chiave privata dell'account. Una firma deve essere fornita per ogni
account firmatario incluso in qualsiasi istruzione della
transazione.
La prima firma appartiene all'account che pagherà la commissione base della transazione ed è la firma della transazione. La firma della transazione può essere utilizzata per cercare i dettagli della transazione sulla rete.
Messaggio
Il message della transazione è una struttura
Message
che contiene le seguenti informazioni:
header: L'intestazione del messaggioaccount_keys: Un array di indirizzi di account richiesti dalle istruzioni della transazionerecent_blockhash: Un blockhash che funge da timestamp per la transazioneinstructions: Un array di istruzioni
Per risparmiare spazio, la transazione non memorizza i permessi per ogni
account individualmente. Invece, i permessi degli account sono determinati
utilizzando il header e gli account_keys.
Message
pub struct Message {/// The message header, identifying signed and read-only `account_keys`.pub header: MessageHeader,/// All the account keys used by this transaction.#[serde(with = "short_vec")]pub account_keys: Vec<Pubkey>,/// The id of a recent ledger entry.pub recent_blockhash: Hash,/// Programs that will be executed in sequence and committed in/// one atomic transaction if all succeed.#[serde(with = "short_vec")]pub instructions: Vec<CompiledInstruction>,}
Intestazione
Il header del messaggio è una struttura
MessageHeader.
Contiene le seguenti informazioni:
num_required_signatures: Il numero totale di firme richieste dalla transazionenum_readonly_signed_accounts: Il numero totale di account di sola lettura che richiedono firmenum_readonly_unsigned_accounts: Il numero totale di account di sola lettura che non richiedono firme
MessageHeader
pub struct MessageHeader {/// The number of signatures required for this message to be considered/// valid. The signers of those signatures must match the first/// `num_required_signatures` of [`Message::account_keys`].pub num_required_signatures: u8,/// The last `num_readonly_signed_accounts` of the signed keys are read-only/// accounts.pub num_readonly_signed_accounts: u8,/// The last `num_readonly_unsigned_accounts` of the unsigned keys are/// read-only accounts.pub num_readonly_unsigned_accounts: u8,}
Diagramma che mostra le tre parti dell'intestazione del messaggio
Indirizzi degli account
Gli
account_keys
del messaggio sono un array di indirizzi di account, inviati in
formato array compatto. Il
prefisso dell'array indica la sua lunghezza. Ogni elemento nell'array è una
chiave pubblica, che punta a un account utilizzato dalle sue istruzioni. L'array
accounts_keys deve essere completo e rigorosamente ordinato come segue:
- Firmatario + Scrivibile
- Firmatario + Sola lettura
- Non firmatario + Scrivibile
- Non firmatario + Sola lettura
L'ordinamento rigoroso consente all'array account_keys di essere combinato
con le informazioni nell'header del messaggio per determinare i
permessi per ciascun account.
Diagramma che mostra l'ordine dell'array degli indirizzi degli account
Blockhash recente
Il recent_blockhash del messaggio è un valore hash che funge da timestamp
della transazione e previene transazioni duplicate. Un blockhash scade dopo
150 blocchi.
(Equivalente a un minuto—assumendo che ogni blocco duri 400ms.) Dopo la scadenza
del blocco, la transazione è scaduta e non può essere elaborata.
Il metodo RPC getLatestBlockhash ti
permette di ottenere il blockhash corrente e l'altezza dell'ultimo blocco in
cui il blockhash sarà valido.
Istruzioni
Il
instructions
del messaggio è un array di tutte le istruzioni da elaborare, inviate in
formato array compatto. Il
prefisso dell'array indica la sua lunghezza. Ogni elemento nell'array è una
struttura
CompiledInstruction
e include le seguenti informazioni:
program_id_index: Un indice che punta a un indirizzo nell'arrayaccount_keys. Questo valore indica l'indirizzo del programma che elabora l'istruzione.accounts: Un array di indici che puntano agli indirizzi nell'arrayaccount_keys. Ogni indice punta all'indirizzo di un account richiesto per questa istruzione.data: Un array di byte che specifica quale istruzione invocare sul programma. Include anche qualsiasi dato aggiuntivo richiesto dall'istruzione. (Ad esempio, argomenti della funzione)
CompiledInstruction
pub struct CompiledInstruction {/// Index into the transaction keys array indicating the program account that executes this instruction.pub program_id_index: u8,/// Ordered indices into the transaction keys array indicating which accounts to pass to the program.#[serde(with = "short_vec")]pub accounts: Vec<u8>,/// The program input data.#[serde(with = "short_vec")]pub data: Vec<u8>,}
Array compatto di istruzioni
Struttura di esempio della transazione
Il seguente esempio mostra la struttura di una transazione che contiene una singola istruzione di trasferimento SOL.
import {createSolanaRpc,generateKeyPairSigner,lamports,createTransactionMessage,setTransactionMessageFeePayerSigner,setTransactionMessageLifetimeUsingBlockhash,appendTransactionMessageInstructions,pipe,signTransactionMessageWithSigners,getCompiledTransactionMessageDecoder} from "@solana/kit";import { getTransferSolInstruction } from "@solana-program/system";const rpc = createSolanaRpc("http://localhost:8899");const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();// Generate sender and recipient keypairsconst sender = await generateKeyPairSigner();const recipient = await generateKeyPairSigner();// Define the amount to transferconst LAMPORTS_PER_SOL = 1_000_000_000n;const transferAmount = lamports(LAMPORTS_PER_SOL / 100n); // 0.01 SOL// Create a transfer instruction for transferring SOL from sender to recipientconst transferInstruction = getTransferSolInstruction({source: sender,destination: recipient.address,amount: transferAmount});// Create transaction messageconst transactionMessage = pipe(createTransactionMessage({ version: 0 }),(tx) => setTransactionMessageFeePayerSigner(sender, tx),(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),(tx) => appendTransactionMessageInstructions([transferInstruction], tx));const signedTransaction =await signTransactionMessageWithSigners(transactionMessage);// Decode the messageBytesconst compiledTransactionMessage =getCompiledTransactionMessageDecoder().decode(signedTransaction.messageBytes);console.log(JSON.stringify(compiledTransactionMessage, null, 2));
Console
Click to execute the code.
Il codice seguente mostra l'output degli snippet di codice precedenti. Il formato differisce tra gli SDK, ma nota che ogni istruzione contiene le stesse informazioni richieste.
{"version": 0,"header": {"numSignerAccounts": 1,"numReadonlySignerAccounts": 0,"numReadonlyNonSignerAccounts": 1},"staticAccounts": ["HoCy8p5xxDDYTYWEbQZasEjVNM5rxvidx8AfyqA4ywBa","5T388jBjovy7d8mQ3emHxMDTbUF8b7nWvAnSiP3EAdFL","11111111111111111111111111111111"],"lifetimeToken": "EGCWPUEXhqHJWYBfDirq3mHZb4qDpATmYqBZMBy9TBC1","instructions": [{"programAddressIndex": 2,"accountIndices": [0, 1],"data": {"0": 2,"1": 0,"2": 0,"3": 0,"4": 128,"5": 150,"6": 152,"7": 0,"8": 0,"9": 0,"10": 0,"11": 0}}]}
Dopo che una transazione è stata inviata, puoi recuperare i suoi dettagli utilizzando la firma della transazione e il metodo RPC getTransaction. La risposta avrà una struttura simile al seguente snippet.
Puoi anche trovare la transazione utilizzando Solana Explorer.
Transaction Data
{"blockTime": 1745196488,"meta": {"computeUnitsConsumed": 150,"err": null,"fee": 5000,"innerInstructions": [],"loadedAddresses": {"readonly": [],"writable": []},"logMessages": ["Program 11111111111111111111111111111111 invoke [1]","Program 11111111111111111111111111111111 success"],"postBalances": [989995000, 10000000, 1],"postTokenBalances": [],"preBalances": [1000000000, 0, 1],"preTokenBalances": [],"rewards": [],"status": {"Ok": null}},"slot": 13049,"transaction": {"message": {"header": {"numReadonlySignedAccounts": 0,"numReadonlyUnsignedAccounts": 1,"numRequiredSignatures": 1},"accountKeys": ["8PLdpLxkuv9Nt8w3XcGXvNa663LXDjSrSNon4EK7QSjQ","7GLg7bqgLBv1HVWXKgWAm6YoPf1LoWnyWGABbgk487Ma","11111111111111111111111111111111"],"recentBlockhash": "7ZCxc2SDhzV2bYgEQqdxTpweYJkpwshVSDtXuY7uPtjf","instructions": [{"accounts": [0, 1],"data": "3Bxs4NN8M2Yn4TLb","programIdIndex": 2,"stackHeight": null}],"indexToProgramIds": {}},"signatures": ["3jUKrQp1UGq5ih6FTDUUt2kkqUfoG2o4kY5T1DoVHK2tXXDLdxJSXzuJGY4JPoRivgbi45U2bc7LZfMa6C4R3szX"]},"version": "legacy"}
Is this page helpful?