Transaktionen

Um mit dem Solana-Netzwerk zu interagieren, müssen Sie eine Transaktion senden. Sie können sich eine Transaktion wie einen Umschlag vorstellen, der mehrere Formulare enthält. Jedes Formular ist eine Anweisung, die dem Netzwerk mitteilt, was zu tun ist. Das Senden der Transaktion ist wie das Versenden des Umschlags, damit die Formulare verarbeitet werden können.

Das folgende Beispiel zeigt eine vereinfachte Version von zwei Transaktionen. Wenn die erste Transaktion verarbeitet wird, führt sie eine einzelne Anweisung aus. Wenn die zweite Transaktion verarbeitet wird, führt sie drei Anweisungen in sequentieller Reihenfolge aus: zuerst Anweisung 1, gefolgt von Anweisung 2, gefolgt von Anweisung 3.

Transaktionen sind atomar: Wenn eine einzelne Anweisung fehlschlägt, wird die gesamte Transaktion fehlschlagen und es werden keine Änderungen vorgenommen.

Ein vereinfachtes Diagramm, das zwei Transaktionen zeigtEin vereinfachtes Diagramm, das zwei Transaktionen zeigt

Eine Transaction besteht aus folgenden Informationen:

  • signatures: Ein Array von Signaturen
  • message: Transaktionsinformationen, einschließlich der Liste der zu verarbeitenden Anweisungen
Transaction
pub struct Transaction {
#[wasm_bindgen(skip)]
#[serde(with = "short_vec")]
pub signatures: Vec<Signature>,
#[wasm_bindgen(skip)]
pub message: Message,
}

Diagramm, das die zwei Teile einer Transaktion zeigtDiagramm, das die zwei Teile einer Transaktion zeigt

Transaktionen haben eine Gesamtgrößenbeschränkung von 1232 Bytes. Diese Beschränkung umfasst sowohl das signatures-Array als auch die message-Struktur.

Dieses Limit wurde entwickelt, um Paketfragmentierung in typischer Internet-Infrastruktur zu vermeiden. Obwohl IPv6 MTUs größer als 9000 Bytes unterstützt, verwenden die meisten Internet-Router eine Standard-MTU von 1500 Bytes (Standard-Ethernet). Um sicherzustellen, dass Transaktionen ohne Fragmentierung in ein einzelnes Paket passen, verwendet Solana 1280 Bytes (die für IPv6 erforderliche Mindest-MTU) minus 48 Bytes für Netzwerk-Header (40 Bytes IPv6 + 8 Bytes Fragment/UDP-Header), was zu dem Transaktionsgrößenlimit von 1232 Bytes führt.

Diagramm, das das Transaktionsformat und Größenbegrenzungen zeigtDiagramm, das das Transaktionsformat und Größenbegrenzungen zeigt

Signaturen

Das signatures-Array der Transaktion enthält Signature-Strukturen. Jede Signature ist 64 Bytes groß und wird durch Signieren der Message der Transaktion mit dem privaten Schlüssel des Kontos erstellt. Für jedes Signer-Konto, das in einer der Anweisungen der Transaktion enthalten ist, muss eine Signatur bereitgestellt werden.

Die erste Signatur gehört zu dem Konto, das die Basisgebühr der Transaktion bezahlt und ist die Transaktionssignatur. Die Transaktionssignatur kann verwendet werden, um die Details der Transaktion im Netzwerk nachzuschlagen.

Nachricht

Die message der Transaktion ist eine Message-Struktur, die folgende Informationen enthält:

  • header: Der Nachrichten-Header
  • account_keys: Ein Array von Kontoadressen, die für die Anweisungen der Transaktion erforderlich sind
  • recent_blockhash: Ein Blockhash, der als Zeitstempel für die Transaktion dient
  • instructions: Ein Array von Anweisungen

Um Platz zu sparen, speichert die Transaktion nicht die Berechtigungen für jedes Konto einzeln. Stattdessen werden die Kontoberechtigungen mithilfe des header und der account_keys bestimmt.

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

