Versionierte Transaktionen

Zusammenfassung

Solana verfügt über drei Transaktionsformate: legacy, v0 und v1. v0 fügt Address Lookup Tables (ALTs) hinzu, um Konten über 1-Byte-Indizes zu referenzieren. v1 erhöht das Größenlimit auf 4.096 Bytes, verschiebt Ressourcenlimits in die Nachricht selbst und entfernt ALTs.

Solana unterstützt drei Transaktionsformate: legacy, v0 und v1. Jedes Format wird nachfolgend anhand derselben drei Aspekte beschrieben: der Byte-Anordnung auf der Leitung, der Art der Kontenreferenzierung und der Herkunft der Ressourcenlimits.

Aktivierungsstatus v1

Das v1-Format ist noch auf keinem Cluster aktiv. Die Aktivierung ist für Agave v4.2 geplant. solana-test-validator 4.2+ ermöglicht das lokale Testen von v1-Transaktionen. Bestehende Apps sollten die Vorbereitung auf v1 prüfen.

Formatvergleich

Limitlegacyv0v1
Maximale Transaktionsgröße1.232 Bytes1.232 Bytes4.096 Bytes
Kontenadressen~32, größenbegrenzt64, über Lookup-Tabellen64, inline
Address Lookup Tablesnicht unterstütztunterstütztnicht unterstützt
RessourcenlimitsComputeBudget- AnweisungenComputeBudget- AnweisungenNachrichtenkonfiguration

Weiter zu: Legacy · v0 · v1

Legacy-Format

Das ursprüngliche Format und nach wie vor der Standard in den meisten Tools. Es hat kein Versionspräfix: Das erste Byte der Transaktion ist die compact-u16-Anzahl des Signatur-Arrays, und das erste Byte der Nachricht ist num_required_signatures, dessen höchstes Bit immer nicht gesetzt ist.

Legacy-Leitungsformat

FeldGrößeBeschreibung
num_signaturescompact-u16Anzahl der Signaturen
signaturesnum_signatures x 64 BytesEd25519-Signaturen
header3 BytesMessageHeader — erstes Byte hat Versionsbit nicht gesetzt
num_account_keyscompact-u16Anzahl der Kontenschlüssel
account_keysnum_account_keys x 32 BytesÖffentliche Schlüssel, alle inline
recent_blockhash32 BytesLebensdauer-Bezeichner
num_instructionscompact-u16Anzahl der Anweisungen
instructionsvariabelJede Anweisung fortlaufend serialisiert

Jedem Array variabler Länge ist eine compact-u16-Länge vorangestellt: 1 Byte für Werte 0–127, 2–3 Bytes für größere Werte. Das Format pro Anweisung und eine Beispielgrößenberechnung finden Sie unter Transaktions-Binärformat.

Konten in legacy

Jedes Konto wird als vollständiger 32-Byte-Public-Key in account_keys geschrieben, und Anweisungen referenzieren sie über einen 1-Byte-Index in diesem Array. Es gibt keine Möglichkeit, ein Konto zu referenzieren, das nicht explizit in der Transaktion angegeben ist – dies begrenzt eine Legacy-Transaktion auf ungefähr 32 Konten, bevor die 1.232 Bytes ausgeschöpft sind.

Ressourcenlimits in legacy

Compute-Unit-Limit, Datenlimit für geladene Konten, Heap-Größe und priority fee werden alle durch das Einbinden von ComputeBudget-Programm- Anweisungen in die Transaktion angefordert. Jede kostet einen Anweisungs-slot und 150 Compute Units. Das Weglassen ist sicher: Die Laufzeit fällt auf Standardwerte zurück: 200.000 CU pro Anweisung (max. 1,4 M), ein 64-MiB-Datenlimit, einen 32-KiB-Heap und eine priority fee von null.

V0-Format

v0 ist eine Legacy-Nachricht plus zwei Ergänzungen: ein 0x80-Versionspräfix-Byte und ein address_table_lookups-Array, das nach den Anweisungen angehängt wird. Alles davor ist byteidentisch mit legacy.

V0-Leitungsformat

FeldGrößeBeschreibung
num_signaturescompact-u16Anzahl der Signaturen
signaturesnum_signatures x 64 BytesEd25519-Signaturen
0x801 ByteVersionspräfix-Byte — erstes Byte der Nachricht
header3 BytesMessageHeader (wie bei Legacy)
num_account_keyscompact-u16Anzahl der statischen Kontenschlüssel
static_account_keysnum_account_keys x 32 BytesSchlüssel, die wörtlich in der Transaktion erscheinen
recent_blockhash32 BytesLebensdauer-Bezeichner
num_instructionscompact-u16Anzahl der Anweisungen
instructionsvariabelGleiches Format wie Legacy
address_table_lookupscompact-u16 + variabelALT-Referenzen (siehe unten)

