Transaktioputki

Yhteenveto

Transaktiot kulkevat 8 vaiheen läpi: vastaanotto, allekirjoituksen varmennus, puhdistus, budjetin/iän tarkistukset, maksajan validointi, tilin lataus, käskyn suoritus ja vahvistus.

Transaktioiden käsittelyputki

Kun transaktio saapuu validatorille, se kulkee läpi sarjan validointi- ja suoritusvaiheita. Seuraavassa kuvataan täydellinen putki vastaanottamisesta vahvistukseen, sisältäen viittaukset lähdetiedostoihin agave-validator-clientissa.

1. Vastaanotto ja deserialisointi

Validator vastaanottaa transaktiotavut UDP/QUIC-yhteyden kautta. Raakadatan on mahduttava yksittäiseen pakettiin (PACKET_DATA_SIZE = 1 232 tavua). Tavut deseralisoidaan VersionedTransaction-muotoon, joka sisältää allekirjoitustaulukon ja VersionedMessage-viestin (joko legacy tai v0).

2. Allekirjoituksen varmennus (sigverify)

Allekirjoitukset varmennetaan sigverify-vaiheessa ennen kuin transaktio siirtyy banking-vaiheeseen. Jokaiselle allekirjoitukselle indeksissä i varmennin tarkistaa Ed25519(signatures[i], account_keys[i], message_bytes). Jos jokin allekirjoitus on virheellinen, paketti hylätään.

Varmennus on rinnakkaistettu: validator jakaa pakettierät VERIFY_PACKET_CHUNK_SIZE-kokoisiin paloihin (128) ja käsittelee ne rinnakkain.

3. Puhdistus

Deserialisoitu transaktio puhdistetaan tuottamaan SanitizedTransaction (tai RuntimeTransaction). Puhdistus validoi rakenteelliset invariantit:

  • Allekirjoitusten määrä vastaa num_required_signatures-arvoa otsikossa
  • Kaikki käskyjen program_id_index- ja account_indices-arvot ovat rajojen sisällä
  • Maksaja (tilin indeksi 0) on kirjoitettava allekirjoittaja

RuntimeTransaction-kääre tallentaa välimuistiin esikäsitellyt metatiedot TransactionMeta-rakenteesta: viestin hash, äänestystransaktiolippu, esikäännösten allekirjoitusmäärät (Ed25519/secp256k1/secp256r1), laskentabudjetin käskytiedot ja käskyjen kokonaisdatan pituus.

4. Tarkista laskentabudjetti, ikä ja tilavälimuisti

check_transactions-metodi suorittaa useita tarkistuksia transaktiota kohden:

Laskentabudjetti: Transaktion laskentabudjetti-instruktiot jäsennetään ja validoidaan ensin. Maksutiedot lasketaan budjettirajoista ja priorisointimaksusta. Jos laskentabudjetti on virheellinen tai ristiriitainen, transaktio epäonnistuu laskentabudjetin jäsennysvirheillä, kuten DuplicateInstruction, InstructionError(..., InvalidInstructionData) tai InvalidLoadedAccountsDataSizeLimit.

Blockhash-ikä: Transaktion recent_blockhash haetaan BlockhashQueue-jonosta. Jos hash löytyy ja sen ikä on MAX_PROCESSING_AGE-arvon sisällä (150 slottia), transaktio jatkaa. Jos sitä ei löydy, validaattori tarkistaa kelvollisen durable nonce -arvon.

Tilavälimuisti: Transaktion viestihashin tarkistetaan tilavälimuistista. Jos se löytyy, transaktio hylätään virheellä AlreadyProcessed.

5. Validoi nonce ja maksaja

SVM:n validate_transaction_nonce_and_fee_payer-metodi käsittelee kaksi validointia:

Nonce-validointi (jos sovellettavissa): Nonce-transaktioissa validaattori lataa nonce-tilin ja varmistaa:

  • Tilin omistaa System Program
  • Se jäsentyy muotoon State::Initialized
  • Tallennettu durable nonce vastaa transaktion recent_blockhash-arvoa
  • Noncea voidaan edistää (sen nykyinen durable nonce eroaa seuraavasta durable noncesta, eli noncea ei ole jo käytetty nykyisessä lohkossa)
  • Nonce-auktoriteetti on allekirjoittanut transaktion

Jos kelvollinen, nonce edistetään seuraavaan durable nonce -arvoon. Katso validate_transaction_nonce.

Maksajan validointi: Maksajatili (aina indeksi 0) ladataan ja tarkistetaan validate_fee_payer-metodilla:

  • Tilin on oltava olemassa (lamports > 0), muuten AccountNotFound
  • Tilin on oltava järjestelmätili tai nonce-tili, muuten InvalidAccountForFee
  • Lamportien on katettava min_balance + total_fee, jossa min_balance on 0 järjestelmätileille tai rent.minimum_balance(NonceState::size()) nonce-tileille; muuten InsufficientFundsForFee
  • Maksun vähentämisen jälkeen tilin on pysyttävä rent-exempt-tilassa (ei voi siirtyä rent-exempt-tilasta rent-paying-tilaan)