Der header der Nachricht ist eine MessageHeader-Struktur. Er enthält folgende Informationen:

  • num_required_signatures: Die Gesamtzahl der für die Transaktion erforderlichen Signaturen
  • num_readonly_signed_accounts: Die Gesamtzahl der schreibgeschützten Konten, die Signaturen erfordern
  • num_readonly_unsigned_accounts: Die Gesamtzahl der schreibgeschützten Konten, die keine Signaturen erfordern
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,
}

Diagramm, das die drei Teile des Nachrichtenheaders zeigtDiagramm, das die drei Teile des Nachrichtenheaders zeigt

Kontoadressen

Das account_keys der Nachricht ist ein Array von Kontoadressen, das im Compact-Array-Format gesendet wird. Das Präfix des Arrays gibt dessen Länge an. Jedes Element im Array ist ein öffentlicher Schlüssel, der auf ein Konto verweist, das von seinen Anweisungen verwendet wird. Das accounts_keys-Array muss vollständig und streng geordnet sein, wie folgt:

  1. Signer + Beschreibbar
  2. Signer + Schreibgeschützt
  3. Kein Signer + Beschreibbar
  4. Kein Signer + Schreibgeschützt

Die strikte Reihenfolge ermöglicht es, das account_keys-Array mit den Informationen im header der Nachricht zu kombinieren, um die Berechtigungen für jedes Konto zu bestimmen.

Diagramm, das die Reihenfolge des Kontenadressenfeldes zeigtDiagramm, das die Reihenfolge des Kontenadressenfeldes zeigt

Aktueller Blockhash

Der recent_blockhash der Nachricht ist ein Hash-Wert, der als Transaktions-Zeitstempel fungiert und doppelte Transaktionen verhindert. Ein Blockhash läuft nach 150 Blöcken ab. (Entspricht einer Minute – unter der Annahme, dass jeder Block 400 ms dauert.) Nach Ablauf des Blocks ist die Transaktion abgelaufen und kann nicht mehr verarbeitet werden.

Die RPC-Methode getLatestBlockhash ermöglicht es Ihnen, den aktuellen Blockhash und die letzte Blockhöhe abzurufen, bei der der Blockhash gültig sein wird.

Anweisungen

Die instructions der Nachricht ist ein Array aller zu verarbeitenden Anweisungen, das im Compact-Array-Format gesendet wird. Das Präfix des Arrays gibt dessen Länge an. Jedes Element im Array ist eine CompiledInstruction Struktur und enthält folgende Informationen:

  1. program_id_index: Ein Index, der auf eine Adresse im account_keys-Array verweist. Dieser Wert gibt die Adresse des Programms an, das die Anweisung verarbeitet.
  2. accounts: Ein Array von Indizes, die auf Adressen im account_keys-Array verweisen. Jeder Index verweist auf die Adresse eines Kontos, das für diese Anweisung erforderlich ist.
  3. data: Ein Byte-Array, das angibt, welche Anweisung auf dem Programm aufgerufen werden soll. Es enthält auch alle zusätzlichen Daten, die von der Anweisung benötigt werden. (Zum Beispiel Funktionsargumente)
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>,
}

Kompaktes Array von AnweisungenKompaktes Array von Anweisungen

Beispiel einer Transaktionsstruktur

Das folgende Beispiel zeigt die Struktur einer Transaktion, die eine einzelne SOL-Überweisungsanweisung enthält.

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.

Der folgende Code zeigt die Ausgabe der vorherigen Codeausschnitte. Das Format unterscheidet sich zwischen den SDKs, aber beachte, dass jede Anweisung die gleichen erforderlichen Informationen enthält.

{
"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
}
}
]
}

Nachdem eine Transaktion übermittelt wurde, können Sie ihre Details mithilfe der Transaktionssignatur und der getTransaction RPC-Methode abrufen. Die Antwort wird eine Struktur ähnlich dem folgenden Ausschnitt haben.

Sie können die Transaktion auch über den Solana Explorer finden.

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?

Inhaltsverzeichnis

Seite bearbeiten

Verwaltet von

© 2026 Solana Foundation.
Alle Rechte vorbehalten.
Verbinden Sie sich