Om met het Solana-netwerk te communiceren, moet je een transactie versturen. Je kunt een transactie zien als een envelop die verschillende formulieren bevat. Elk formulier is een instructie die het netwerk vertelt wat te doen. Het versturen van de transactie is als het posten van de envelop zodat de formulieren kunnen worden verwerkt.
Het onderstaande voorbeeld toont een vereenvoudigde versie van twee transacties. Wanneer de eerste transactie wordt verwerkt, zal deze één enkele instructie uitvoeren. Wanneer de tweede transactie wordt verwerkt, zal deze drie instructies in opeenvolgende volgorde uitvoeren: eerst instructie 1, gevolgd door instructie 2, gevolgd door instructie 3.
Transacties zijn atomair: als een enkele instructie mislukt, zal de hele transactie mislukken en zullen er geen wijzigingen plaatsvinden.
Een vereenvoudigd diagram dat twee transacties toont
Een
Transaction
bevat de volgende informatie:
signatures: een array van handtekeningenmessage: transactie-informatie, inclusief de lijst met instructies die moeten worden verwerkt
pub struct Transaction {#[wasm_bindgen(skip)]#[serde(with = "short_vec")]pub signatures: Vec<Signature>,#[wasm_bindgen(skip)]pub message: Message,}
Diagram dat de twee delen van een transactie toont
Transacties hebben een totale groottelimiet van
1232
bytes. Deze limiet omvat zowel de signatures array als de
message struct.
Deze limiet is ontworpen om pakketfragmentatie op typische internetinfrastructuur te voorkomen. Hoewel IPv6 MTU's groter dan 9000 bytes ondersteunt, gebruiken de meeste internetrouters een standaard MTU van 1500 bytes (standaard Ethernet). Om ervoor te zorgen dat transacties binnen één pakket passen zonder fragmentatie, gebruikt Solana 1280 bytes (de minimale MTU vereist voor IPv6) minus 48 bytes voor netwerkheaders (40 bytes IPv6 + 8 bytes fragment/UDP-header), wat resulteert in de transactiegrootte limiet van 1232 bytes.
Diagram dat het transactieformaat en de groottelimieten toont
Handtekeningen
De signatures array van de transactie bevat Signature structs. Elke
Signature
is 64 bytes en wordt aangemaakt door de Message van de transactie te
ondertekenen met de private key van het account. Een handtekening moet worden
verstrekt voor elk signer account dat is opgenomen in een
van de instructies van de transactie.
De eerste handtekening behoort tot het account dat de basistarieven van de transactie zal betalen en is de transactiehandtekening. De transactiehandtekening kan worden gebruikt om de details van de transactie op het netwerk op te zoeken.
Bericht
De message van de transactie is een
Message
struct die de volgende informatie bevat:
header: de bericht headeraccount_keys: een array van accountadressen die vereist zijn voor de instructies van de transactierecent_blockhash: een blockhash die fungeert als tijdstempel voor de transactieinstructions: een array van instructies
Om ruimte te besparen, slaat de transactie geen rechten op voor elk account
afzonderlijk. In plaats daarvan worden accountrechten bepaald met behulp van
de header en account_keys.
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>,}
Header
De header van het bericht is een
MessageHeader
struct. Deze bevat de volgende informatie:
num_required_signatures: het totale aantal handtekeningen dat vereist is voor de transactienum_readonly_signed_accounts: het totale aantal read-only accounts die handtekeningen vereisennum_readonly_unsigned_accounts: het totale aantal read-only accounts die geen handtekeningen vereisen
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,}
Diagram met de drie delen van de berichtheader
Accountadressen
De
account_keys
van het bericht is een array van accountadressen, verzonden in
compact array-formaat. Het
prefix van de array geeft de lengte aan. Elk item in de array is een publieke
sleutel die verwijst naar een account dat door de instructies wordt gebruikt. De
accounts_keys-array moet compleet en strikt geordend zijn, als volgt:
- Ondertekenaar + Beschrijfbaar
- Ondertekenaar + Alleen-lezen
- Geen ondertekenaar + Beschrijfbaar
- Geen ondertekenaar + Alleen-lezen
Strikte ordening stelt de account_keys-array in staat om gecombineerd te
worden met de informatie in de header van het bericht om de
rechten voor elk account te bepalen.
Diagram dat de volgorde van de array met accountadressen toont
Recente blockhash
De recent_blockhash van het bericht is een hashwaarde die fungeert als een
transactie- tijdstempel en dubbele transacties voorkomt. Een blockhash verloopt
na
150 blokken.
(Equivalent aan één minuut—ervan uitgaande dat elk blok 400ms duurt.) Nadat het
blok verloopt, is de transactie verlopen en kan deze niet meer worden verwerkt.
De getLatestBlockhash RPC-methode stelt
je in staat om de huidige blockhash en de laatste blokhoogte te verkrijgen
waarop de blockhash geldig zal zijn.
Instructies
De
instructions
van het bericht is een array van alle instructies die moeten worden verwerkt,
verzonden in
compact array-formaat. Het
prefix van de array geeft de lengte aan. Elk item in de array is een
CompiledInstruction
struct en bevat de volgende informatie:
program_id_index: Een index die verwijst naar een adres in deaccount_keys-array. Deze waarde geeft het adres aan van het programma dat de instructie verwerkt.accounts: Een array van indices die verwijzen naar adressen in deaccount_keys-array. Elke index verwijst naar het adres van een account dat vereist is voor deze instructie.data: Een byte-array die specificeert welke instructie moet worden aangeroepen op het programma. Het bevat ook eventuele aanvullende gegevens die vereist zijn voor de instructie. (Bijvoorbeeld functieargumenten)
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>,}
Compacte array van instructies
Voorbeeld transactiestructuur
Het volgende voorbeeld toont de structuur van een transactie die een enkele SOL-overdrachtsinstructie bevat.
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));
De onderstaande code toont de uitvoer van de vorige codefragmenten. Het formaat verschilt tussen SDK's, maar merk op dat elke instructie dezelfde vereiste informatie bevat.
{"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}}]}
Nadat een transactie is ingediend, kun je de details ervan ophalen met behulp van de transactiehandtekening en de getTransaction RPC-methode. De respons zal een structuur hebben die vergelijkbaar is met het volgende fragment.
Je kunt de transactie ook vinden met behulp van Solana Explorer.
{"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?