Maksu vähennetään maksajalta tässä vaiheessa. Tilannekuva maksusta vähennetystä maksajasta (ja edistetystä noncesta, jos sovellettavissa) tallennetaan nimellä RollbackAccounts, jotka ovat tilejä, jotka vahvistetaan, vaikka suoritus epäonnistuisi.

6. Lataa tilit

load_transaction lataa kaikki tilit, joihin transaktio viittaa. AccountLoader käärii ulkoisen tilivaraston ja ylläpitää eräkohtaista välimuistia, jotta saman erän aiempien transaktioiden muokkaamat tilit ovat näkyvissä myöhemmille transaktioille.

Jokaiselle ei-maksajatilille lataaja:

  1. Hakee tilin välimuistista tai accounts-db:stä
  2. Päivittää vuokravapautuksen tilan tarvittaessa
  3. Kerää tilin datakoon loaded_accounts_data_size_limit -rajaan (oletuksena 64 MiB). Jokainen tili aiheuttaa peruskuorman TRANSACTION_ACCOUNT_BASE_SIZE (64 tavua) plus sen datapituuden

Jokaiselle transaktion käskyjen kutsumalle ohjelmalle lataaja varmistaa, että ohjelmatili on olemassa ja sen omistaa kelvollinen lataaja (NativeLoader tai jokin PROGRAM_OWNERS). Virheelliset ohjelmat epäonnistuvat virheellä ProgramAccountNotFound tai InvalidProgramForExecution.

LoaderV3 (päivitettävät) ohjelmat lataavat implisiittisesti niihin liittyvän programdata-tilin, joka myös lasketaan ladatun datan kokorajaan.

Jos tilin lataus epäonnistuu, mutta maksaja validoitiin onnistuneesti, transaktiosta tulee FeesOnly -tulos: maksu peritään silti, mutta käskyjä ei suoriteta.

7. Suorita käskyt

execute_loaded_transaction luo TransactionContext -olion kaikilla ladatuilla tileillä ja kutsuu process_message -funktiota. Käskyt suoritetaan peräkkäin siinä järjestyksessä, jossa ne esiintyvät viestissä. Jokainen käskyn kutsu luo InvokeContext -olion ja kutsuu kohdeohjelmaa.

Käskyn käsittelyn yksityiskohdat

Ajoympäristön process_message -funktio iteroi jokaisen käskyn läpi ja kutsuu kohdeohjelmaa:

  1. Jokaiselle ohjeelle runtime kutsuu prepare_next_top_level_instruction, joka rakentaa InstructionContext. Tämä konteksti sisältää viittaukset ohjeen tileille (ratkaistuna käännetyistä indekseistä), instruction datan ja program account -indeksin.
  2. Runtime tarkistaa, onko ohjelma precompile (Ed25519, Secp256k1, Secp256r1). Precompilet vahvistetaan suoraan ilman BPF VM:n kutsumista.
  3. Kaikille muille ohjelmille runtime kutsuu process_instruction, joka lataa ohjelman välimuistista ja suorittaa sen BPF-virtuaalikoneessa.
  4. Ohjeen suorittamisen jälkeen runtime vahvistaa, että lamport-saldo kaikkien ohjeen tilien välillä ei ole muuttunut (UnbalancedInstruction -tarkistus).
  5. Jos jokin ohje epäonnistuu, koko transaktio peruutetaan. Mitään välitilan muutoksia ei vahvisteta.

Jokainen ohje kasvattaa instruction trace -jälkeä. Jälki sisältää sekä ylätason ohjeet että kaikki niiden kutsutut CPI:t. Jäljen kokonaispituus (ylätason ohjeet plus kaikki sisäkkäiset CPI:t) ei voi ylittää 64:ää (MAX_INSTRUCTION_TRACE_LENGTH). Tämän rajan ylittäminen palauttaa InstructionError::MaxInstructionTraceLengthExceeded.

Suorituksen jälkeen runtime vahvistaa, että:

  • Lamport-summa kaikkien tilien välillä ei ole muuttunut
  • Mikään tili ei ole siirtynyt rent-exempt-tilasta rent-paying-tilaan

8. Vahvistus tai peruutus

Jos suoritus onnistuu, muokatut tilitilat TransactionContext:sta kirjoitetaan takaisin AccountLoader:n batch-paikalliseen välimuistiin. Jos suoritus epäonnistuu, vain RollbackAccounts (maksaja, jolta maksu on vähennetty ja nonce edistetty) kirjoitetaan takaisin. Maksu peritään silti, mutta kaikki muut tilimuutokset hylätään.

Pipeline-yhteenveto

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)

