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 toontEen vereenvoudigd diagram dat twee transacties toont

Een Transaction bestaat uit de volgende informatie:

  • signatures: Een array van handtekeningen
  • message: Transactie-informatie, inclusief de lijst van instructies die moeten worden verwerkt
Transaction
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 toontDiagram 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 toontDiagram 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 bericht
  • account_keys: Een array van accountadressen die vereist zijn door de instructies van de transactie
  • recent_blockhash: Een blockhash die fungeert als tijdstempel voor de transactie
  • instructions: 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.

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>,
}

De header van het bericht is een MessageHeader struct. Het bevat de volgende informatie:

  • num_required_signatures: Het totale aantal handtekeningen vereist door de transactie
  • num_readonly_signed_accounts: Het totale aantal alleen-lezen accounts die handtekeningen vereisen
  • num_readonly_unsigned_accounts: Het totale aantal alleen-lezen accounts die geen handtekeningen vereisen
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,
}

Diagram met de drie delen van de berichtheaderDiagram 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:

  1. Ondertekenaar + Beschrijfbaar
  2. Ondertekenaar + Alleen-lezen
  3. Geen ondertekenaar + Beschrijfbaar
  4. 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 toontDiagram 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:

  1. program_id_index: Een index die verwijst naar een adres in de account_keys array. Deze waarde geeft het adres aan van het programma dat de instructie verwerkt.
  2. accounts: Een array van indices die verwijzen naar adressen in de account_keys array. Elke index verwijst naar het adres van een account dat vereist is voor deze instructie.
  3. 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)
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>,
}

Compacte array van instructiesCompacte 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 keypairs
const sender = await generateKeyPairSigner();
const recipient = await generateKeyPairSigner();
// Define the amount to transfer
const 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 recipient
const transferInstruction = getTransferSolInstruction({
source: sender,
destination: recipient.address,
amount: transferAmount
});
// Create transaction message
const transactionMessage = pipe(
createTransactionMessage({ version: 0 }),
(tx) => setTransactionMessageFeePayerSigner(sender, tx),
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
(tx) => appendTransactionMessageInstructions([transferInstruction], tx)
);
const signedTransaction =
await signTransactionMessageWithSigners(transactionMessage);
// Decode the messageBytes
const compiledTransactionMessage =
getCompiledTransactionMessageDecoder().decode(signedTransaction.messageBytes);
console.log(JSON.stringify(compiledTransactionMessage, null, 2));
Console
Click to execute the code.

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.

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?

Inhoudsopgave

Pagina Bewerken

Beheerd door

© 2025 Solana Foundation.
Alle rechten voorbehouden.
Blijf Verbonden