Sarı Kağıdın Ethereum Sanal Makinesi Spesifikasyonlarını Anlama
Sarı Kağıt, Ethereum'un resmi spesifikasyonudur. EIP süreci tarafından düzenlenen yerler dışında, her şeyin nasıl çalıştığına dair net bir açıklama içerir. Programcıların anlaşılır bulmayabileceği terimler içeren matematiksel bir kağıt olarak yazılmıştır. Bu kağıtta, spesifikasyonu ve dolayısıyla bağlantılı diğer matematiksel kağıtları nasıl okuyacağınızı öğreneceksiniz.
Hangi Sarı Kağıt?
Ethereum'daki her şey gibi, Sarı Kağıt da zamanla evrimleşiyor. Spesifik bir versiyona atıfta bulunabilmek için yazımı devam eden versiyonu yükledim. Kullanacağım bölüm, sayfa ve denklem numaraları o versiyona ait olacaktır. Bu dokümanı okurken farklı bir pencerede Sarı Kağıdı açık tutmak iyi bir fikir olabilir.
Neden Ethereum Sanal Makinesi?
Orijinal sarı kağıt, Ethereum'un geliştirme sürecinin başında yazılmıştı. Başlangıçta ağı korumak için kullanılan mutabakat mekanizmasını temel alan orijinal iş ispatını açıklamaktadır. Bununla birlikte, Ethereum Eylül 2022'de iş ispatını bırakıp hisse ispatı tabanlı istemciyi kullanmaya başladı. Bu öğretici, sarı kağıdın Ethereum Sanal Makinesi'ni tanıttığı bölümlere değinecektir. EVM, (DIFFICULTY işlem kodunun dönüş değeri dışında) hisse ispatına geçiş nedeniyle değiştirilmemiştir.
9 Yürütüm modeli
Bu bölüm (sayfa 12-14) daha çok EVM'nin tanıtımını içeriyor.
Sistem durumu terimi, sistemi çalıştırmak için bilmeniz gereken her şeyi içerir. Bu, tipik bir bilgisayarda bellek, kayıt içerikleri vs. anlamlarına gelir.
Turing makinesi, bir hesaplama modelidir. Aslında bir bilgisayarın basitleştirilmiş bir halidir ve normal bir bilgisayarın hesaplamaları yapma kabiliyetine sahip olduğu kanıtlanmıştır (bir bilgisayarın hesaplayabileceği her şeyi bir Turing makinesi de hesaplayabilir). Bu model neyin hesaplanabilir olduğuna ve olmadığına dair değişik teorileri kanıtlamayı kolaylaştırır.
Turing-tamam terimi, bir bilgisayarın hesapları bir Turing makinesi gibi çalıştırabileceği anlamına gelir. Turing makineleri sonsuz döngülere girebilir ancak EVM giremez; çünkü gazı biter, yani EVM sadece yarı-Turing-tamam niteliğindedir.
9.1 Temeller
Bu bölüm EVM'nin temellerini ve diğer hesaplama modelleri ile nasıl benzerlik ve farklılıklarını gösterir.
Bir yığın makinesi, ara verileri kayıtlarda değil, yığında depolayan bir bilgisayardır. Bu, hata ve güvenlik açıklarının bulunma olasılığının az olması sayesinde uygulanması kolay olduğundan sanal makineler için tercih edilen mimaridir. Yığındaki bellek 256 bitlik kelimelere bölünür. Bunun seçilme sebebi, Keccak-256 karmalaması ve eliptik eğri hesaplamaları gibi Ethereum'un temel kriptografik operasyonları için uygun olmasıdır. Yığının sahip olabileceği maksimum boyut 1024 bayttır. İşlem kodları yürütüldüklerinde parametrelerini genelde yığından alırlar. Yığındaki elementleri yeniden düzenlemeye yarayan POP
(yığının başındaki öğeyi siler), DUP_N
(yığındaki n'inci öğeyi kopyalar) gibi işlem kodları vardır.
EVM'nin ayrıca çalıştırma sürecinde veri depolama amacıyla kullanılan bellek adında geçici bir alanı vardır. Bu bellek, 32 baytlık kelimeler halinde düzenlenmiştir. Her bellek konumu sıfırdan başlatılır. Yul kodunu belleğe bir kelime eklemek için çalıştırırsanız, 32 baytlık bir belleği kelimedeki sıfırlı boş alan ile dolduracaktır, yani 0-29, 0x60'tan 30'a ve 0xA7'den 31'e konumlarındaki sıfırlarla yeni bir kelime oluşturur.
1mstore(0, 0x60A7)
mstore
, EVM'nin bellekle etkileşime girebilmek için sağladığı üç işlem kodundan biridir; belleğe bir kelime yükler. Diğer ikisi ise belleğe tek bir bayt yükleyen mstore8
ile bellekteki bir kelimeyi yığına taşıyan mload
'dur.
EVM ayrıca sistem durumunun bir parçası olarak korunan ve geçici olmayan ayrı bir depolamaya sahiptir; bu bellek, kelime dizileri olarak düzenlenir (yığındaki kelime adreslenebilir bayt dizilerinin aksine). Bu depolama, sözleşmelerin kalıcı verilerini tuttuğu yerdir, bir sözleşme sadece kendi depolamasıyla etkileşime girebilir. Depolama, anahtar-değer eşlemeleri şeklinde düzenlenir.
Sarı Kağıdın bu kısmında bahsedilmemiş olsa da, dördüncü bir bellek türü olduğunu bilmemizde fayda var. Çağrı verileri, bir işlemin data
parametresiyle aktarılan değerini depolamak için kullanılan bayt-adreslenebilir, salt okunur bir bellektir. EVM'nin calldata
yönetimine yönleik özel işlem kodları vardır. calldatasize
, verinin boyutunu döndürür. calldataload
, veriyi yığına yükler. calldatacopy
, veriyi belleğe kopyalar.
Standart Von Neumann mimarisi, kod ile veriyi aynı bellekte depolar. EVM güvenlik sebebiyle bu standarda uymaz; geçici belleğin paylaşılması, program kodunun değiştirilmesini mümkün kılar. Bunun yerine kod, depolamaya kaydedilir.
Kodun bellekten yürütüldüğü sadece iki durum vardır:
- Bir sözleşme (
CREATE
ya daCREATE2
) kullanarak başka bir sözleşme oluşturduğunda, sözleşme oluşturucunun kodu bellekten gelir. - Herhangi bir sözleşmenin oluşturulma sürecinde, oluşturucu kodu çalışır ve yine bellekten asıl sözleşmenin kodunu döndürür.
İstisnai yürütüm terimi, güncel sözleşmenin yürütümünün durmasına sebep olan bir istisnayı ifade eder.
9.2 Ücretlerle ilgili genel bilgi
Bu bölüm, gaz ücretlerinin nasıl hesapladığını anlatır. Üç maliyet kalemi vardır:
İşlem kodu maliyeti
Spesifik işlem kodunun öz maliyeti. Bu değere ulaşabilmek için Ek H'de (sayfa 28, (327). denklemin altında) işlem kodunun maliyet grubunu ve (324.) denklemdeki maliyet grubunu bulun. Bu size bir maliyet fonksiyonu verir, bu da çoğu durumda Ek G'deki (sayfa 27) parametreleri kullanır.
Örnek olarak CALLDATACOPY
işlem kodu Wcopy grubunun bir üyesidir. Bu grup için işlem kodu maliyeti Gverylow+Gcopy×⌈μs[2]÷32⌉ şeklindedir. Ek G'ye baktığımızda, iki sabit değerin de 3 olduğunu görürüz, bu da bize 3+3×⌈μs[2]÷32⌉ değerini verir.
Hala ⌈μs[2]÷32⌉ ifadesini çözmemiz gerekiyor. En dıştaki kısım olan ⌈ <value> ⌉ tavan fonksiyonudur ve değerden küçük olmayan en küçük tam sayıyı verir. Örneğin ⌈2.5⌉ = ⌈3⌉ = 3. İç kısım μs[2]÷32 şeklindedir. 3. bölüme (Yöntemler) bakarsak, sayfa 3'te μ, makinenin durumudur. Makine durumu sayfa 13, bölüm 9.4.1'de açıklanmıştır. O bölüme göre yığın için makine durumu parametrelerinden biri s'dir. Hepsini birleştirdiğimizde μs[2], yığındaki 2. konumdur. İşlem koduna bakarsak, yığındaki 2. konum, verinin bayt cinsinden boyutudur. Grup Wcopy, CODECOPY
ve RETURNDATACOPY
içindeki diğer işlem kodlarına bakarsak, işlem kodlarının da aynı konumda veri boyutları olduğunu görürüz. Yani ⌈μs[2]÷32⌉, kopyalanan veriyi depolayabilmek için gereken 32 baytlık kelimelerin sayısıdır. Toparlamak gerekirse, CALLDATACOPY
işlem kodunun kalıtımsal maliyeti, kopyalanan veri kelimesi başına 3 gaz artı 3'tür.
Çalıştırma maliyeti
Çağrı yaptığımız kodun çalıştırma maliyetidir.
CREATE
veCREATE2
durumlarında, yeni sözleşmenin oluşturucusu.CALL
,CALLCODE
,STATICCALL
, ya daDELEGATECALL
durumlarında, çağırdığımız sözleşme.
Bellek maliyetini genişletme
Bellek genişletme maliyeti (eğer gerekliyse).
- denklemde bu değer Cmem(μi')-Cmem(μi) olarak yazılmıştır. 9.4.1. bölüme baktığımızda μi değerinin bu bellekteki kelime sayısı olduğunu görürüz. Yani μi, bellekte işlem kodundan önce bulunan kelime sayısı ve μi', bellekte işlem kodundan sonra bulunan kelime sayısıdır.
Cmem fonksiyonu 326. denklemde tanımlanmıştır: Cmem(a) = Gmemory × a + ⌊a2 ÷ 512⌋. ⌊x⌋ taban fonksiyonudur. Bir değer verildiğinde o değerden büyük olmayan en büyük tam sayıyı verir. Örneğin, ⌊2.5⌋ = ⌊2⌋ = 2. a < √512, a2 < 512 ve taban fonksiyonunun sonucu 0 olduğunda. Yani ilk 22 kelime için (704 bayt), gereken bellek kelimesi sayısı arttıkça maliyet de doğrusal olarak artar. O noktanın ötesinde ⌊a2 ÷ 512⌋ pozitiftir. Gereken bellek yeteri kadar yüksek olduğunda gaz maliyeti bellek miktarının karesiyle orantılıdır.
Bu faktörlerin sadece kalıtımsal gaz maliyetini etkilediğini unutmayın. Ücret piyasasını ya da doğrulayıcılara yönelik son kullanıcının ne kadar ödemesi gerektiğini belirleyen ipuçlarını dikkate almaz; bu, sadece EVM'de belirli bir işlemi çalıştırmanın ham maliyetidir.
Gaz hakkında daha fazla bilgi edinin.
9.3 Yürütüm ortamı
Yürütme ortamları veri tabanında kayıtları oluşturan bir veri grubudur, I, blokzincirin durumu ya da ESM'nin bir parçası olmayan bilgiyi içerir.
Parametre | Veriye erişecek işlem kodu | Veriye erişecek Solidity kodu |
---|---|---|
Ia | ADDRESS | address(this) |
Io | ORIGIN | tx.origin |
Ip | GASPRICE | tx.gasprice |
Id | CALLDATALOAD , vs. | msg.data |
Is | CALLER | msg.sender |
Iv | CALLVALUE | msg.value |
Ib | CODECOPY | address(this).code |
IH | NUMBER ve DIFFICULTY gibi blok başlığı alanları | block.number , block.difficulty , vs. |
Ie | Sözleşmeler arası çağrılar için çağrı yığınının derinliği (sözleşme oluşturma dahil) | |
Iw | EVM'nin durumu değiştirme izni var mı yoksa statik olarak mı çalışıyor? |
- bölümün geri kalanını anlamak için birkaç parametre daha gereklidir:
Parametre | Anlatıldığı bölüm | Anlam |
---|---|---|
σ | 2 (2. sayfa, 1. denklem) | Blokzincirin durumu |
g | 9.3 (13. sayfa) | Kalan gaz |
A | 6.1 (8. sayfa) | Birikmiş yan durum (değişimler, işlem sonuna göre programlanmıştır) |
o | 9.3 (13. sayfa) | Çıktı - İç işlem durumunda (bir sözleşme bir diğerini aradığında) ve fonksiyonları görüntülemek için yapılan aramalarda (sadece bilgi istiyorken, yani bir işlem için beklemeye gerek yokken) döndürülen sonuçtur |
9.4 Yürütme ile ilgili temel bilgiler
Ön hazırlıkların hepsi tamam olduğuna göre, artık EVM'nin nasıl çalıştığı üzerinde çalışmaya başlayabiliriz.
137-142 denklemleri bize EVM'yi çalıştırmak için ilk şartları veriyor:
Sembol | Başlangıç değeri | Anlam |
---|---|---|
μg | g | Kalan gaz |
μpc | 0 | Program sayacı, yürütülecek yeni talimatın adresi |
μm | (0, 0, ...) | Bellek, tamamen sıfırlardan başlatılır |
μi | 0 | Kullanılan en yüksek bellek konumu |
μs | () | Yığın, başlangıçta boştur |
μo | ∅ | Çıktı, döndürülen veriyle (RETURN ya da REVERT ) ya da onsuz (STOP ya da SELFDESTRUCT ) durmazsak boş olan küme. |
-
denklem bize yürütüm sırasında her bir zaman noktasında dört olası durum olduğunu ve onlarla ne yapacağımızı söylüyor:
-
Z(σ,μ,A,I)
. Z, bir işlemin geçersiz bir durum geçişi yapıp yapmadığını test eden bir fonksiyonu temsil eder (bkz. istisnai durma). Değerlendirme sonucu Doğru olursa, yeni durum eskisiyle aynı olur (gazın yanması dışında) çünkü değişiklikler uygulanmamıştır. -
Yürütülen işlem kodu
REVERT
ise yeni durum yine eski durumla aynıdır, bir miktar gaz kaybedilmiştir. -
Eğer işlem dizisi
RETURN
) ile gösterildiği gibi tamamlanmışsa durum, yeni duruma güncellenir. -
1-3 uç koşullarından birinde değilsek, çalıştırmaya devam edin.
9.4.1 Makine Durumu
Bu bölüm makine durumunu daha detaylı bir şekilde anlatıyor. w'nin güncel işlem kodu olduğunu belirtiyor. Eğer μpc ||Ib|| kodun uzunluğundan daha azsa, o zaman o bayt (Ib[μpc]) işlem kodudur. Aksi halde işlem kodu, STOP
olarak tanımlanır.
Bu bir yığın makinesi olduğundan, her bir işlem kodu tarafından çıkarılmış (δ) ve sokulmuş (α) öğeleri takip etmemiz gerekir.
9.4.2 İstisnai Durma
Bu bölüm, anormal bir sonuca ulaştığımızda verilen Z fonksiyonunu tanımlar. Bu bir Boole fonksiyonudur, dolayısıyla bir mantıksal veya için ∨ işaretini ve bir mantıksal ve için ∧ işaretini kullanır.
Bu durumlardan biri doğruysa bir istisnai durma söz konusudur:
-
μg < C(σ,μ,A,I), 9.2.Bölümde gördüğümüz gibi C gaz maliyetini belirten fonksiyondur. Sonraki işlem kodunu karşılayacak kadar gaz kalmamıştır.
-
δw=∅ Eğer bir işlem kodu için çıkarılmış öğe sayısı tanımlanmamışsa, işlem kodunun kendisi tanımsız olur.
-
|| μs || < δwYığın yetersizliği, güncel işlem kodu için yığında yeterli öğe yok.
-
w = JUMP ∧ μs[0]∉D(Ib) İşlem kodu
JUMP
'tır ve adres birJUMPDEST
değildir. Sıçramalar sadece varış noktası birJUMPDEST
olduğunda geçerlidirler. -
w = JUMPI ∧ μs[1]≠0 ∧ μs[0] ∉ D(Ib) İşlem kodu
JUMPI
, durum doğru (sıfır değil), bu yüzden sıçrama gerçekleşmeli ve adres birJUMPDEST
değil. Sıçramalar sadece varış noktası birJUMPDEST
olduğunda geçerlidirler. -
w = RETURNDATACOPY ∧ μs[1]+μs[2]>|| μo || İşlem kodu
RETURNDATACOPY
. Bu işlem kodu yığın öğesinde μs[1] dönen veri arabelleğinden okunacak kaymadır ve yığın öğesi μs[2], verinin uzunluğudur. Bu durum, döndürülen arabelleğin son kısmının ötesini okumaya çalıştığınızda gerçekleşir. Çağrı verisi ya da kodun kendisi için benzer bir durum olmadığını dikkate alın. O arabelleklerin sonunun ötesini okumaya çalıştığınızda sadece sıfırlar elde edersiniz. -
|| μs || - δw + αw > 1024
Yığın taşması. Eğer işlem kodunu çalıştırmak 1024 öğeden de büyük bir yığın ile sonuçlanacaksa, iptal edilir.
-
¬Iw ∧ W(w,μ) Statik olarak mı çalışıyoruz (¬ olumsuzlama ve Iw blokzincir durumunu değiştirmemize izin veriliyorken doğrudur)? Eğer böyleyse ve durum değiştirecek bir işlem deniyorsak bu gerçekleşemez.
W(w,μ) fonksiyonu daha sonra 150.denklemde anlatılacaktır. W(w,μ) aşağıdaki durumlardan biri doğruysa doğru olur:
-
w ∈ {CREATE, CREATE2, SSTORE, SELFDESTRUCT} Bu işlem kodları, yeni bir söyleşme oluşturarak, bir değer depolayarak ya da güncel sözleşmeyi yok ederek durumu değiştirirler.
-
LOG0≤w ∧ w≤LOG4 statik olarak çağrıldıysak günlük girdileri yayımlayamayız. Günlük işlem kodları
LOG0
(A0) veLOG4
(A4) arasında değişmektedir. Günlük işlem kodundan sonraki numara, günlük girdisinin kaç konu içerdiğini belirtir. -
w=CALL ∧ μs[2]≠0 Statikken başka bir sözleşme çağırabilirsiniz fakat ona ETH transfer edemezsiniz.
-
-
w = SSTORE ∧ μg ≤ Gcallstipend
SSTORE
değerini Gcallstipend değerinden daha fazla gazınız yoksa çalıştıramazsınız (Ek G'de 2300 olarak tanımlanmıştır).
9.4.3 Sıçrama Varış Noktası Doğruluğu
Burada resmi olarak JUMPDEST
işlem kodlarını tanımlıyoruz. Sadece 0x5B bayt değerini arayamayız, çünkü bir PUSH'un içinde de olabilir (ve bu yüzden bir işlem kodu değil, veridir).
(153). denklemde bir fonksiyon tanımlıyoruz, N(i,w). İlk parametre olan i, işlem kodunun konumudur. İkinci parametre olan w, işlem kodunun kendisidir. w∈[PUSH1, PUSH32] uygularsak bu, işlem kodunun bir PUSH olduğu anlamına gelir (kare parantezler başlangıç ve bitiş noktaları arasında bir değer olabileceğini ifade eder). Bu durumda bir sonraki işlem kodu i+2+(w−PUSH1)'dedir. PUSH1
için iki bayt ilerlemeliyiz (PUSH'un kendisi ve bir bayt değeri), PUSH2
için de 3 bayt ilerlemeliyiz çünkü kendisi iki baytlık bir değerdir, vs. Diğer tüm EVM işlem kodları sadece bir bayt uzunluğundadır, bu yüzden bütün diğer durumlarda N(i,w)=i+1.
Bu fonksiyon 152. denklemde DJ(c,i) öğesini tanımlamak için kullanılır; söz konusu öğe, c kodunun içindeki tüm geçerli sıçrama varış noktalarından oluşan bir kümedir ve i işlem kodu konumundan başlar. Bu fonksiyon tekrarlı olarak tanımlanır. i≥||c|| ise bu, kodumuzun sonunda ya da sonrasındayız demektir. Daha fazla sıçrama varış noktası bulmayacağız, sadece boş kümeyi döndüreceğiz.
Tüm ayrı durumlarda yeni işlem koduna giderek kodun geri kalanına bakarız ve buradan başlayan kümeyi alırız. c[i] güncel işlem kodudur, bu yüzden N(i,c[i]) bir sonraki işlem kodunun konumudur. Bu yüzden DJ(c,N(i,c[i])), sonraki işlem kodunda başlayan geçerli işlem kodlarının bir kümesidir. Eğer şu anki işlem kodu JUMPDEST
değilse, sadece o kümeyi döndürün. JUMPDEST
ise, sonuç kümesine dahil edin ve döndürün.
9.4.4 Normal durma
Durma fonksiyonu H, üç farklı değer türü döndürebilir.
- Durma işlem kodunda değilsek, ∅ boş kümesini döndürün. Kural olarak bu değer, bir Boole yanlış değeri olarak yorumlanır.
- Eğer çıktı oluşturmayan bir durma işlem kodumuz varsa, (
STOP
ya daSELFDESTRUCT
), sıfır boyutlu baytlardan oluşan bir diziyi dönen veri olarak döndürün. Bunun boş bir kümeden çok daha farklı olduğunu not edin. Bu değer EVM'nin gerçekten durduğu anlamına gelir, yalnız okunacak bir dönen veri yoktur. - Eğer çıktı oluşturan bir işlem kodumuz varsa (
RETURN
ya daREVERT
), o işlem kodu tarafından belirtilen bayt dizisini döndürün. Bu dizi bellekten alınır, yığının başındaki değer (μs[0]) ilk bayttır ve ondan sonraki değer de (μs[1]) uzunluktur.
H.2 Talimat kümesi
EVM'nin son alt kümesine olan 9.5'e gitmeden önce, talimatların kendilerine bir bakalım. Bu talimatlar, 29. sayfada başlayan Ek H.2'de tanımlanmıştır. O spesifik işlem koduyla değişen olarak belirtilmeyen her şeyin aynı kalması beklenir. Değişen değişkenler <something>′ olarak belirtilir.
Örnek olarak ADD
işlem koduna bakalım.
Değer | Anımsatıcı | δ | α | Açıklama |
---|---|---|---|---|
0x01 | EKLE | 2 | 1 | Ekleme işlemi. |
μ′s[0] ≡ μs[0] + μs[1] |
δ yığından çıkardığımız değerlerin sayısıdır. Bu durumda iki tane var, çünkü en üst iki değeri ekliyoruz.
α geri ittiğimiz değerlerin sayısıdır. Bu durumda bir, toplam.
Bu yüzden yığının yeni başı (μ′s[0]), eski yığın başının (μs[0]) ve aşağısındaki eski değerin (μs[1]) toplamı olur.
Bu belge, "bıktırıcı bir listeyle" tüm işlem kodlarının üstünden geçmek yerine, sadece yeni bir şey tanıtan işlem kodlarını açıklıyor.
Değer | Anımsatıcı | δ | α | Açıklama |
---|---|---|---|---|
0x20 | KECCAK256 | 2 | 1 | Keccak-256 karmasını hesaplar. |
μ′s[0] ≡ KEC(μm[μs[0] . . . (μs[0] + μs[1] − 1)]) | ||||
μ′i ≡ M(μi,μs[0],μs[1]) |
Bu, belleğe erişen ilk işlem kodudur (bu durumda, salt okunur). Yine de, belleğin güncel sınırlarının ötesine kadar büyüyebilir, bu yüzden μi değerini güncellememiz gerekir. Bunu 29. sayfadaki 328. denklemde tanımlanan M fonksiyonunu kullanarak yaparız.
Değer | Anımsatıcı | δ | α | Açıklama |
---|---|---|---|---|
0x31 | BALANCE | 1 | 1 | Söz konusu hesabın bakiyesini alın. |
... |
Bakiyesini bulmamız gereken hesap: μs[0] mod 2160. Yığının başı adrestir, fakat adresler sadece 160 bit olduğu için modulo 2160 değerini hesaplarız.
Eğer σ[μs[0] mod 2160] ≠ ∅ ise, bu adresle ilgili bilgi bulunduğu anlamına gelir. Bu durumda σ[μs[0] mod 2160]b, bu hesabın bakiyesidir. Eğer σ[μs[0] mod 2160] = ∅ ise, bu da adresin başlatılmadığını ve bakiyenin 0 olduğu anlamına gelir. Hesap bilgisi alanları listesini 4. sayfadaki 4.1. bölümünde bulabilirsiniz.
İkinci denklem olan A'a ≡ Aa ∪ {μs[0] mod 2160}, sıcak depolama (yakın zamanda erişilmiş ve muhtemelen önbellekte olan depolama) ile soğuk depolama (erişilmemiş ve muhtemelen daha yavaş ve alması daha pahalı olan depolama) arasındaki maliyet farkıyla alakalıdır. Aa, işlem tarafından önceden erişilmiş adreslerin listesidir, bu yüzden 8. sayfada 6.1. bölümde anlatıldığı üzere erişilmesi daha ucuz olmalıdır. EIP-2929'da bu konuyla ilgili daha fazla okuma yapabilirsiniz.
Değer | Anımsatıcı | δ | α | Açıklama |
---|---|---|---|---|
0x8F | DUP16 | 16 | 17 | 16. yığın öğesini çoğaltın. |
μ′s[0] ≡ μs[15] |
Herhangi bir yığın öğesini kullanabilmek için onu çıkarmamız gerektiğini, yani üstündeki her yığın öğesini çıkarmamız gerektiğini unutmayın. DUP<n>
ve SWAP<n>
durumlarında bu, on altı değere kadar ekleme ve çıkarma yapmak mecburiyeti anlamına gelir.
9.5 Yürütme döngüsü
Artık her parçasına hakim olduğumuza göre, EVM'nin yürütme döngüsünün nasıl belgelendiğini sonunda anlayabiliriz.
(155). denklem, durum belirtildiğinde şunu söyler:
- σ (küresel blokzincir durumu)
- μ (EVM durumu)
- A (alt durum, değişiklikler işlem bittiğinde gerçekleşir)
- I (yürütme ortamı)
Yeni durum: (σ', μ', A', I').
(156) ila (158). denklemler yığını ve işlem kodu sebepleri yığında olan değişiklikleri tanımlar (μs). (159). denklem gazdaki değişimdir (μg). (160). denklem program sayacındaki değişikliktir (μpc). Son olarak, (161) ila (164). denklemler, diğer parametrelerin işlem kodu tarafından açıkça değiştirilmediği sürece aynı kalacaklarını belirtir.
Artık EVM tamamen açıklanmıştır.
Sonuç
Matematiksel gösterim kesindir ve Sarı Kağıdın Ethereum'un her detayını belirtmesini sağlamıştır. Yine de, bazı dezavantajları vardır:
- Sadece insanlar tarafından anlaşılabilir, bu da uygunluk testlerinin manuel olarak yazılması zorunluluğunu doğurur.
- Programcılar bilgisayar kodunu anlar. Matematiksel gösterimleri anlayabilir ya da anlamayabilirler.
Belki bu sebeplerden yeni fikir birliği katmanı spesifikasyonları Python'da yazılmaktadır. Python'da yürütüm katmanı spesifikasyonları da mevcuttur fakat bunlar henüz tamamlanmamıştır. Sarı Kağıt eksiksiz olarak Python ya da başka bir dile çevrilmeden, Sarı Kağıt kullanımda kalmaya devam edecektir ve onu okuma olanağına sahip olmak faydalıdır.
Son düzenleme: @pettinarip, 25 Şubat 2025