Transaktiovirheiden viite

Seuraava taulukko listaa kaikki TransactionError -variantit ja missä pipeline-vaiheessa ne esiintyvät:

VirheVaiheSyy
AccountInUseAjastusTili on jo toisen tapahtuman lukitsema samassa erässä
AccountLoadedTwiceAjastusPubkey esiintyy kahdesti tapahtuman account_keys-kentässä
AccountNotFoundMaksajan validointiMaksajatiliä ei ole olemassa
ProgramAccountNotFoundTilin latausKutsuttua ohjelmaa ei ole olemassa
InsufficientFundsForFeeMaksajan validointiMaksaja ei voi kattaa maksua + rent-exempt-minimiä
InvalidAccountForFeeMaksajan validointiMaksaja ei ole järjestelmä- tai nonce-tili
AlreadyProcessedTilavälimuistiTapahtuma oli jo käsitelty
BlockhashNotFoundIkätarkistusBlockhash ei ole jonossa eikä kelvollinen nonce
InstructionErrorSuoritusVirhe tapahtui käskyä suoritettaessa (sisältää käskyn indeksin ja tietyn InstructionError-virheen)
CallChainTooDeepTilin latausLataajan kutsuketju on liian syvä
MissingSignatureForFeeSanitointiTapahtuma vaatii maksun, mutta allekirjoitusta ei ole
InvalidAccountIndexSanitointiTapahtuma sisältää virheellisen tiliviitteen
SignatureFailureAllekirjoituksen varmennusEd25519-allekirjoitus ei täsmää (paketti hylätään)
InvalidProgramForExecutionTilin latausOhjelman omistaja ei ole kelvollinen lataaja
SanitizeFailureSanitointiTapahtuman tilien offsetien sanitointi epäonnistui
ClusterMaintenanceAjastusTapahtumat ovat tällä hetkellä pois käytöstä klusterin huollon vuoksi
AccountBorrowOutstandingSuoritusTapahtuman käsittely jätti tilille avoimen lainaviitteen
WouldExceedMaxBlockCostLimitAjastusTapahtuma ylittäisi lohkon maksimikustannusrajan
UnsupportedVersionSanitointiTapahtuman versio ei ole tuettu
InvalidWritableAccountTilin latausTapahtuma lataa kirjoitettavan tilin, johon ei voi kirjoittaa
WouldExceedMaxAccountCostLimitAjastusTapahtuma ylittäisi tilin maksimikustannusrajan lohkossa
WouldExceedAccountDataBlockLimitAjastusTapahtuma ylittäisi tilin datarajan lohkossa
TooManyAccountLocksAjastusTapahtuma lukitsi liian monta tiliä
AddressLookupTableNotFoundTilin latausOsoitehakutaulun tiliä ei ole olemassa
InvalidAddressLookupTableOwnerTilin latausOsoitehakutaulun omistaa väärä ohjelma
InvalidAddressLookupTableDataTilin latausOsoitehakutaulu sisältää virheellistä dataa
InvalidAddressLookupTableIndexTilin latausOsoitetaulun haku käyttää virheellistä indeksiä
InvalidRentPayingAccountSuorituksen jälkeinen tarkistusTili siirtyi rent-exempt-tilasta rent-paying-tilaan
WouldExceedMaxVoteCostLimitAjastusTapahtuma ylittäisi äänestyksen maksimikustannusrajan
WouldExceedAccountDataTotalLimitAjastusTapahtuma ylittäisi tilin kokonaisdatarajan
DuplicateInstructionLaskentabudjetin jäsennysCompute budget -käskyn variantti esiintyy kahdesti samassa tapahtumassa
InsufficientFundsForRentSuorituksen jälkeinen tarkistusTilillä ei ole tarpeeksi lamportteja kattamaan rent-maksua sen datakoolle
MaxLoadedAccountsDataSizeExceededTilin latausLadattu data ylittää 64 MiB -rajan
InvalidLoadedAccountsDataSizeLimitLaskentabudjetin jäsennysSetLoadedAccountsDataSizeLimit asetettu arvoon 0
ResanitizationNeededSanitointiTapahtuma erosi ennen/jälkeen ominaisuuden aktivoinnin ja vaatii uudelleensanitoinnin
ProgramExecutionTemporarilyRestrictedTilin latausOhjelman suoritus on väliaikaisesti rajoitettu viitatulla tilillä
UnbalancedTransactionSuorituksen jälkeinen tarkistusLamporttien kokonaissaldo ennen tapahtumaa ei vastaa saldoa sen jälkeen
ProgramCacheHitMaxLimitTilin latausOhjelmavälimuisti saavutti maksimirajan
CommitCancelledCommitCommit peruutettu sisäisesti

Is this page helpful?

Hallinnoi

© 2026 Solana Foundation.
Kaikki oikeudet pidätetään.
Yhdistä