Transacties
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
bestaat uit de volgende informatie:
signatures: Een array van handtekeningenmessage: Transactie-informatie, inclusief de lijst van 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 komt van de IPv6 Maximum Transmission Unit (MTU) grootte van 1280 bytes, minus 48 bytes voor netwerkheaders (40 bytes IPv6 + 8 bytes header).
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 gemaakt door de Message van de transactie te ondertekenen
met de privésleutel van het account. Een handtekening moet worden verstrekt voor
elk ondertekenend 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
Het message van de transactie is een
Message
struct die de volgende informatie bevat:
header: De header van het berichtaccount_keys: Een array van accountadressen die vereist zijn door 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 niet voor elk account afzonderlijk
machtigingen op. In plaats daarvan worden accountmachtigingen 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. Het bevat de volgende informatie:
num_required_signatures: Het totale aantal handtekeningen vereist door de transactienum_readonly_signed_accounts: Het totale aantal alleen-lezen accounts die handtekeningen vereisennum_readonly_unsigned_accounts: Het totale aantal alleen-lezen 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
voorvoegsel 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 volledig zijn en strikt geordend, als
volgt:
- Ondertekenaar + Beschrijfbaar
- Ondertekenaar + Alleen-lezen
- Geen ondertekenaar + Beschrijfbaar
- Geen ondertekenaar + Alleen-lezen
Strikte ordening maakt het mogelijk om de account_keys array te combineren
met de informatie in de header van het bericht om de machtigingen
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
tijdstempel voor de transactie en voorkomt dat transacties worden gedupliceerd.
Een blockhash verloopt na
150 blokken.
(Gelijk aan één minuut—ervan uitgaande dat elk blok 400ms duurt.) Nadat het blok
is verlopen, 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 krijgen waarop
de blockhash geldig zal zijn.
Instructies
De
instructions
van het bericht is een array van alle instructies die verwerkt moeten worden,
verzonden in
compact array format. Het
voorvoegsel 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_keysarray. Deze waarde geeft het adres aan van het programma dat de instructie verwerkt.accounts: Een array van indices die verwijzen naar adressen in deaccount_keysarray. Elke index verwijst naar het adres van een account dat vereist is voor deze instructie.data: Een byte-array die aangeeft welke instructie moet worden aangeroepen op het programma. Het bevat ook eventuele aanvullende gegevens die vereist zijn door 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?