Jeder Eintrag in der Adress-Lookup-Tabelle enthält:

FeldGrößeBeschreibung
account_key32 BytesDer öffentliche Schlüssel des ALT-Kontos
writable_indexescompact-u16 + N x 1 ByteIndizes in die ALT für beschreibbare Konten
readonly_indexescompact-u16 + N x 1 ByteIndizes in die ALT für schreibgeschützte Konten

Address Lookup Tables

Eine ALT ist ein On-Chain-Konto, das bis zu 256 öffentliche Schlüssel speichert. Durch die Referenzierung einer ALT kann eine Transaktion zusätzliche Konten mithilfe von 1-Byte-Indizes anstelle von 32-Byte-Public-Keys einbinden, wodurch der Overhead pro Konto erheblich reduziert wird.

Zur Laufzeit, vor Beginn der Ausführung, löst der Validator alle ALT-Referenzen in vollständige öffentliche Schlüssel auf. Die aufgelösten Adressen werden an die statischen Kontenschlüssel angehängt, um die vollständige Liste der Kontenschlüssel zu bilden. ALT-aufgelöste Konten folgen derselben Reihenfolge wie statische Konten: beschreibbare Lookups kommen vor schreibgeschützten Lookups.

Adress-Lookup-Tabellen beeinflussen nur, wie Konten in der On-Wire-Transaktion referenziert werden. Zur Ausführungszeit löst die Runtime alle Indizes in vollständige Kontenadressen auf. ALT-aufgelöste Konten können nur beschreibbar oder schreibgeschützt (nicht signierend) sein; sie können keine Signierer sein.

Ressourcenlimits in v0

Unverändert gegenüber legacy: ComputeBudget- Anweisungen, mit denselben Standardwerten, wenn sie weggelassen werden.

V1-Format

v1 erhöht das Größenlimit auf 4.096 Bytes und strukturiert die Nachricht um eine Transaktionskonfiguration herum: Ressourcenlimits werden aus den ComputeBudget- Anweisungen herausgelöst und in fest positionierte Felder der Nachricht selbst verschoben. Dadurch kann das Netzwerk eine Transaktion nach priority fee durch einen einzelnen Lesevorgang mit festem Offset priorisieren, anstatt dessen Anweisungsliste zu durchsuchen und zu deserialisieren.

V1-Leitungsformat

FeldGrößeBeschreibung
0x811 ByteVersionspräfix-Byte — das erste Byte der Transaktion
header3 BytesMessageHeader (wie bei legacy)
config_mask4 Bytesu32 LE-Bitmaske, die angibt, welche Konfigurationswerte vorhanden sind
recent_blockhash32 BytesLebensdauer-Bezeichner
num_instructions1 ByteFest codierte Anzahl, max. 64
num_addresses1 ByteFest codierte Anzahl, max. 64
addressesN x 32 BytesKontenadressen, alle inline — keine Lookup-Table-Referenzen
config_values0–20 BytesEin Wert pro gesetztem Maskenbit, in Bit-Reihenfolge (siehe unten)
instruction_headersN x 4 BytesPro Anweisung: program_id_index (u8), num_accounts (u8), data_len (u16 LE)
instruction_payloadsvariabelPro Anweisung: Kontenindizes, dann instruction data
signaturesN x 64 BytesAm Ende, ohne Längenpräfix — die Anzahl ergibt sich aus dem Header

Beim Schreiben eines Decoders sind zwei strukturelle Unterschiede gegenüber legacy und v0 zu beachten. Die Zählfelder sind fest codierte u8-Felder statt compact-u16, und die Anweisungen sind in zwei Blöcke aufgeteilt: zunächst alle Header fester Größe, dann alle Payloads variabler Länge, anstatt dass jede Anweisung fortlaufend steht.

Konten in v1: keine Address Lookup Tables

v1 entfernt ALT-Unterstützung absichtlich. 64 rohe Adressen entsprechen 2.048 Bytes – bequem innerhalb des 4.096-Byte-Limits – daher ist jede Adresse inline wie in legacy. Wenn Ihre Anwendung auf Lookup-Tabellen angewiesen ist, bedeutet der Wechsel zu v1, diese Adressen einzubetten.

Ressourcenlimits in v1: die Transaktionskonfiguration

Die Konfiguration besteht aus einer u32-Bitmaske gefolgt von fest codierten Werten für jedes Feld, dessen Bit gesetzt ist:

Bit(s)FeldBreiteHinweise
0–1Priority feeu64Gesamt-lamports — beide Bits gemeinsam gesetzt
2Compute-Unit-Limitu32
3Datenlimit für geladene Kontenu32
4Angeforderter Heap-Speicheru32

Unbekannte Bits werden abgelehnt. Da die Nachricht signiert ist, können nicht erkannte Konfigurationsfelder nicht stillschweigend verworfen werden.

Priority fee ist Gesamt-lamports, kein Preis

