Ethereum Aslında Nasıl Çalışır?
Ne olduğunu bilseniz de bilmeseniz de Ethereum blockchainini muhtemelen duymuşsunuzdur. Bazı büyük dergilerin kapakları da dahil olmak üzere son zamanlarda gündemde çokça yer aldı ancak Ethereum’un tam olarak ne olduğuna dair bir temeliniz yoksa bu makaleleri okumak size çok da anlamlı gelmeyebilir. Peki nedir bu Ethereum? Özünde, dijital işlemlerin kalıcı kaydını tutan halka açık bir veritabanıdır. Buna ek olarak bu veritabanının bakımı ve güvenliği için herhangi bir merkezi otoriteye ihtiyaç duyulmamaktadır. Bunun yerine “güvensiz” (bireylerin üçüncü bir partiye veya birbirlerine güvenmek zorunda kalmadan işlemler yapabileceği) bir işlem sistemi olarak çalışır.
Kafanızda hala soru işaretleri mi var? İşte bu yazı burada devreye giriyor. Bu yazıyı yazmamın amacı karmaşık matematik içeren ve korkutucu görünen formüller olmadan Ethereum’un teknik düzeyde nasıl işlediğini açıklamak. Bir programcı olmasanız da bu yazı sayesinde en azından teknolojiyi daha iyi kavrayacağınızı umuyorum. Bazı kısımlar çok teknik veya anlaşılmaz gelebilir fakat sizi temin ederim ki bu hiç sorun olmayacak. Her küçük detayı anlamaya gerçekten gerek yok. Sadece burada anlatılanları geniş bir çerçevede anlamaya odaklanmanızı öneririm.
Bu yazıda ele alınan konuların çoğu aslında Ethereum Yellow Paper’da bahsedilen kavramların bir dökümü. Ethereum’u anlamayı kolaylaştırmak için kendi açıklamalarımı ve şemalarımı ekledim. Teknik meydan okumayı göze alacak kadar cesur olanlar Ethereum Yellow Paper’ını okumayı da deneyebilirler.
Haydi başlayalım!
Blockchain
Blockchain, “durum-paylaşımlı, kriptografik olarak güvenli işlemsel tekil makinedir”. Ne kadar da karmaşık duyuluyor değil mi? Biraz açalım.
- “Kriptografik olarak güvenli”, dijital para biriminin üretilmesinin ve bunun ardındaki süreçlerin kırılması son derece zor olan karmaşık matematiksel algoritmalarla güvence altına alındığı anlamına gelir. Bunu bir tür güvenlik duvarı gibi düşünebilirsiniz. Bu duvar kötü niyetli aktörlerin sistemi aldatabilmesini neredeyse imkansız hale getiririr. (örneğin sahte işlemler oluşturmak, işlemleri silmek vb.)
- “İşlemsel-“tekil makine”, sistemde gerçekleşen tüm işlemlerden sorumlu tek bir standart makine sonucu olduğu anlamına gelir. Başka bir deyişle, işin sonunda herkesin kabul ettiği tek bir gerçek vardır.
- “Durum-paylaşımlı” bu makinede saklanan durumun (bilginin) paylaşıldığı ve herkese açık olduğu anlamına gelir.
Ethereum bu blockchain paradigmasını uygulamaktadır.
Ethereum Blockchain Paradigması
Ethereum Blockchain’i esasen işlem tabanlı bir durum makinesidir. Bilgisayar biliminde “durum makinesi”, bir dizi girdiyi okuyacak ve bu girdilere dayanarak yeni bir duruma geçiş yapacak bir şeyi ifade eder.Ethereum’un durum makinesinde işlemlere bir “genesis durumu (genesis state) ile başlarız. Bu, ağ üzerinde herhangi bir işlem gerçekleşmeden önceki boş bir sayfaya benzer. İşlemler gerçekleştirildiğinde ise genesis durumu bir “son duruma” dönüşür. Ayrıca zaman fark etmeksizin son durum Ethereum’un mevcut durumunu temsil eder.
Yukarıda bahsettiğimiz Ethereum’un “mevcut durumunun” öncesinde yapılmış milyonlarca işlem vardır. Bu işlemler “bloklar” halinde gruplandırılmıştır. Bir blok bir dizi işlem içerir ve aynı zamanda her blok bir önceki blokla birlikte zincirlenmiştir.
Mevcut durumdan bir sonraki duruma geçebilmek için bir işlemin “geçerli” olması gerekir. İşlemler, geçerli sayılabilmeleri için “madencilik” olarak bilinen bir doğrulama sürecinden geçmelidirler. Madencilik, bir grup düğümün (yani bilgisayarın) geçerli işlemlerden oluşacak bir blok üretmek hesaplama kaynaklarını harcamasına verilen isimdir.
Ağ üzerinde kendini “madenci” olarak ilan eden herhangi bir düğüm bir blok oluşturmayı ve doğrulamayı deneyebilir. Dünyanın dört bir yanından çok sayıda madenci aynı anda bir blok oluşturmaya ve onu doğrulamaya çalışır. Her madenci, blockchaine bir blok gönderirken matematiksel bir “kanıt” sunar ve bu kanıt bir garanti rolü oynar. “Kanıt varsa, blok geçerli olmalıdır.”
Bir bloğun ana blockchaine eklenebilmesi için madencinin bu bloğu diğer madencilerden daha hızlı kanıtlaması gerekir. Bir madencinin matematiksel bir kanıt sunarak her bloğu doğrulama süreci “iş kanıtı” (proof of work) olarak bilinir.
Yeni bir bloğu doğrulamayı başaran bir madenci, bu işi yaptığı için belirli bir değerle ödüllendirilir. Peki nedir bu değer? “Ether”. Ethereum blockchaini, “Ether” adı verilen kendine özgü bir dijital token kullanır. Bir madenci bir bloğu her kanıtladığında yeni Ether tokenları üretilir ve madenci bu tokenlarla ödüllendirilir.
Peki herkesin tek bir blockchaine bağlı kalması nasıl garantileniyor? Ya bir grup madenci kendi blockchainini üretmeye karar verir ve sistemi manipüle etmeye çalışırsa? Bunun yaşanmayacağından nasıl emin olabiliriz?
Daha önce bir blockchaini durum-paylaşımlı, kriptografik olarak güvenli, işlemsel-tekil makine olarak tanımlamıştık. Bu tanımdan yola çıkarak da “mevcut durumun” herkes tarafından kabul edilmesi gereken tek bir gerçek olduğunu açıklamıştık. Bu durumda birden fazla duruma (ya da zincire) sahip olmak tüm sistemi mahveder çünkü hangi durumun doğru olduğu konusunda bir uzlaşmaya varmak imkansızdır. Zincirler herhangi bir şekilde birbirinden ayrılırsa bir zincirde 10, diğerinde 20 ve bir başkasında 40 coin’e sahip olabilirsiniz. Bu senaryoda, hangi zincirin geçerli olduğunu belirlemenin bir yolu olmayacaktır.
Birden fazla yol oluşturulduğunda bir “çatal” meydana gelir. Genellikle çatallanmalardan kaçınmak isteriz çünkü yukarda da bahsettiğimiz gibi bunlar sistemi bozar ve insanları hangi zincire “inandıklarını” seçmeye zorlarlar. Bu durumda da, örneğin, çoğunluğun avantajlı gördüğü ve seçtiği yanlış zincir, başkalarının doğru zincirdeki haklı kazançlarından faydalanamamalarına sebep olabilir.Ethereum, hangi yolun en geçerli olduğunu belirlemek ve birden fazla zinciri önlemek için “GHOST Protokolü” adı verilen bir mekanizma kullanır.
“GHOST” = “Greedy Heaviest Observed Subtree”
Basit bir ifadeyle GHOST protokolü, üzerinde en fazla hesaplama yapılmış olan yolu seçmemiz gerektiğini söyler. Bu yolu belirlemenin yollarından biri en son bloğun “yaprak blok” blok numarasını kullanmaktır. Bu numara, mevcut yoldaki toplam blok sayısını temsil eder (genesis bloğu sayılmaz). Blok numarası ne kadar yüksekse, yol o kadar uzun ve son yaprağa ulaşmak için harcanmış olması gereken madencilik eforu da o kadar büyüktür. Bu mantığı kullanmak, mevcut durumun kabul edilecek versiyonunda uzlaşmamızı sağlar.Artık blockchainin ne olduğuna dair bir fikir edindiğimize göre, Ethereum sisteminin içerdiği ana bileşenleri daha da derinden inceleyelim:
- Hesaplar
- Durum
- Gaz ve ücretler
- İşlemler
- Bloklar
- İşlem yürütme
- Madencilik
- İş kanıtı (PoW)
Not: Yazının ilerleyen kısımlarında “X’in hashi” kalıbını sıkça kullanacağım. Bu kalıpta kastettiğim hash, Ethereum’un kullandığı KECCAK-256 hash’i.
Hesaplar
Ethereum’un küresel “durum-paylaşımı” bir mesaj iletme çerçevesi (framework) aracılığıyla birbiriyle etkileşime girebilen birçok küçük nesneden “hesap” oluşur. Her hesabın kendisiyle ilişkili bir durumu ve 20 baytlık bir adresi vardır. Ethereum’daki adresler, herhangi bir hesabı tanımlamak için kullanılan 160 bitlik bir tanımlayıcıdır.
İki tür hesap vardır:
- Özel anahtarlar tarafından kontrol edilen ve kendileriyle ilişkili bir kodu olmayan, harici olarak sahip olunan hesaplar (eoa:externally-owned-account).
- Sözleşme kodu tarafından kontrol edilen ve kendileriyle ilişkili bir koda sahip olan sözleşme hesapları (ca:contract account).
Harici Olarak Sahip Olunan Hesaplar (EOA) vs Sözleşme Hesapları (CA)
Harici olarak sahip olunan hesaplar ile sözleşme hesapları arasındaki temel farkları anlamak önemlidir. Harici olarak sahip olunan hesaplar, kendi özel anahtarını kullanarak bir işlem oluşturup imzalayarak diğer harici olarak sahip olunan hesaplara veya diğer sözleşme hesaplarına mesaj gönderebilir. Harici olarak sahip olunan iki hesap arasındaki bir mesaj basitçe bir “değer transferi”dir. Ancak harici olarak sahip olunan bir hesaptan bir sözleşme hesabına gönderilen bir mesaj, sözleşme hesabının ilişkili kodunu etkinleştirerek çeşitli eylemler gerçekleştirmesini sağlar (örneğin token’ları aktarmak, dahili depolamaya yazmak, yeni token’lar basmak, basit hesaplamalar yapmak, yeni sözleşmeler oluşturmak vb.)
Harici olarak sahip olunan hesapların aksine sözleşme hesapları, kendi başlarına yeni işlemler başlatamaz. Sadece aldıkları diğer işlemlere (harici olarak sahip olunan bir hesaptan veya başka bir sözleşme hesabından) yanıt olarak işlem başlatabilir. “İşlemler ve Mesajlar” bölümünde sözleşmeden sözleşmeye çağrılar hakkında daha fazla bilgi edineceğiz.Bu nedenle, Ethereum blockchain’inde meydana gelen herhangi bir eylem her zaman harici olarak kontrol edilen hesaplardan gönderilen işlemler tarafından harekete geçirilir.
Hesap Durumu
Hesap durumu, hesap türünden bağımsız olarak mevcut olan dört farklı bileşenden oluşur:
- Nonce: Hesap harici olarak sahip olunan bir hesapsa, bu sayı hesabın adresinden gönderilen işlem sayısını; sözleşme hesabı ise, hesap tarafından oluşturulan sözleşmelerin sayısını temsil eder.
- Balance: Adresin sahip olduğu Wei sayısını temsil eder. Ether başına 1e+18 Wei vardır.
- StorageRoot: Bir “Merkle Patricia” ağacının kök düğümünün hash’i (Merkle ağaçlarını daha sonra açıklayacağız). Bu ağaç, bu hesabın depolama içeriğini kodlar ve varsayılan hali boştur.
- CodeHash: Bu, hesabın EVM (Ethereum Virtual Machine-Ethereum Sanal Makinesi- bu konuda da daha sonra bilgi vereceğiz) kodunun hash’i. Sözleşme hesapları için bu kod hashlenir ve codeHash olarak saklanır. Harici olarak sahip olunan hesaplar için ise codeHash alanı boş bir dizenin (string) hash’idir.
Genel Durum
Ethereum’un global durumunun hesap adresleri ve hesap durumları arasındaki bir eşleşmeden oluştuğunu artık biliyoruz. Bu eşleşme, Merkle Patricia Ağacı olarak bilinen bir veri yapısında saklanır.
Bir Merkle Ağacı, aşağıdaki özelliklere sahip bir dizi düğümden oluşan bir tür ikili ağaçtır.
- Ağacın alt kısmında temel verileri içeren çok sayıda yaprak düğümü
- Her bir düğümün iki alt düğümünün hash’i olduğu bir ara düğüm kümesi
- Ağacın tepesini temsil eden ve iki alt düğümünün hash’inden oluşan tek bir kök düğüm
Ağacın en altındaki veriler, depolamak istediğiniz verileri parçalara bölerek, parçaları kovalara ayırarak, ardından her kovanın hash’ini alarak ve kalan toplam hash sayısı yalnızca bir olana kadar aynı işlemi tekrarlayarak oluşturulur: Kök hash (root hash).
Bu ağacın içinde saklanan her değer için bir anahtar olması gerekir. Anahtarın, ağacın kök düğümünden itibaren size yaprak düğümlerinde saklanan ilgili değere ulaşmak için hangi alt düğümü takip etmeniz gerektiğini söylemesi gerekir. Ethereum’un durumunda, durum ağacının anahtar/değer eşlemesi, her bir hesap için balance, nonce, codeHash ve storageRoot (ayrıca storageRoot’un kendisi de bir ağaçtır) dahil olmak üzere adresler ve bunlarla ilişkili hesaplar arasındadır.
Aynı ağaç yapısı, işlemleri ve makbuzları saklamak için de kullanılır. Daha spesifik olmak gerekirse, her blok, aşağıdakiler de dahil olmak üzere üç farklı Merkle Ağacı yapısının kök düğümünün hash’ini depolayan bir başlığa sahiptir:
- Durum Ağacı (stateRoot)
- İşlem Ağacı (transactionsRoot)
- Makbuz Ağacı (receiptsRoot)
Tüm bu bilgilerin Merkle ağaçlarında verimli bir şekilde saklanabilmesi, Ethereum’da “hafif istemciler” veya “hafif düğümler” dediğimiz şey için inanılmaz derecede kullanışlıdır. Bir blokchaininin bir grup düğüm tarafından yönetildiğini unutmayın. Genel olarak konuşmak gerekirse, iki tür düğüm vardır:” tam düğümler” ve “hafif düğümler”.
Tam arşiv düğümü, oluşum bloğundan mevcut ana bloğa kadar tüm zinciri indirerek ve içerdiği tüm işlemleri gerçekleştirerek blok zincirini senkronize eder. Genelde madenciler tam arşiv düğümünü depolar çünkü madencilik sürecinde bu gereklidir. Her bir işlemi gerçekleştirmeden tam bir düğüm indirmek de mümkündür fakat her iki durumda da herhangi bir tam düğüm tüm zinciri içinde bulundurur.
Ancak bir düğümün her işlemi yürütmesi ya da geçmiş verileri kolayca sorgulaması gerekmediği sürece zincirin tamamını depolamaya gerek yoktur. Hafif düğüm kavramı da tam olarak burada devreye girer. Hafif düğümler, zincirin tamamını indirip depolamak ve tüm işlemleri yürütmek yerine, herhangi bir işlem yürütmeden veya ilişkili herhangi bir durumu almadan yalnızca genesis bloğundan mevcut duruma kadar olan başlık zincirini indirir. Hafif düğümler, üç ağacın hash’lerini içeren blok başlıklarına erişebildikleri için işlemler, olaylar, bakiyeler (balance) vb. hakkında doğrulanabilir yanıtları kolayca oluşturabilir ve alabilirler.
Bunun işe yaramasının sebebi Merkle ağacındaki hash’lerin yukarı doğru yayılmasıdır — kötü niyetli bir kullanıcı Merkle ağacının en altına sahte bir işlem yerleştirmeye çalışırsa, bu değişiklik yukarıdaki düğümün hash’inde bir değişikliğe neden olacak, bu da onun üzerindeki düğümün hashing değiştirecek ve sonunda ağacın kökünü değiştirene kadar bu böyle devam edecektir.Bir veri parçasını doğrulamak isteyen herhangi bir düğüm, bunu yapmak için “Merkle kanıtı” adı verilen bir şey kullanabilir. Bir Merkle kanıtı şunlardan oluşur:
- Doğrulanacak bir veri yığını ve onun hash’i
- Ağacın kök hash’i
- “Dal” (Yığından köke giden yol boyunca yukarı çıkan tüm ortak karmalar-the branch)
Kanıtı okuyan herkes, o dalın hash’inin ağaç boyunca tutarlı olduğunu ve dolayısıyla verilen yığının aslında ağaçta o konumda olduğunu doğrulayabilir.
Özetle, bir Merkle Patricia Ağacı kullanmanın faydası, bu yapının kök düğümünün kriptografik olarak ağaçta depolanan verilere bağlı olması ve bu nedenle kök düğümünün hash’inin bu veriler için güvenli bir kimlik olarak kullanılabilmesidir. Blok başlığı mevcut durumun, işlemlerin ve makbuz ağaçlarının kök hash’ini içerdiğinden, herhangi bir düğüm Ethereum durumunun küçük bir bölümünü, potansiyel olarak sınırsız boyutta olabilecek tüm durumu depolamaya gerek kalmadan doğrulayabilir.
Gaz ve Ücretler
Ethereum’daki önemli kavramlardan biri de gaz ve ödeme kavramlarıdır. Ethereum ağındaki bir işlem sonucunda gerçekleşen her hesaplama bir ücrete tabidir — beleşe yemek yok! — Bu ücret “gas” (gaz) adı verilen bir değerle ödenir.
Gaz, belirli bir hesaplama için gereken ücretleri ölçmek için kullanılan bir birimdir. Gaz fiyatı, her bir gaz birimi için harcamak istediğiniz Ether miktarıdır ve “gwei” ile ölçülür. (“Wei” en küçük Ether birimidir ve ¹⁰¹⁸ Wei 1 Ether’i temsil eder.) Bir gwei 1.000.000.000 Wei’dir.
Her işlemde, gönderici bir gaz limiti ve gaz fiyatı belirler. Gaz fiyatı ve gaz limitinin çarpımı, göndericinin bir işlemi gerçekleştirmek için ödemek istediği maksimum Wei miktarını temsil eder.
Örneğin, gönderenin gaz limitini 50.000 ve gaz fiyatını 20 gwei olarak belirlediğini varsayalım. Bu, göndericinin bu işlemi gerçekleştirmek için en fazla 50.000 x 20 gwei = 1.000.000.000.000 Wei = 0,001 Ether harcamayı göze aldığı anlamına gelir.Gaz limitinin, göndericinin harcamak istediği maksimum gazı temsil ettiğini unutmayalım. İşleme ancak hesap bakiyelerinde bu maksimum miktarı karşılayacak kadar Ether varsa devam edilebilir yani. Bu miktar kitlenir ve işlemin sonunda göndericiye kullanılmayan gaz (eğer varsa) için geri ödeme yapılır ve orijinal kur üzerinden takas edilir.
Göndericinin işlemi gerçekleştirmek için gerekli gazı sağlamaması durumunda ise işlem “gazsız” şekilde yürütülür ve geçersiz kabul edilir. İşlem süreci iptal edilir ve meydana gelen tüm durum değişiklikleri tersine çevrilir, böylece Ethereum’un işlemden hemen önceki durumuna geri döneriz. Ayrıca hangi işlemin denendiği, nerede başarısız olduğuna dair bir kayıt da tutulur. Ve makine, gazı bitmeden önce hesaplamaları yapmak için zaten bir efor harcadığından, mantıken göndericiye bir gaz iadesi de yapılmaz.
Peki bu gaz parası tam olarak nereye gidiyor? Gönderici tarafından gaz için harcanan tüm para, genellikle madencinin adresi olan “hak sahibi” (beneficiary) adresine gönderilir. Madenciler hesaplamaları yürütmek ve işlemleri doğrulamak için bir çaba harcadıklarından, madenciler gaz ücretini bir ödül olarak alırlar.
Mantıken, göndericinin ödemeyi göze aldığı gaz fiyatı ne kadar yüksekse, madencinin işlemden elde edeceği değer de o kadar yüksek olur. Dolayısıyla madencilerin bu işlemi seçme olasılığı da artar. Bu şekilde, madenciler hangi işlemleri doğrulamak ya da göz ardı etmek istediklerini seçmekte özgür olurlar. Madenciler, göndericileri hangi gaz fiyatını belirleyecekleri konusunda yönlendirmek için işlemleri gerçekleştirecekleri minimum gaz fiyatını ilan etme seçeneğine sahiptir.
Depolama İçin de Ücretler Vardır
Gaz sadece hesaplama adımlarını ödemek için değil aynı zamanda depolama kullanımını ödemek için de kullanılır. Depolama için toplam ücret, kullanılan 32 baytın en küçük katı ile orantılıdır.
Depolama ücretlerinin bazı farklılıkları vardır. Örneğin, artan depolama alanı tüm düğümlerdeki Ethereum durum veritabanının boyutunu artırdığından, depolanan veri miktarını küçük tutmak için bir teşvik vardır. Bu nedenle, bir işlemin depolama alanındaki bir girişi temizleyen bir adımı varsa, bu işlemi gerçekleştirme ücretinden feragat edilir VE depolama alanını boşaltmak için bir geri ödeme yapılır.
Ücretlerin Amacı Nedir?
Ethereum’un çalışma şeklinin önemli yönlerinden biri, yukarıda da bahsettiğimiz gibi ağ tarafından yürütülen her bir işlemin aynı anda her tam düğüm tarafından gerçekleştirilmesidir. Bununla birlikte, EVM üzerindeki hesaplama adımları çok pahalıdır. Bu nedenle, Ethereum akıllı sözleşmeleri, dosya depolama, e-posta veya makine öğrenimi gibi ağı zorlayabilecek daha karmaşık kullanımlar yerine, basit iş mantığını yürütmek veya imzaları ve diğer kriptografi nesneleri doğrulamak gibi basit görevler için en iyi şekilde kullanılır (en azından amaç bu). Ücret uygulamak, kullanıcıların ağı aşırı zorlamasını bu anlamda engellemiş olur.
Ethereum bir tam-Turing dilidir. (Turing makinesi, herhangi bir bilgisayar algoritmasını simüle edebilen bir makinedir. İlginenler yazının sonuna bıraktığım linkleri incleyebilirler.) Bu, döngülere (loop) izin verir ve Ethereum’u bir programın sonsuza kadar çalışıp çalışmayacağını belirleyemediğiniz bir problem olan “durma” problemine duyarlı hale getirir. Yani ücretler olmasaydı, kötü niyetli bir aktör herhangi bir yankı uyandırmadan bir işlem içinde sonsuz bir döngü yürüterek ağı kolayca bozmaya çalışabilirdi. Dolayısıyla, ücretler ağı kasıtlı saldırılara karşı korur.
“Neden depolama için de ödeme yapmak zorundayız?” diye düşünüyor olabilirsiniz. Tıpkı hesaplamalarda olduğu gibi, Ethereum ağındaki depolama da tüm ağın yükünü üstlenmesi gereken bir maliyettir.
İşlemler ve Mesajlar
Ethereum’un işlem tabanlı bir durum makinesi olduğunu daha önce belirtmiştik. Başka bir deyişle, farklı hesaplar arasında gerçekleşen işlemler Ethereum’un küresel durumunu bir durumdan diğerine taşıyan şeydir.
En temel anlamda bir işlem, harici olarak sahip olunan bir hesap tarafından oluşturulan, serileştirilen ve ardından blockchaine gönderilen kriptografik olarak imzalanmış bir talimat parçasıdır.
İki tür işlem vardır: mesaj çağrıları ve sözleşme oluşturma (yani yeni Ethereum sözleşmeleri oluşturan işlemler).
Tüm işlemler, türlerine bakılmaksızın aşağıdakileri içerir:
- nonce: gönderici tarafından gönderilen işlem sayısının bir sayımı.
- gasPrice: göndericinin işlemin gerçekleştirilmesi için gereken gaz birimi başına ödemeye razı olduğu Wei sayısı.
- gasLimit: göndericinin bu işlemi gerçekleştirmek istediği maksimum gaz miktarı. Bu miktar, herhangi bir hesaplama yapılmadan önce belirlenir ve önceden belirlenir.
- to: alıcının adresi. Sözleşme oluşturan bir işlemde, sözleşme hesap adresi henüz mevcut değildir ve bu nedenle boş bir değer kullanılır.
- value: göndericiden alıcıya aktarılacak Wei miktarı. Sözleşme oluşturan bir işlemde bu değer, yeni oluşturulan sözleşme hesabındaki başlangıç bakiyesi olarak hizmet eder.
- V, r, s: işlemin göndericisini tff anımlayan imzayı oluşturmak için kullanılır.
- init (yalnızca sözleşme oluşturan işlemler için mevcuttur): Yeni sözleşme hesabını başlatmak için kullanılan bir EVM kod parçası. init yalnızca bir kez yürütülür ve ardından atılır. init ilk yürütüldüğünde sözleşme hesabıyla kalıcı olarak ilişkilendirilen kod parçası olan hesap kodunun gövdesini yürütür.
- data (yalnızca mesaj çağrıları için var olan, isteğe bağlı alan): mesaj çağrısının girdi verileri (yani parametreler). Örneğin, bir akıllı sözleşme bir alan adı kayıt hizmeti olarak hizmet veriyorsa, bu sözleşmeye yapılan bir çağrıda alan adı ve IP adresi gibi girdi alanları beklenebilir.
“Hesaplar” bölümünde işlemlerin -hem mesaj çağrıları hem de sözleşme oluşturma işlemleri- her zaman harici olarak sahip olunan hesaplar tarafından başlatıldığını ve blok zincirine gönderildiğini öğrendik. Bunu işlemlerin dış dünya ile Ethereum’un iç durumu arasında köprü kurması olarak da düşünebiliriz.
Ancak bu, sözleşmelerin diğer sözleşmelerle iletişim kuramayacağı anlamına gelmez. Ethereum’un durumunun küresel kapsamı içinde var olan sözleşmeler, aynı kapsam içindeki diğer sözleşmelerle iletişim kurabilir. Bunu yapmalarının yolu, diğer sözleşmelere “mesajlar” ya da “dahili işlemler” göndermektir. Mesajların ya da dahili işlemlerin bildiğimiz klasik işlemlere benzediğini düşünebiliriz ancak aralarındaki en büyük fark, bunların harici olarak sahip olunan hesaplar tarafından değil, sözleşmeler tarafından oluşturulmalarıdır. Bunlar, işlemlerin aksine serileştirilmeyen ve yalnızca Ethereum yürütme ortamında var olan sanal nesnelerdir.
Bir sözleşme başka bir sözleşmeye dahili bir işlem gönderdiğinde, alıcı sözleşme hesabındaki kod yürütülür.Son olarak, dikkat edilmesi gereken bir önemli husus da dahili işlemlerin veya mesajların herhangi bir gasLimit içermediğidir. Bunun nedeni, gaz limitinin orijinal işlemin harici yaratıcısı (yani harici olarak sahip olunan bir hesap) tarafından belirlenmesidir (burada da böyle bir şey yok). Harici olarak sahip olunan hesabın belirlediği gaz limiti, sözleşmeden sözleşmeye mesajlar gibi bu işlemin bir sonucu olarak ortaya çıkan tüm alt işlemler de dahil olmak üzere işlemi gerçekleştirmek için yeterince yüksek olmalıdır. İşlemler ve mesajlar zincirinde belirli bir mesaj yürütme işleminde gaz biterse, bu mesajın yürütmesi, yürütme tarafından tetiklenen sonraki mesajlarla birlikte geri döner. Ancak ana yürütmenin geri dönmesi gerekmez.
Bloklar
Tüm işlemler “bloklar” halinde gruplandırılır. Daha önce de öğrendiğimiz gibi bir blockchain, birbirine zincirlenmiş bir dizi blok içerir.
Ethereum’da bir blok aşağıdakilerden oluşur:,
- Blok başlığı
- Bu blokta yer alan işlem kümesi hakkında bilgi
- Mevcut bloğun ommers’i için bir dizi başka blok başlığı
Ommer da ne?
Ommer, üst öğesi geçerli bloğun iki üst öğesine eşit olan bir bloktur. Ommerlerin ne için kullanıldığına ve bir bloğun neden ommerler için blok başlıkları içerdiğine hızlıca bir göz atalım.
Ethereum’un oluşturulma şekli nedeniyle, blok süreleri Bitcoin (~10 dakika) gibi diğer blockchainlerden çok daha düşüktür (~15 saniye). Bu da işlemlerin daha hızlı işlenmesini sağlar. Bununla birlikte, daha kısa blok sürelerinin dezavantajlarından biri, madenciler tarafından çok daha fazla rakip blok çözümünün bulunmasıdır. Bu rakip bloklar “Orphaned Block” olarak da bilinen yetim blok olarak adlandırılır (yani kazılan bu “fazladan” bloklar ana zincire girmez).
Ommer’lerin amacı, madencilerin bu yetim blokları dahil etmeleri için ödüllendirilmelerine yardımcı olmaktır. Madencilerin dahil ettiği ommerler “geçerli” olmalıdır, yani mevcut bloğun altıncı nesli veya daha küçük bir neslin içinde olmalıdır. Altı çocuktan sonra, eski yetim bloklara artık başvurulamaz (çünkü daha eski işlemleri dahil etmek işleri biraz karmaşıklaştıracaktır).
Ommer bloklar, tam bir bloktan daha küçük bir ödül alır. Fakat yine de madenciler için bu öksüz blokları dahil etmek ve bir ödül almak için hala bir miktar teşvik vardır (yani bu ommer olayı küçük bir teselli ödülü gibi düşünebiliriz).
Blok Başlığı
Bloğun aslına geri dönelim. Daha önce her bloğun bir “blok başlığı” olduğundan bahsetmiştik, ancak bu tam olarak nedir?
Bir blok başlığı, bloğun aşağıdakilerden oluşan bir bölümüdür:
- parentHash: üst bloğun başlığının bir hash’i (blok setini bir “zincir” yapan şey budur)
- ommersHash: geçerli bloğun ommers listesinin bir hash’i
- beneficiary: bu bloğun madenciliği için ücretleri alan hesap adresi
- stateRoot: durum üçlüsünün kök düğümünün hash’i (durum üçlüsünün başlıkta saklandığını ve hafif istemcilerin durum hakkında herhangi bir şeyi doğrulamasını kolaylaştırdığını nasıl öğrendiğimizi hatırlayın).
- transactionsRoot: bu blokta listelenen tüm işlemleri içeren ağacın kök düğümünün hash’i
- receiptsRoot: bu blokta listelenen tüm işlemlerin makbuzlarını içeren ağacın kök düğümünün hash’i
- logsBloom: günlük bilgilerinden oluşan bir Bloom filtresi (veri yapısı)
- difficulty: bu bloğun zorluk seviyesi
- number: mevcut bloğun sayısı (genesis bloğunun blok numarası sıfırdır; blok numarası sonraki her blok için 1 artar)
- gasLimit: blok başına geçerli gaz limiti
- gasUsed: bu bloktaki işlemler tarafından kullanılan toplam gaz miktarı
- timestamp: bu bloğun başlangıcının unix zaman damgası
- extraData: bu blokla ilgili ekstra veriler
- mixHash: nonce ile birleştirildiğinde bu bloğun yeterli hesaplamayı gerçekleştirdiğini kanıtlayan bir hash
- nonce: mixHash ile birleştirildiğinde bu bloğun yeterli hesaplamayı gerçekleştirdiğini kanıtlayan bir hash
Her blok başlığının aşağıdakiler için üç ağaç yapısı içerdiğine dikkat edin:
- durum (stateRoot)
- işlemler (transactionsRoot)
- makbuzlar (receiptsRoot)
Bu ağaç yapıları, daha önce konuştuğumuz Merkle Patricia ağaçlarıyla aynı aslında. Bazı terimleri açıklığa kavuşturalım.
Günlükler (Logs)
Ethereum, çeşitli işlemlerin ve mesajların izlenmesini mümkün kılmak için günlüklere izin verir. Bir sözleşme, günlüğe kaydetmek istediği “olayları” tanımlayarak açıkça bir günlük oluşturabilir.
Bir günlük girdisi şunları içerir:
- Günlükçünün (logger) hesap adresi,
- Bu işlem tarafından gerçekleştirilen çeşitli olayları temsil eden bir dizi konu,
- bu olaylarla ilişkili herhangi bir veri.
Günlükler, sonsuz günlük verilerini verimli bir şekilde depolayan bir “bloom” filtresinde saklanır.
İşlem Makbuzu
Başlıkta saklanan günlükler, işlem makbuzunda bulunan günlük bilgilerinden gelir. Tıpkı bir mağazadan bir şey satın aldığınızda makbuz aldığınız gibi, Ethereum da her işlem için bir makbuz oluşturur. Ve tahmin edebileceğiniz gibi, her makbuz işlem hakkında belirli bilgiler içerir. Bir makbuzda aşağıdaki gibi öğeler bulunur:
- Blok numarası
- Blok hash’i
- İşlem hash’i
- Mevcut işlem tarafından kullanılan gaz
- Geçerli işlem yürütüldükten sonra geçerli blokta kullanılan kümülatif (birikerek artan) gaz
- Geçerli işlem yürütülürken oluşturulan günlükler
Blok Zorluğu
Bir bloğun “zorluğu”, blokları doğrulamak için gereken sürede tutarlılığı sağlamak için kullanılır. Genesis bloğunun zorluk derecesi 131.072’dir ve bundan sonraki her bloğun zorluk derecesini hesaplamak için özel bir formül kullanılır. Belirli bir blok bir önceki bloktan daha hızlı doğrulanırsa, Ethereum protokolü o bloğun zorluğunu artırır.
Bloğun zorluğu, “iş kanıtı” (proof-of-work (PoW)) algoritması kullanılarak bir blok madenciliği yapılırken hesaplanması gereken bir has olan nonce’ı da etkiler.
Bloğun zorluğu ve nonce arasındaki ilişki matematiksel olarak şu şekilde formüle edilir:(Hd, burada zorluğu temsil ediyor)
Zorluk eşiğini karşılayan bir nonce bulmanın tek yolu, tüm olasılıkları sıralamak için proof-of-work algoritmasını kullanmaktır (Artık değil). Bir çözüm bulmak için beklenen süre zorluk derecesiyle orantılıdır — zorluk derecesi arttıkça nonce’u bulmak zorlaşır, dolayısıyla bloğu doğrulamak da zorlaşır ve bu da yeni bir bloğu doğrulamak için gereken süreyi artırır. Dolayısıyla protokol, bir bloğun zorluğunu ayarlayarak bloğu doğrulamanın ne kadar süreceğini hesaplayabilir.
Öte yandan protokol, doğrulama süresi yavaşlıyorsa zorluğu azaltır. Bu şekilde, doğrulama süresi için sabit bir oranı (ortalama olarak her 15 saniyede bir blok) korumak için ayarlamalar yapar.