Ö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_signaturesile eşleşir - Tüm instruction
program_id_indexveaccount_indicessı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::Initializedolarak ayrıştırılır- Saklanan durable nonce, işlemin
recent_blockhashdeğ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_feedeğerini karşılamalıdır; buradamin_balancesistem hesapları için 0 veya nonce hesapları içinrent.minimum_balance(NonceState::size())'dir; aksi takdirdeInsufficientFundsForFee - Ü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:
- Hesabı önbellekten veya accounts-db'den getirir
- Gerekirse kira muafiyeti durumunu günceller
- Hesabın veri boyutunu
loaded_accounts_data_size_limitlimitine ekler (varsayılan 64 MiB). Her hesapTRANSACTION_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:
- Her talimat için, çalışma zamanı
prepare_next_top_level_instructionfonksiyonunu çağırır ve bu fonksiyonInstructionContextoluşturur. Bu bağlam, talimatın hesaplarına (derlenmiş indekslerden çözümlenen), instruction data'ya ve program account indeksine referanslar içerir. - Ç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.
- Diğer tüm programlar için, çalışma zamanı
process_instructionfonksiyonunu çağırır, bu fonksiyon programı önbellekten yükler ve BPF sanal makinesinde çalıştırır. - Talimat tamamlandıktan sonra, çalışma zamanı tüm talimat hesaplarındaki
toplam lamport bakiyesinin değişmediğini
doğrular
(
UnbalancedInstructionkontrolü). - 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:
| Hata | Aşama | Neden |
|---|---|---|
AccountInUse | Zamanlama | Hesap aynı toplu işlemdeki başka bir işlem tarafından zaten kilitlenmiş |
AccountLoadedTwice | Zamanlama | Bir pubkey işlemin account_keys içinde iki kez görünüyor |
AccountNotFound | Ücret ödeyen doğrulama | Ücret ödeyen hesap mevcut değil |
ProgramAccountNotFound | Hesap 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 |
AlreadyProcessed | Durum önbelleği | İşlem zaten işlendi |
BlockhashNotFound | Yaş kontrolü | Blockhash kuyrukta değil ve geçerli bir nonce değil |
InstructionError | Yürütme | Bir talimat işlenirken hata oluştu (talimat indeksi ve spesifik InstructionError içerir) |
CallChainTooDeep | Hesap yükleme | Yükleyici çağrı zinciri çok derin |
MissingSignatureForFee | Sanitize | İşlem ücret gerektiriyor ancak imza mevcut değil |
InvalidAccountIndex | Sanitize | İşlem geçersiz bir hesap referansı içeriyor |
SignatureFailure | Sigverify | Ed25519 imzası doğrulanamıyor (paket atılıyor) |
InvalidProgramForExecution | Hesap yükleme | Program geçerli bir yükleyiciye ait değil |
SanitizeFailure | Sanitize | İşlem hesap ofsetlerini doğru şekilde sanitize edemedi |
ClusterMaintenance | Zamanlama | Küme bakımı nedeniyle işlemler şu anda devre dışı |
AccountBorrowOutstanding | Yürütme | İşlem işleme, bekleyen ödünç alınmış referansa sahip bir hesap bıraktı |
WouldExceedMaxBlockCostLimit | Zamanlama | İşlem maksimum blok maliyet limitini aşacak |
UnsupportedVersion | Sanitize | İşlem sürümü desteklenmiyor |
InvalidWritableAccount | Hesap yükleme | İşlem yazılamayan yazılabilir bir hesap yüklüyor |
WouldExceedMaxAccountCostLimit | Zamanlama | İşlem blok içindeki maksimum hesap maliyet limitini aşacak |
WouldExceedAccountDataBlockLimit | Zamanlama | İşlem blok içindeki hesap veri limitini aşacak |
TooManyAccountLocks | Zamanlama | İşlem çok fazla hesap kilitledi |
AddressLookupTableNotFound | Hesap yükleme | Adres arama tablosu hesabı mevcut değil |
InvalidAddressLookupTableOwner | Hesap yükleme | Adres arama tablosu yanlış programa ait |
InvalidAddressLookupTableData | Hesap yükleme | Adres arama tablosu geçersiz veri içeriyor |
InvalidAddressLookupTableIndex | Hesap yükleme | Adres tablosu araması geçersiz bir indeks kullanıyor |
InvalidRentPayingAccount | Yürütme sonrası kontrol | Hesap rent-exempt'ten rent-paying'e geçiş yaptı |
WouldExceedMaxVoteCostLimit | Zamanlama | İşlem maksimum oy maliyet limitini aşacak |
WouldExceedAccountDataTotalLimit | Zamanlama | İşlem toplam hesap veri limitini aşacak |
DuplicateInstruction | Compute budget ayrıştırma | Aynı işlemde yinelenen compute budget talimat varyantı |
InsufficientFundsForRent | Yürütme sonrası kontrol | Hesap veri boyutu için rent'i karşılayacak yeterli lamport'a sahip değil |
MaxLoadedAccountsDataSizeExceeded | Hesap yükleme | Toplam yüklenen veri 64 MiB limitini aşıyor |
InvalidLoadedAccountsDataSizeLimit | Compute budget ayrıştırma | SetLoadedAccountsDataSizeLimit 0 olarak ayarlandı |
ResanitizationNeeded | Sanitize | İşlem özellik aktivasyonundan önce/sonra farklılaştı ve yeniden sanitizasyon gerektiriyor |
ProgramExecutionTemporarilyRestricted | Hesap yükleme | Program yürütme referans verilen hesapta geçici olarak kısıtlanmış |
UnbalancedTransaction | Yürütme sonrası kontrol | İşlemden önceki toplam lamport bakiyesi işlem sonrası bakiyeye eşit değil |
ProgramCacheHitMaxLimit | Hesap yükleme | Program önbelleği maksimum limite ulaştı |
CommitCancelled | Commit | Commit dahili olarak iptal edildi |
Is this page helpful?