In legacy und v0 wird die priority fee über SetComputeUnitPrice als Micro-lamports pro Compute Unit angegeben, multipliziert mit dem Compute-Unit-Limit. In v1 handelt es sich um einen absoluten Gesamtbetrag in lamports — keine Multiplikation, keine Rundung. Übertragen Sie die CU-basierte Berechnung nicht. Die Gesamtgebührenformel bleibt ansonsten unverändert: (signatures × lamports_per_signature) + priority_fee.

ComputeBudget- Anweisungen sind No-Ops in v1

Eine v1-Transaktion lehnt ComputeBudget- Anweisungen nicht ab — sie ignoriert sie für die Konfiguration. Sie werden weiterhin als erfolgreiche No-Ops ausgeführt, verbrauchen 150 Compute Units und einen der 64 Anweisungs-slots, ohne Einfluss auf das Budget zu haben. Entfernen Sie sie beim Erstellen von v1-Transaktionen, und hören Sie beim Lesen von v1-Transaktionen auf, nach ihnen zu suchen: Die Werte befinden sich in der Nachrichtenkonfiguration.

Konfigurationsfelder müssen explizit gesetzt werden

Die wichtigste Verhaltensänderung für Sender: Im Gegensatz zu legacy und v0 müssen bei v1-Transaktionen das Compute-Unit-Limit und das Datenlimit für geladene Konten explizit gesetzt werden, sonst schlägt Ihre Transaktion fehl.

Nicht gesetztes Feldlegacy / v0v1Symptom bei Weglassen
Compute-Unit-Limit200k pro Anweisung, max. 1,4 M0 CUSchlägt sofort fehl, Budget erschöpft
Datengröße geladener Konten64 MiB0 BytesMaxLoadedAccountsDataSizeExceeded beim ersten geladenen Konto
Priority fee00
Heap-Größe32 KiB32 KiB

Die empfohlene Vorgehensweise ist, einmal mit maximierten Limits zu simulieren und dann die zurückgegebenen Werte unitsConsumed und loadedAccountsDataSize in die Konfiguration zu schreiben, wobei die Datengröße auf die nächste 32-KiB-Seite aufgerundet wird, um Puffer zu schaffen (das Blockkostenmodell rechnet in 32-KiB-Seiten, daher ist Puffer unterhalb der nächsten Seitengrenze kostenlos).

Vorbereitung auf v1

v1 verändert das Lesen von Transaktionen, nicht nur das Senden. Wenn v1 aktiviert wird, werden alle Clients, die getTransaction oder getBlock ohne Opt-in aufrufen, bei v1-Transaktionen Fehler erhalten:

  • Übergeben Sie maxSupportedTransactionVersion: 1 — die JSON-Ganzzahl 1, nicht den String "1" — an getTransaction und getBlock. Die Übergabe von 0 schlägt bei v1-Transaktionen genauso fehl wie das Weglassen des Parameters. Eine Codebasis, die beim v0-Rollout aktualisiert wurde, muss den Wert daher noch ändern.
  • getTransaction schlägt bei einer v1-Transaktion mit Fehler -32015 fehl, und eine einzelne v1-Transaktion lässt eine gesamte getBlock-Antwort mit demselben Fehler fehlschlagen — es gibt kein Teilergebnis.
  • blockSubscribe gibt block: null zurück und hört auf, fortzuschreiten. Ein Consumer, der dies als leeren Block interpretiert, fällt ab dem ersten v1-slot stillschweigend zurück.
  • getSignaturesForAddress untersucht Transaktionsinhalte nie, daher werden v1-Signaturen normal aufgelistet.
  • Antworten mit Opt-in enthalten ein transactionConfig-Objekt in der Nachricht für v1-Transaktionen (bei legacy und v0 vollständig abwesend). Pipelines, die priority fees oder Compute-Limits durch Suche nach ComputeBudget- Anweisungen ermitteln, werden für jede v1-Transaktion stillschweigend null melden.
  • Verwenden Sie encoding: 'base64', wenn Sie Transaktionen clientseitig dekodieren, sowie für sendTransaction/simulateTransaction bei Transaktionen über 1.232 Bytes — base58-Kodierung ist weiterhin auf die alte Größe begrenzt.
  • Die Unterstützung durch Client-Bibliotheken erfordert aktuelle Versionen: @solana/kit 8.0+, Agave 4.2.x-Generation Rust-Crates oder web3.js v3. web3.js v1 liest v1 ab 1.99.0, kann es aber weder erstellen noch senden.

Den vollständigen Migrationsleitfaden — einschließlich Client-Bibliotheksunterstützung, Streaming- (Geyser/gRPC-)Versionserkennung und Simulationsverhalten — finden Sie auf der Upgrade-Seite für Transaktionsformat v1.

Is this page helpful?

© 2026 Solana Foundation. Alle Rechte vorbehalten.