İşlem hattı

Özet

İşlemler 8 aşamadan geçer: alma, imza doğrulama, temizleme, bütçe/yaş kontrolleri, ücret ödeyici doğrulama, hesap yükleme, instruction yürütme ve taahhüt.

İşlem işleme hattı

Bir işlem validator'a ulaştığında, bir dizi doğrulama ve yürütme aşamasından geçer. Aşağıda, alımdan taahhüde kadar tam hat açıklanmakta olup, agave validator istemcisine kaynak dosya referansları verilmiştir.

1. Alma ve deserialize etme

Validator, UDP/QUIC üzerinden işlem byte'larını alır. Ham byte'lar tek bir paket içine sığmalıdır (PACKET_DATA_SIZE = 1.232 byte). Byte'lar, imza dizisi ve bir VersionedMessage (legacy veya v0) içeren bir VersionedTransaction içine deserialize edilir.

2. İmza doğrulama (sigverify)

İmzalar, işlem banking aşamasına girmeden önce sigverify aşamasında doğrulanır. i indeksindeki her imza için, doğrulayıcı Ed25519(signatures[i], account_keys[i], message_bytes) kontrolü yapar. Herhangi bir imza geçersizse, paket atılır.

Doğrulama paralelleştirilmiştir: validator, paket gruplarını VERIFY_PACKET_CHUNK_SIZE (128) parçalarına böler ve bunları paralel olarak işler.

3. Temizleme

Deserialize edilmiş işlem, bir SanitizedTransaction (veya RuntimeTransaction) üretmek için temizlenir. Temizleme, yapısal değişmezleri doğrular:

  • İmza sayısı, başlıktaki num_required_signatures ile eşleşir
  • Tüm instruction program_id_index ve account_indices sınırlar içindedir
  • Ücret ödeyici (hesap indeksi 0) yazılabilir bir imzalayıcıdır

RuntimeTransaction sarmalayıcısı, TransactionMeta'den önceden hesaplanmış metadata'yı önbelleğe alır: mesaj hash'i, oy işlemi bayrağı, precompile imza sayıları (Ed25519/secp256k1/secp256r1), compute budget instruction detayları ve toplam instruction data uzunluğu.

4. Hesaplama bütçesini, yaşını ve durum önbelleğini kontrol edin

check_transactions metodu, işlem başına birkaç kontrol gerçekleştirir:

Hesaplama bütçesi: İşlemin hesaplama bütçesi talimatları önce ayrıştırılır ve doğrulanır. Ücret detayları, bütçe limitleri ve önceliklendirme ücretinden hesaplanır. Hesaplama bütçesi geçersiz veya çelişkili ise, işlem DuplicateInstruction, InstructionError(..., InvalidInstructionData) veya InvalidLoadedAccountsDataSizeLimit gibi hesaplama bütçesi ayrıştırma hatalarıyla başarısız olur.

Blockhash yaşı: İşlemin recent_blockhash değeri BlockhashQueue içinde aranır. Hash bulunursa ve yaşı MAX_PROCESSING_AGE (150 slot) içindeyse, işlem devam eder. Bulunamazsa, validator geçerli bir durable nonce olup olmadığını kontrol eder.

Durum önbelleği: İşlemin mesaj hash'i bir durum önbelleğine karşı kontrol edilir. Bulunursa, işlem AlreadyProcessed ile reddedilir.

5. Nonce ve ücret ödeyiciyi doğrulayın

SVM'deki validate_transaction_nonce_and_fee_payer metodu iki doğrulama işler:

