
Pembuatan Versi Transaksi Solana: Legacy, v0, dan v1
Daftar Isi
- Sejarah Singkat Format Transaksi Solana
- Transaksi Legacy
- Transaksi v0
- Menambahkan Biaya Prioritas ke Format Lama
- Ukuran Transaksi yang Lebih Besar
- Spesifikasi dan Perbandingan Format
- Spesifikasi Transaksi Legacy
- Spesifikasi Transaksi v0
- Spesifikasi Transaksi v1
- Contoh Transaksi
- Transaksi Legacy dan v0
- Konfigurasi Sumber Daya
- Transaksi v1
- Verifikasi Tanda Tangan
- Penguraian Instruksi yang Lebih Baik
- Mask Konfigurasi Transaksi
- Kesimpulan
- Referensi Lebih Lanjut
Sejarah Singkat Format Transaksi Solana
Solana memiliki tiga format transaksi: legacy, v0, dan v1. Secara umum, semuanya memiliki tujuan yang sama. Format ini mengemas tanda tangan, akun, dan instruksi untuk dieksekusi validator pada program onchain.
Yang berubah seiring waktu adalah format wire, yaitu cara bagian-bagian informasi tersebut diserialisasi dan dikirimkan melalui jaringan.
Setiap format baru diperkenalkan untuk mengatasi keterbatasan yang muncul ketika aplikasi Solana menjadi makin kompleks, sekaligus mempertahankan kompatibilitas mundur agar format lama tetap dapat digunakan.
Ketiga format tersebut digunakan secara berdampingan di jaringan, dan developer dapat memakai format yang paling sesuai dengan transaksi yang mereka buat.
Transaksi Legacy
Format awal disebut legacy karena mendahului pembuatan versi transaksi dan tidak memiliki pengidentifikasi versi.
Ukuran maksimumnya sebesar 1.232 byte berasal dari desain jaringan awal Solana: ukuran transaksi ditetapkan agar muat dalam MTU minimum IPv6 sebesar 1.280 byte, sehingga tersisa 1.232 byte setelah overhead jaringan.
Ini berfungsi baik untuk transaksi kecil, tetapi ruang menjadi makin terbatas seiring berkembangnya aplikasi. Setiap alamat akun yang disertakan langsung dalam transaksi menggunakan 32 byte, sedangkan setiap tanda tangan Ed25519 menggunakan 64 byte lagi.
Dalam praktiknya, transaksi yang melibatkan banyak akun dapat mencapai batas byte jauh sebelum mencapai batas penguncian akun runtime.
Transaksi v0
Upaya pertama untuk mengurangi tekanan ini adalah transaksi v0, yang mulai aktif di mainnet-beta pada Oktober 2022. Alih-alih menaikkan batas 1.232 byte, v0 memperkenalkan Address Lookup Tables (ALT).
ALT menyimpan alamat akun secara onchain sehingga transaksi v0 dapat merujuknya menggunakan indeks satu byte, tanpa mengulang setiap kunci publik berukuran 32 byte. Dengan demikian, transaksi dapat mencapai batas 64 akun dari runtime sambil tetap mematuhi batas ukuran paket yang ada.
v0 merupakan ekstensi bertahap dari format legacy: format ini menambahkan prefiks versi 0x80 dan bagian pencarian alamat, sambil mempertahankan pengodean pesan dan instruksi dasar yang sama.
Pengenalan pembuatan versi juga membentuk kerangka kerja yang memungkinkan format transaksi baru digunakan berdampingan dengan transaksi legacy, bukan menggantikannya.
ALT mengatasi masalah ukuran akun yang mendesak, tetapi juga menimbulkan kerumitan baru. Aplikasi harus membuat dan memelihara lookup table secara onchain, validator harus me-resolve entrinya sebelum eksekusi, sedangkan layanan RPC dan pengindeks memerlukan alamat yang telah di-resolve untuk merekonstruksi transaksi lengkap.
Decoding historis juga menjadi jauh lebih sulit jika lookup table yang dirujuk transaksi mentah telah ditutup. Karena itu, v0 mengompresi daftar akun secara efektif, tetapi melakukannya dengan menambahkan dependensi onchain eksternal ke representasi wire transaksi.
ALT diadopsi secara luas oleh developer Solana. Riset yang dilakukan sesaat sebelum transaksi v1 diperkenalkan menemukan bahwa sekitar 62% transaksi v0 merujuk setidaknya satu ALT.
Menambahkan Biaya Prioritas ke Format Lama
Biaya prioritas juga diperkenalkan di Solana pada 2022, sebelum transaksi v0 diaktifkan di mainnet, meskipun desain format v0 sendiri sudah selesai saat itu. Alih-alih mendesain ulang salah satu format transaksi, Solana menambahkan konfigurasi biaya melalui Compute Budget Program yang sudah ada. Transaksi dapat menyertakan instruksi seperti SetComputeUnitLimit dan SetComputeUnitPrice, sehingga pengguna dapat meminta anggaran komputasi dan menambahkan biaya ekstra untuk prioritas penjadwalan. Pendekatan ini berfungsi sama baiknya untuk transaksi legacy maupun v0, tanpa memerlukan mekanisme biaya terpisah untuk setiap format.
Ini merupakan solusi pragmatis yang kompatibel dengan versi lama, tetapi bukan solusi yang sangat elegan. Biaya prioritas dan batas komputasi sebenarnya adalah metadata tingkat transaksi. Namun, legacy dan v0 tidak memiliki kolom khusus untuk keduanya, sehingga informasi tersebut ditambahkan ke aliran instruksi sebagai panggilan program. Artinya, Compute Budget Program harus dirujuk oleh transaksi, konfigurasi menggunakan byte instruksi, dan validator harus memeriksa instruksi tersebut saat menerima transaksi untuk mendapatkan pengaturan biaya dan sumber daya.
Dengan demikian, v0 bukanlah desain ulang menyeluruh atas format transaksi Solana. Tujuan utamanya adalah mengatasi hambatan alamat akun melalui Address Lookup Tables, sambil mempertahankan sebagian besar struktur pesan legacy. Karena instruksi Compute Budget sudah menyediakan cara yang kompatibel untuk mendukung biaya prioritas di kedua format, tidak ada banyak alasan untuk memperluas cakupan v0 lebih jauh.
Ukuran Transaksi yang Lebih Besar
Seiring waktu, Solana mengalihkan penerimaan transaksinya dari UDP ke QUIC, yang stream-nya tidak lagi dibatasi pada satu payload seukuran MTU. Karena itu, batas awal sebesar 1.232 byte tidak lagi menjadi persyaratan transportasi. Dua SIMD diajukan pada 2025 untuk memperkenalkan format v1 baru. SIMD-0296 menaikkan ukuran maksimum transaksi v1 menjadi 4.096 byte, sekitar 3,3× batas sebelumnya, sedangkan SIMD-0385 menetapkan format wire yang sepenuhnya baru, dirancang untuk memanfaatkan ruang tambahan tersebut dan meningkatkan efisiensi penerimaan oleh validator.
Ruang tambahan memungkinkan v1 menghapus ALT sepenuhnya. Batas 64 akun dengan alamat berukuran 32 byte memerlukan paling banyak 2.048 byte, sehingga daftar akun lengkap dapat disertakan langsung secara inline.
Analisis Solana Foundation menunjukkan bahwa dampak menyertakan semua alamat secara inline tergolong moderat saat sebagian besar transaksi v0 yang ada ditingkatkan: 50% bertambah kurang dari 420 byte dan 90% bertambah kurang dari 1.400 byte. Dengan demikian, masih tersedia ruang yang besar dalam batas 4.096 byte v1, bahkan untuk transaksi yang banyak menggunakan ALT.
Lebih penting lagi, v1 bukan sekadar transaksi v0 yang lebih besar. Format ini mengatur ulang format wire secara signifikan: tanda tangan dipindahkan ke bagian akhir, konfigurasi sumber daya dipindahkan dari instruksi Compute Budget ke bagian konfigurasi transaksi, dan payload instruksi dengan panjang variabel dipisahkan dari header berlebar tetap. Perubahan ini membuat transaksi lebih murah dan lebih mudah diurai serta diprioritaskan oleh validator.
Batas 4.096 byte yang lebih besar juga memungkinkan beban kerja yang tidak dapat terbantu hanya dengan kompresi alamat. Bukti zero-knowledge, multisig bertingkat, tanda tangan Winternitz yang tidak dipotong, tanda tangan BLS, dan operasi kriptografis lainnya dapat memerlukan ratusan atau ribuan byte data instruksi. Misalnya, Token-2022 Confidential Balances kini dapat dibuat sebagai satu transaksi v1 atomik, alih-alih dipecah menjadi beberapa transaksi.
Perlu diperhatikan bahwa format v1 awal tidak menaikkan batas komputasi, tanda tangan, jumlah instruksi, atau 64 akun Solana. Format ini terutama menghapus hambatan ukuran dan mendesain ulang cara transaksi direpresentasikan pada wire.
SIMD-0596, yang diusulkan oleh Anza, akan menaikkan batas penguncian akun v1 dari 64 menjadi 96, mencakup semua akun yang dirujuk transaksi, termasuk penanda tangan, ID program, serta akun yang dapat ditulis dan hanya-baca. Saat artikel ini ditulis, proposal tersebut masih ditinjau. Transaksi legacy dan v0 akan tetap dibatasi hingga 64.
Spesifikasi dan Perbandingan Format
| Batas | Legacy | v0 | v1 |
| Ukuran maks. | 1.232 byte | 1.232 byte | 4.096 byte |
| Alamat akun | ~32, dibatasi ukuran | 64, melalui lookup table | 64, inline |
| Address lookup table | Tidak didukung | Didukung | Tidak didukung |
| Alamat duplikat | diizinkan | diizinkan | ditolak |
| Prefiks | Tidak ada | 0x80 | 0x81 |
| Biaya prioritas | Instruksi SetComputeUnitPrice, micro-lamport per CU | Instruksi SetComputeUnitPrice, micro-lamport per CU | config.priorityFeeLamports, total lamport |
| Batas unit komputasi | Instruksi SetComputeUnitLimit | Instruksi SetComputeUnitLimit | config.computeUnitLimit |
| Ukuran heap | Instruksi RequestHeapFrame | Instruksi RequestHeapFrame | config.heapSize |
| Batas akun yang dimuat | Instruksi SetLoadedAccountsDataSizeLimit | Instruksi SetLoadedAccountsDataSizeLimit | config.loadedAccountsDataSizeLimit |
Spesifikasi Transaksi Legacy
Transaksi legacy yang diserialisasi diawali dengan jumlah tanda tangan compact-u16, kemudian diikuti tanda tangan Ed25519 berukuran 64 byte.
Berikutnya adalah pesan, yang berisi header tiga byte, daftar akun dengan prefiks panjang ringkas, recent blockhash 32 byte, dan array instruksi terkompilasi dengan prefiks panjang ringkas.
Transaksi legacy tidak memiliki prefiks versi.
NumSignatures (compact-u16)
Signatures [[u8; 64]]
-- Length = NumSignatures
MessageHeader (u8, u8, u8)
-- (NumRequiredSignatures,
NumReadonlySignedAccounts,
NumReadonlyUnsignedAccounts)
NumAccountKeys (compact-u16)
AccountKeys [[u8; 32]]
-- Length = NumAccountKeys
RecentBlockhash [u8; 32]
NumInstructions (compact-u16)
Instructions [CompiledInstruction]
-- Length = NumInstructions
CompiledInstruction:
ProgramIdIndex (u8)
NumInstructionAccounts (compact-u16)
InstructionAccountIndexes [u8]
-- Length = NumInstructionAccounts
InstructionDataLength (compact-u16)
InstructionData [u8]
-- Length = InstructionDataLengthSalah satu karakteristik utamanya adalah setiap CompiledInstruction diserialisasi secara penuh sebelum instruksi berikutnya dimulai.
Array indeks akun dan data memiliki panjang variabel, dengan prefiks compact-u16 yang menentukan ukurannya.
Spesifikasi Transaksi v0
Transaksi v0 mempertahankan hampir seluruh format wire legacy. Transaksi tetap diawali dengan jumlah tanda tangan dan tanda tangan, tetapi pesannya dimulai dengan prefiks versi 0x80.
Pesan kemudian menggunakan header tiga byte, daftar akun statis, blockhash, dan format instruksi terkompilasi yang sama seperti legacy, lalu menambahkan bagian Address Lookup Table.
Inilah yang memungkinkan transaksi v0 memuat akun tambahan melalui ALT sambil tetap berada dalam batas transaksi 1.232 byte.
NumSignatures (compact-u16)
Signatures [[u8; 64]]
-- Length = NumSignatures
VersionByte (u8)
-- 0x80
MessageHeader (u8, u8, u8)
NumStaticAccountKeys (compact-u16)
StaticAccountKeys [[u8; 32]]
-- Length = NumStaticAccountKeys
RecentBlockhash [u8; 32]
NumInstructions (compact-u16)
Instructions [CompiledInstruction]
-- Same encoding as legacy
NumAddressTableLookups (compact-u16)
AddressTableLookups [MessageAddressTableLookup]
-- Length = NumAddressTableLookups
MessageAddressTableLookup:
AccountKey [u8; 32]
-- Address of the lookup table account
NumWritableIndexes (compact-u16)
WritableIndexes [u8]
-- Indices into the lookup table
NumReadonlyIndexes (compact-u16)
ReadonlyIndexes [u8]
-- Indices into the lookup tablePerbedaan antara kunci akun statis dan alamat yang dimuat sangatlah penting. Hanya kunci statis yang diserialisasi langsung ke dalam pesan. Alamat yang dirujuk melalui ALT di-resolve saat runtime dan ditambahkan ke daftar akun efektif.
Untuk transaksi v0 yang menggunakan ALT, validator harus terlebih dahulu memuat setiap lookup table yang dirujuk dari Bank dan AccountsDB, memastikan bahwa akun tersebut merupakan Address Lookup Table yang valid, mendeserialisasi statusnya, me-resolve indeks yang diminta menjadi alamat lengkap 32 byte, lalu menggabungkan alamat tersebut dengan kunci akun statis transaksi. Hanya setelah proses resolusi ini validator memiliki daftar akun lengkap yang diperlukan untuk menentukan penguncian baca/tulis dan konflik dengan transaksi lain.
Spesifikasi Transaksi v1
Transaksi v1 yang diserialisasi diawali dengan byte versi 0x81. Setelah itu terdapat header pesan tiga byte bergaya legacy, mask konfigurasi transaksi 32-bit, penentu masa berlaku 32 byte, jumlah instruksi dan alamat, array lengkap alamat 32 byte, nilai konfigurasi, header instruksi berukuran tetap, payload instruksi yang berurutan, dan terakhir tanda tangan.
VersionByte (u8)
-- 0x81
LegacyHeader (u8, u8, u8)
TransactionConfigMask (u32)
-- Bitmask describing which configuration values are present
LifetimeSpecifier [u8; 32]
NumInstructions (u8)
NumAddresses (u8)
Addresses [[u8; 32]]
-- Length = NumAddresses
ConfigValues [[u8; 4]]
-- Length = popcount(TransactionConfigMask)
-- Multi-word values, such as priority fee, consume multiple entries
InstructionHeaders [(u8, u8, u16)]
-- Length = NumInstructions
-- (ProgramAccountIndex,
NumInstructionAccounts,
NumInstructionDataBytes)
InstructionPayloads [InstructionPayload]
-- Length = NumInstructions
InstructionPayload:
InstructionAccountIndexes [u8]
-- Length = NumInstructionAccounts
InstructionData [u8]
-- Length = NumInstructionDataBytes
Signatures [[u8; 64]]
-- Length = LegacyHeader.NumRequiredSignaturesKarena itu, v1 berbeda dari format sebelumnya dalam beberapa aspek mendasar. Pengidentifikasi versi berada di byte nol, tanda tangan dipindahkan ke bagian akhir dan tidak lagi memerlukan prefiks panjangnya sendiri, jumlah akun dan instruksi menjadi nilai u8 berlebar tetap, konfigurasi sumber daya dienkode langsung dalam transaksi, dan header instruksi berukuran tetap dipisahkan dari payload berpanjang variabel. Tidak seperti legacy dan v0, v1 tidak menggunakan Address Lookup Tables.
Transaksi v1 mengganti instruksi konfigurasi Compute Budget Program dengan kolom di header transaksi. TransactionConfigMask awal dapat mendeklarasikan hal berikut untuk transaksi:
- total biaya prioritas dalam lamport
- batas unit komputasi
- batas ukuran data akun yang dimuat
- ukuran heap yang diminta
Setiap bit yang ditetapkan mengidentifikasi nilai konfigurasi empat byte yang menyertainya, dengan biaya prioritas 64-bit menempati dua posisi mask. Mask dirancang agar dapat diperluas dalam versi transaksi mendatang.
Contoh Transaksi
Untuk membandingkan berbagai format transaksi Solana, kita akan menggunakan contoh berguna yang paling sederhana: mentransfer SOL dari satu alamat ke alamat lain.
Contoh transaksi kita memiliki satu penanda tangan (yaitu pengirim) dan memanggil System Program satu kali untuk mentransfer 1.000 lamport kepada penerima. Transaksi ini merujuk tiga alamat: pengirim, penerima, dan System Program.
Transaksi Legacy dan v0
Transaksi legacy dan v0 menggunakan tata letak tingkat atas yang hampir sama. Keduanya dimulai dengan jumlah tanda tangan, yang langsung diikuti tanda tangan itu sendiri. Setelah itu terdapat pesan transaksi. Untuk transfer dengan satu penanda tangan, byte pertama adalah 01, yang menentukan satu tanda tangan, lalu diikuti tanda tangan Ed25519 pengirim berukuran 64 byte.
Pesan berisi header tiga byte, alamat akun, recent blockhash (penentu masa berlaku), dan instruksi terkompilasi.
Pengirim adalah alamat 0, penerima adalah alamat 1, dan System Program adalah alamat 2. Instruksi transfer merujuk program pada indeks 2 dan meneruskan indeks akun 00 01 ke program.
Format legacy dan v0 hanya sedikit berbeda:
- Pesan legacy langsung dimulai dengan header pesan tiga byte, sedangkan pesan v0 dimulai dengan byte versi
0x80, kemudian diikuti header. - v0 juga menambahkan bagian Address Lookup Table setelah instruksi. Contoh sederhana kita tidak menggunakan lookup table, sehingga bagian ini hanya terdiri dari satu byte
00yang menunjukkan nol pencarian.
Akibatnya, contoh transaksi transfer SOL kita berukuran 215 byte sebagai transaksi legacy dan 217 byte sebagai v0. v0 menambahkan 1 byte untuk prefiks versi dan 1 byte untuk array lookup table kosong. Bagian transaksi lainnya identik.
Pengirim hanya menandatangani pesan. Dalam contoh legacy kita, berarti tanda tangan mencakup byte 65–214. Untuk v0, tanda tangan mencakup byte 65–216, dimulai dengan prefiks versi pesan 0x80.
Tabel berikut merinci tata letak byte untuk contoh transfer SOL antara dua alamat menggunakan format transaksi v0.
| Offset | Ukuran | Kolom | Contoh nilai | Deskripsi |
| 0 | 1 B | Jumlah tanda tangan | 01 | Satu tanda tangan; compact-u16 |
| 1–64 | 64 B | Tanda tangan 0 | <Ed25519 signature> | Tanda tangan pengirim |
| 65 | 1 B | Prefiks versi | 80 | Pesan berversi, versi 0 |
| 66–68 | 3 B | Header pesan | 01 00 01 | 1 penanda tangan wajib, 0 akun bertanda tangan hanya-baca, 1 akun tanpa tanda tangan hanya-baca |
| 69 | 1 B | Jumlah akun statis | 03 | Tiga akun inline |
| 70–101 | 32 B | Akun 0 | <sender pubkey> | Pengirim/pembayar biaya; penanda tangan yang dapat ditulis |
| 102–133 | 32 B | Akun 1 | <recipient pubkey> | Penerima; tanpa tanda tangan dan dapat ditulis |
| 134–165 | 32 B | Akun 2 | 11111111111111111111111111111111 | System Program; tanpa tanda tangan dan hanya-baca |
| 166–197 | 32 B | Recent blockhash | <recent blockhash> | Masa berlaku transaksi |
| 198 | 1 B | Jumlah instruksi | 01 | Satu instruksi |
| 199 | 1 B | Indeks ID program | 02 | System Program |
| 200 | 1 B | Jumlah akun instruksi | 02 | Dua akun instruksi |
| 201–202 | 2 B | Indeks akun | 00 01 | Pengirim, penerima |
| 203 | 1 B | Panjang data | 0C | 12 byte |
| 204–207 | 4 B | Diskriminator transfer | 02 00 00 00 | SystemInstruction::Transfer |
| 208–215 | 8 B | Lamport | E8 03 00 00 00 00 00 00 | 1.000 lamport |
| 216 | 1 B | Jumlah pencarian tabel alamat | 00 | Tidak ada pencarian ALT |
| Total | 217 B |
Konfigurasi Sumber Daya
Dalam transaksi legacy dan v0, konfigurasi sumber daya dinyatakan sebagai instruksi kepada Compute Budget Program. Instruksi yang umum mencakup SetComputeUnitLimit dan SetComputeUnitPrice. SetLoadedAccountsDataSizeLimit dan RequestHeapFrame juga digunakan bila diperlukan.
Dalam contoh transaksi minimal kita, instruksi tersebut tidak ada. Runtime menggunakan nilai default sebagai gantinya.
Tanpa harga unit komputasi, tidak ada biaya prioritas, dan batas data akun yang dimuat menggunakan nilai maksimum runtime secara default.
Ketidakefisienan karena validator harus memindai daftar instruksi untuk mencari instruksi Compute Budget saat menerima transaksi menjadi salah satu alasan pembaruan format v1, yang memindahkan informasi ini ke TransactionConfigMask dan ConfigValues.
Sejak awal, terdapat pula overhead bawaan dalam merepresentasikan konfigurasi tingkat transaksi sebagai instruksi. Legacy dan v0 tidak memiliki kolom khusus untuk komputasi yang diminta atau biaya prioritas, sehingga pengaturan ini ditambahkan melalui Compute Budget Program: ID programnya harus dirujuk oleh transaksi, setiap pengaturan menggunakan ruang dalam daftar instruksi, dan pemanggilan program itu sendiri tidak menjalankan pekerjaan aplikasi meskipun tetap menggunakan komputasi.
Sebagai gantinya, v1 menyediakan tempat native bagi nilai tersebut dalam format wire. Ini menghindari overhead instruksi tambahan serta membuat konfigurasi sumber daya lebih murah dan lebih mudah diperiksa validator.
Transaksi v1
Alih-alih dimulai dengan jumlah tanda tangan dan tanda tangan, transaksi v1 langsung dimulai dengan byte versi 0x81.
Berikutnya adalah header tiga byte, diikuti TransactionConfigMask empat byte yang baru, penentu masa berlaku (biasanya blockhash, tetapi juga dapat berupa nonce), jumlah instruksi dan alamat, alamat akun, nilai konfigurasi, instruksi, dan terakhir tanda tangan.
| Offset | Ukuran | Kolom | Contoh nilai | Deskripsi |
| 0 | 1 B | Byte versi | 81 | Transaksi v1 |
| 1–3 | 3 B | Header legacy | 01 00 01 | 1 tanda tangan wajib, 0 akun bertanda tangan hanya-baca, 1 akun tanpa tanda tangan hanya-baca |
| 4–7 | 4 B | Mask konfigurasi transaksi | 0C 00 00 00 | 0x0000000C: bit 2 dan 3 ditetapkan, yang menentukan dua nilai konfigurasi 4 byte |
| 8–39 | 32 B | Penentu masa berlaku | <recent blockhash> | Recent blockhash (atau nonce) |
| 40 | 1 B | Jumlah instruksi | 01 | 1 instruksi System Program |
| 41 | 1 B | Jumlah alamat | 03 | Pengirim, penerima, System Program |
| 42–73 | 32 B | Alamat 0 | <sender pubkey> | Pengirim, pembayar biaya, penanda tangan yang dapat ditulis |
| 74–105 | 32 B | Alamat 1 | <recipient pubkey> | Penerima, akun tanpa tanda tangan yang dapat ditulis |
| 106–137 | 32 B | Alamat 2 | 11111111111111111111111111111111 | System Program, hanya-baca, tanpa tanda tangan |
| 138–141 | 4 B | Nilai konfigurasi: Batas unit komputasi | 10 27 00 00 | 10.000 CU sebagai u32 little-endian (sesuai dengan bit mask 2) |
| 142–145 | 4 B | Nilai konfigurasi: Batas ukuran data akun yang dimuat | 00 00 01 00 | 65.536 byte / 64 KiB sebagai u32 little-endian (sesuai dengan bit mask 3) |
| 146–149 | 4 B | Instruksi: Header | 02 02 0C 00 | Indeks program 2, 2 akun, 12 byte data |
| 150–151 | 2 B | Instruksi: Indeks akun | 00 01 | Alamat 0 = pengirim, Alamat 1 = penerima |
| 152–155 | 4 B | Instruksi: Diskriminator transfer | 02 00 00 00 | SystemInstruction::Transfer |
| 156–163 | 8 B | Instruksi: Lamport | mis. E8 03 00 00 00 00 00 00 | 1.000 lamport sebagai u64 little-endian |
| 164–227 | 64 B | Tanda tangan 0 | <Ed25519 signature> | Tanda tangan pengirim atas byte 0–155 |
| Total | 228 B |
Verifikasi Tanda Tangan
Verifikasi tanda tangan merupakan salah satu operasi pertama yang dilakukan ketika transaksi mencapai validator. Transaksi dengan tanda tangan tidak valid harus difilter dan dibuang sebelum mencapai scheduler. Menambahkan tanda tangan setelah pesan berpanjang variabel tampaknya akan membuatnya lebih sulit diakses, tetapi dalam praktiknya tidak demikian.
Sebelum melakukan verifikasi Ed25519 yang mahal, validator hanya perlu mengidentifikasi titik awal dan akhir setiap bagian transaksi. Format v1 dirancang agar proses ini murah dan deterministik.
Byte pertama, 0x81, langsung mengidentifikasi transaksi sebagai v1. Header berikutnya berisi num_required_signatures, sehingga sejak awal validator mengetahui jumlah tanda tangan 64 byte yang harus ditemukan.
Parser TransactionView milik Agave kemudian menelusuri transaksi sambil mencatat offset. Parser membaca kolom berukuran tetap dan menggunakan NumAddresses untuk melewati array alamat.
Parser menggunakan mask konfigurasi untuk menentukan ukuran bagian konfigurasi, lalu membaca setiap header instruksi 4 byte untuk mengetahui ukuran payload instruksi terkait.
Setelah parser melewati payload instruksi terakhir, posisinya saat itu dicatat sebagai offset tanda tangan. Mulai dari posisi tersebut, Agave mengharapkan tepat num_required_signatures × 64 byte.
Implementasinya menyimpan SignatureFrame yang berisi jumlah tanda tangan dan offset byte dari tanda tangan pertama dalam paket. Pesan transaksi yang ditandatangani adalah rentang byte dari awal pesan v1 hingga offset tanda tangan yang dicatat. Dengan demikian, validator dapat menjalankan verifikasi Ed25519 yang mahal tanpa mengeksekusi transaksi atau memuat akun.
v1 juga melarang byte tambahan setelah array tanda tangan. Setelah parser mencapai tanda tangan, byte yang tersisa memiliki ukuran yang tidak ambigu dan ditentukan oleh jumlah tanda tangan. SIMD-0385 mewajibkan tepat satu tanda tangan 64 byte untuk setiap penanda tangan wajib dan tidak boleh ada data setelah tanda tangan terakhir.
Penguraian Instruksi yang Lebih Baik
Tata letak transaksi v1 membuat instruksi lebih mudah diurai. Untuk menemukan instruksi berikutnya dalam transaksi legacy dan v0, parser harus menelusuri instruksi sebelumnya, mendecode panjangnya, dan melewati setiap payload berpanjang variabel.
v1 memisahkan header instruksi berlebar tetap dari payload berpanjang variabel. Setiap instruksi terlebih dahulu menyumbangkan header empat byte yang berisi indeks akun program, jumlah akun instruksi, dan panjang data instruksi. Header tersebut dikelompokkan sebelum indeks akun dan payload data. Ini menyediakan deskripsi ringkas setiap instruksi di awal. Pendekatan ini mengurangi biaya untuk membingkai dan melewati bagian instruksi serta membantu menentukan offset array tanda tangan di bagian akhir tanpa mengurai data instruksi.
Mask Konfigurasi Transaksi
Penambahan utama lainnya dalam format v1 adalah TransactionConfigMask empat byte.
Transaksi legacy dan v0 mengonfigurasi sumber daya melalui instruksi kepada Compute Budget Program. Misalnya, transaksi dapat berisi instruksi SetComputeUnitLimit, SetComputeUnitPrice, atau SetLoadedAccountsDataSizeLimit. Validator yang memerlukan informasi tentang kebutuhan sumber daya atau prioritas transaksi harus menemukan dan menafsirkan instruksi tersebut. Transaksi v1 memindahkan informasi ini dari aliran instruksi ke dalam format transaksi itu sendiri.
Mask tersebut merupakan bitfield little-endian 32-bit. Setiap bit yang ditetapkan berkaitan dengan word empat byte dalam bagian ConfigValues pada bagian transaksi berikutnya:
- Bit 0 dan 1: total biaya prioritas dalam lamport (dienkode sebagai
u64little-endian 8 byte) - Bit 2: batas unit komputasi (
u324 byte) - Bit 3: batas ukuran data akun yang dimuat (
u324 byte) - Bit 4: ukuran heap yang diminta (
u324 byte)
Catatan: Spesifikasi awal v1 hanya menetapkan arti bagi bit 0–4. Bit lainnya belum ditetapkan, sehingga tersedia ruang untuk kolom konfigurasi tingkat transaksi pada masa mendatang.
Mask berfungsi sebagai skema ringkas yang memberi tahu parser kolom mana yang tersedia dan berapa banyak byte yang harus diterima. Misalnya, transfer SOL sederhana kita memerlukan batas unit komputasi dan batas ukuran data akun yang dimuat, tetapi tidak memerlukan biaya prioritas atau ukuran heap khusus.
Karena kedua bit tersebut ditetapkan, tepat dua nilai konfigurasi 4 byte mengikuti array alamat transaksi. Dalam kasus kita, nilai tersebut meminta batas 20.000 CU dan batas data akun yang dimuat sebesar 64 KiB.
Mask memberi tahu validator bahwa konfigurasi 4 byte pertama terkait dengan bit 2 (batas unit komputasi), sedangkan yang kedua terkait dengan bit 3 (batas data akun yang dimuat).
Dalam transaksi legacy dan v0, tidak menyertakan instruksi batas unit komputasi akan memberikan anggaran komputasi implisit kepada transaksi. v1 tidak menggunakan nilai default yang sama. Batas unit komputasi yang tidak ditetapkan akan menjadi nol, demikian pula batas ukuran data akun yang dimuat. Hanya heap yang mempertahankan nilai default 32 KiB. Karena itu, transaksi v1 harus secara eksplisit meminta sumber daya yang diperlukannya.
Memindahkan pengaturan ini ke area konfigurasi yang ditetapkan dengan jelas memberi validator akses langsung ke informasi yang diperlukan saat menerima transaksi, tanpa harus mencarinya dalam instruksi. Artinya, instruksi Compute Budget Program juga tidak lagi mengonfigurasi transaksi v1. Jika disertakan, instruksi tersebut diabaikan dan diproses sebagai instruksi no-op, tetapi tetap menggunakan unit komputasi.
Ini juga memberikan manfaat tambahan dari segi ruang. Dalam transaksi legacy/v0, penambahan instruksi Compute Budget umumnya mengharuskan alamat Compute Budget Program berukuran 32 byte disertakan dalam daftar akun, bersama dengan instruksi yang telah diserialisasi.
Kesimpulan
Ketiga format transaksi Solana mencerminkan evolusi jaringan. Legacy membentuk model awal, v0 memperluasnya dengan ALT untuk mendukung kumpulan akun yang lebih besar dalam batas 1.232 byte, sedangkan v1 merombak format wire secara lebih mendasar untuk mendukung transaksi yang lebih besar, penguraian yang lebih sederhana, alamat inline, dan konfigurasi sumber daya native.
Ketiganya tetap valid, tetapi masing-masing mewakili tahap berbeda dalam perkembangan Solana. Secara keseluruhan, format tersebut menunjukkan bagaimana format transaksi beradaptasi seiring berkembangnya aplikasi jaringan, pasar biaya, dan kebutuhan validator.
Referensi Lebih Lanjut
- Transaksi v1 dan Konsekuensi ALT - Umberto Natale, Solana Foundation
- Transaksi Berversi - Dokumentasi Solana
- Meningkatkan Ukuran Transaksi - Forum Diskusi SIMD
- Ukuran Transaksi yang Lebih Besar - Peningkatan Solana
Artikel Terkait
Berlangganan Helius
Ikuti perkembangan terbaru dalam pengembangan Solana dan dapatkan pembaruan saat kami memublikasikan postingan