Nonce doğrulaması (uygulanabilirse): Nonce işlemleri için, validator nonce hesabını yükler ve şunları doğrular:

  • Hesap System Program'a aittir
  • State::Initialized olarak ayrıştırılır
  • Saklanan durable nonce, işlemin recent_blockhash değeriyle eşleşir
  • Nonce ilerletilebilir (mevcut durable nonce, bir sonraki durable nonce'tan farklıdır, yani nonce mevcut blokta zaten kullanılmamıştır)
  • Nonce yetkisi işlemi imzalamıştır

Geçerliyse, nonce bir sonraki durable nonce değerine ilerletilir. Bkz. validate_transaction_nonce.

Ücret ödeyici doğrulaması: Ücret ödeyici hesabı (her zaman indeks 0) yüklenir ve validate_fee_payer tarafından kontrol edilir:

  • Hesap mevcut olmalıdır (lamports > 0), aksi takdirde AccountNotFound
  • Hesap bir sistem hesabı veya nonce hesabı olmalıdır, aksi takdirde InvalidAccountForFee
  • Lamports, min_balance + total_fee değerini karşılamalıdır; burada min_balance sistem hesapları için 0 veya nonce hesapları için rent.minimum_balance(NonceState::size())'dir; aksi takdirde InsufficientFundsForFee
  • Ücret kesintisinden sonra, hesap kira muafiyetini korumalıdır (kira muafiyetinden kira ödemeye geçiş yapamaz)

Ücret bu aşamada ücret ödeyiciden düşülür. Ücret düşülmüş ücret ödeyicinin (ve varsa gelişmiş nonce'un) bir anlık görüntüsü RollbackAccounts olarak kaydedilir; bunlar, yürütme başarısız olsa bile commit edilen hesaplardır.

6. Hesapları yükle

load_transaction işlem tarafından referans verilen tüm hesapları yükler. AccountLoader harici hesap deposunu sarar ve batch-yerel bir önbellek tutar, böylece aynı batch içindeki önceki işlemler tarafından değiştirilen hesaplar sonraki işlemler için görünür olur.

Her ücret ödeyici olmayan hesap için yükleyici:

  1. Hesabı önbellekten veya accounts-db'den getirir
  2. Gerekirse kira muafiyeti durumunu günceller
  3. Hesabın veri boyutunu loaded_accounts_data_size_limit limitine ekler (varsayılan 64 MiB). Her hesap TRANSACTION_ACCOUNT_BASE_SIZE (64 bayt) temel ek yükü artı veri uzunluğu kadar maliyet getirir

İşlemin talimatları tarafından çağrılan her program için yükleyici, program hesabının var olduğunu ve geçerli bir yükleyiciye (NativeLoader veya PROGRAM_OWNERS'den biri) ait olduğunu doğrular. Geçersiz programlar ProgramAccountNotFound veya InvalidProgramForExecution ile başarısız olur.

LoaderV3 (yükseltilebilir) programları, yüklenen veri boyutu limitine dahil olan ilişkili programdata hesabını örtük olarak yükler.

Hesap yükleme başarısız olursa ancak ücret ödeyici başarıyla doğrulanmışsa, işlem FeesOnly sonucu olur: ücret yine de tahsil edilir ancak hiçbir talimat yürütülmez.

7. Talimatları yürüt

execute_loaded_transaction tüm yüklenmiş hesaplarla bir TransactionContext oluşturur ve process_message'ı çağırır. Talimatlar, mesajda göründükleri sırayla sıralı olarak yürütülür. Her talimat çağrısı bir InvokeContext oluşturur ve hedef programı çağırır.

Talimat işleme detayları

Runtime'ın process_message fonksiyonu her talimat üzerinde iterasyon yapar ve hedef programı çağırır:

  1. Her talimat için, çalışma zamanı prepare_next_top_level_instruction fonksiyonunu çağırır ve bu fonksiyon InstructionContext oluşturur. Bu bağlam, talimatın hesaplarına (derlenmiş indekslerden çözümlenen), instruction data'ya ve program account indeksine referanslar içerir.
  2. Çalışma zamanı, programın bir precompile (Ed25519, Secp256k1, Secp256r1) olup olmadığını kontrol eder. Precompile'lar BPF VM çağrılmadan doğrudan doğrulanır.
  3. Diğer tüm programlar için, çalışma zamanı process_instruction fonksiyonunu çağırır, bu fonksiyon programı önbellekten yükler ve BPF sanal makinesinde çalıştırır.
  4. Talimat tamamlandıktan sonra, çalışma zamanı tüm talimat hesaplarındaki toplam lamport bakiyesinin değişmediğini doğrular (UnbalancedInstruction kontrolü).
  5. Herhangi bir talimat başarısız olursa, tüm işlem geri alınır. Hiçbir ara durum değişikliği kaydedilmez.

Her talimat, instruction trace'i artırır. Trace hem üst düzey talimatları hem de bunların çağırdığı CPI'ları içerir. Toplam trace uzunluğu (üst düzey talimatlar artı tüm iç içe CPI'lar) 64'ü (MAX_INSTRUCTION_TRACE_LENGTH) aşamaz. Bu sınırın aşılması InstructionError::MaxInstructionTraceLengthExceeded döndürür.

Çalıştırma sonrasında, çalışma zamanı şunları doğrular:

  • Tüm hesaplardaki lamport toplamının değişmediği
  • Hiçbir hesabın rent-exempt durumundan rent-paying durumuna geçmediği

8. Commit veya rollback

Çalıştırma başarılı olursa, TransactionContext'den değiştirilmiş hesap durumları AccountLoader'ın batch-local önbelleğine geri yazılır. Çalıştırma başarısız olursa, yalnızca RollbackAccounts (ücret düşülmüş fee payer ve ileri alınmış nonce) geri yazılır. Ücret yine de tahsil edilir, ancak diğer tüm hesap değişiklikleri iptal edilir.

Pipeline özeti

Receive packet (UDP/QUIC)
--> Deserialize into VersionedTransaction
--> Sigverify (parallel Ed25519 verification)
--> Sanitize (structural validation, metadata extraction)
--> Parse compute budget, calculate fees
--> Check blockhash age (or verify nonce account)
--> Check status cache (dedup)
--> Validate nonce authority and advanceability (if nonce transaction)
--> Validate fee payer (load, check balance, deduct fee)
--> Load all accounts (with data size limits)
--> Load programs (verify loaders)
--> Execute instructions sequentially
--> Verify post-conditions (lamport balance, rent state)
--> Commit account changes (or rollback on failure)

Transaction error referansı

Aşağıdaki tablo tüm TransactionError varyantlarını ve bunların hangi pipeline aşamasında oluştuğunu listeler:

HataAşamaNeden
AccountInUseZamanlamaHesap aynı toplu işlemdeki başka bir işlem tarafından zaten kilitlenmiş
AccountLoadedTwiceZamanlamaBir pubkey işlemin account_keys içinde iki kez görünüyor
AccountNotFoundÜcret ödeyen doğrulamaÜcret ödeyen hesap mevcut değil
ProgramAccountNotFoundHesap yüklemeÇağrılan program mevcut değil
InsufficientFundsForFeeÜcret ödeyen doğrulamaÜcret ödeyen, ücret + rent-exempt minimumunu karşılayamıyor
InvalidAccountForFeeÜcret ödeyen doğrulamaÜcret ödeyen bir sistem veya nonce hesabı değil
AlreadyProcessedDurum önbelleğiİşlem zaten işlendi
BlockhashNotFoundYaş kontrolüBlockhash kuyrukta değil ve geçerli bir nonce değil
InstructionErrorYürütmeBir talimat işlenirken hata oluştu (talimat indeksi ve spesifik InstructionError içerir)
CallChainTooDeepHesap yüklemeYükleyici çağrı zinciri çok derin
MissingSignatureForFeeSanitizeİşlem ücret gerektiriyor ancak imza mevcut değil
InvalidAccountIndexSanitizeİşlem geçersiz bir hesap referansı içeriyor
SignatureFailureSigverifyEd25519 imzası doğrulanamıyor (paket atılıyor)
InvalidProgramForExecutionHesap yüklemeProgram geçerli bir yükleyiciye ait değil
SanitizeFailureSanitizeİşlem hesap ofsetlerini doğru şekilde sanitize edemedi
ClusterMaintenanceZamanlamaKüme bakımı nedeniyle işlemler şu anda devre dışı
AccountBorrowOutstandingYürütmeİşlem işleme, bekleyen ödünç alınmış referansa sahip bir hesap bıraktı
WouldExceedMaxBlockCostLimitZamanlamaİşlem maksimum blok maliyet limitini aşacak
UnsupportedVersionSanitizeİşlem sürümü desteklenmiyor
InvalidWritableAccountHesap yüklemeİşlem yazılamayan yazılabilir bir hesap yüklüyor
WouldExceedMaxAccountCostLimitZamanlamaİşlem blok içindeki maksimum hesap maliyet limitini aşacak
WouldExceedAccountDataBlockLimitZamanlamaİşlem blok içindeki hesap veri limitini aşacak
TooManyAccountLocksZamanlamaİşlem çok fazla hesap kilitledi
AddressLookupTableNotFoundHesap yüklemeAdres arama tablosu hesabı mevcut değil
InvalidAddressLookupTableOwnerHesap yüklemeAdres arama tablosu yanlış programa ait
InvalidAddressLookupTableDataHesap yüklemeAdres arama tablosu geçersiz veri içeriyor
InvalidAddressLookupTableIndexHesap yüklemeAdres tablosu araması geçersiz bir indeks kullanıyor
InvalidRentPayingAccountYürütme sonrası kontrolHesap rent-exempt'ten rent-paying'e geçiş yaptı
WouldExceedMaxVoteCostLimitZamanlamaİşlem maksimum oy maliyet limitini aşacak
WouldExceedAccountDataTotalLimitZamanlamaİşlem toplam hesap veri limitini aşacak
DuplicateInstructionCompute budget ayrıştırmaAynı işlemde yinelenen compute budget talimat varyantı
InsufficientFundsForRentYürütme sonrası kontrolHesap veri boyutu için rent'i karşılayacak yeterli lamport'a sahip değil
MaxLoadedAccountsDataSizeExceededHesap yüklemeToplam yüklenen veri 64 MiB limitini aşıyor
InvalidLoadedAccountsDataSizeLimitCompute budget ayrıştırmaSetLoadedAccountsDataSizeLimit 0 olarak ayarlandı
ResanitizationNeededSanitizeİşlem özellik aktivasyonundan önce/sonra farklılaştı ve yeniden sanitizasyon gerektiriyor
ProgramExecutionTemporarilyRestrictedHesap yüklemeProgram yürütme referans verilen hesapta geçici olarak kısıtlanmış
UnbalancedTransactionYürütme sonrası kontrolİşlemden önceki toplam lamport bakiyesi işlem sonrası bakiyeye eşit değil
ProgramCacheHitMaxLimitHesap yüklemeProgram önbelleği maksimum limite ulaştı
CommitCancelledCommitCommit dahili olarak iptal edildi

Is this page helpful?

Yönetici

© 2026 Solana Vakfı.
Tüm hakları saklıdır.
Bağlanın