Ana içeriğe geç

Python Geliştiricileri için Ethereum'a Giriş, Bölüm 1

pythonweb3.js
Acemi
Marc Garreau
Snake charmers(opens in a new tab)
8 Eylül 2020
10 dakikalık okuma minute read

Şu Ethereum denen şeyi duydunuz ve konuya daha derinlemesine inmeye hazır mı hissediyorsunuz? Bu gönderi, bazı blok zinciri temellerini hızlı bir şekilde ele alacak, ardından sizi simüle edilmiş bir Ethereum düğümü ile etkileşime sokarak blok verilerini okuyacak, hesap bakiyelerini kontrol edecek ve işlemleri gönderecektir. Bu arada, uygulama oluşturmanın geleneksel yolları ile bu yeni merkeziyetsiz paradigma arasındaki farkları vurgulayacağız.

(Hafif) ön koşullar

Bu gönderi, birçok türden geliştiricileri için ulaşılabilir olmayı arzulamaktadır. Python araçları kullanılacaktır, ama sadece fikirler için bir araç olacaklardır: Bir Python geliştiricisi değilseniz de sorun olmaz. Gelgelelim, Ethereum ile ilgili kısımlara hızlıca geçebilmemiz için bazı şeyleri bildiğinizi varsayacağım.

Varsayımlar:

  • Bir terminalde gezinebildiğiniz,
  • Birkaç satır Python kodu yazdığınız,
  • Python'un 3.6 ya da daha yüksek bir sürümü cihazınızda yüklüdür (bir sanal ortam(opens in a new tab) kullanılması teşvik edilmektedir), ve
  • Python’un paket indiricisi pip'i kullandığınız varsayılır. Buna karşın, eğer varsayımlardan herhangi biri doğru değilse, veya bu makaledeki kodu yeniden uygulamayı düşünmüyorsanız, büyük ihtimalle yine de gayet iyi şekilde takip edebilirsiniz.

Kısaca blok zincirleri

Ethereum'u tanımlamanın birçok yolu bulunsa da Ethereum, özünde bir blok zinciridir. Blok zincirleri bir dizi bloktan oluşur, bu yüzden oradan başlayalım. En basit şekilde, Ethereum blok zincirindeki her bir blok sadece birtakım meta veri ve bir dizi işlemdir. JSON formatında, şöyle bir şeye benzer:

1{
2 "number": 1234567,
3 "hash": "0xabc123...",
4 "parentHash": "0xdef456...",
5 ...,
6 "transactions": [...]
7}
Kopyala

Her blok kendinden önceki bloğa doğru bir referansa sahiptir; parentHash kısaca önceki bloğun hash değeridir.

Not: Ethereum, hash fonksiyonlarını(opens in a new tab) sürekli sabit büyüklükteki değerler ("hash değerleri") oluşturmak için kullanır. Hash değerleri, Ethereum'da büyük bir rol oynar ama şimdilik onları benzersiz kimlikler olarak düşünebilirsiniz.

Her bloğun içindeki verileri içeren bir blok zincirini gösteren bir diyagram

Bir blok zinciri aslen bağlantılı bir dizidir; her bir blok önceki bloğa doğru bir referansa sahiptir.

Bu veri yapısı yeni bir şey değildir ama ağı yöneten kurallar (yani eşler arası protokoller) öyledir. Merkezi bir otorite yoktur; eşler ağı, ağı sürdürmek için iş birliği yapmalı ve bir sonraki bloğa hangi işlemlerin dahil edileceğine karar vermek için rekabet etmelidir. Bu nedenle, bir arkadaşınıza biraz para göndermek istediğinizde, bu işlemi ağa yayınlamanız ve ardından gelecek bir bloğa eklenmesini beklemeniz gerekir.

Blok zincirinin, paranın bir kullanıcıdan diğerine gerçekten gönderildiğini doğrulamasının tek yolu, o blok zincirine özgü (yani, blok zinciri tarafından oluşturulan ve yönetilen) bir para birimi kullanmaktır. Ethereum'da bu para birimine ether denir ve Ethereum blok zinciri, hesap bakiyelerinin tek resmi kaydını içerir.

Yeni bir paradigma

Bu merkeziyetsiz yeni teknoloji yığını, yeni geliştirici araçları ortaya çıkardı. Bu tür araçlar birçok programlama dilinde mevcuttur, ancak biz Python merceğinden bakacağız. Tekrarlamak gerekirse: Python tercih ettiğiniz dil olmasa bile, takip etmek çok zor olmayacaktır.

Ethereum ile etkileşim kurmak isteyen Python geliştiricilerinin Web3.py(opens in a new tab).'ye ulaşması muhtemeldir. Web3.py, bir Ethereum düğümüne bağlanma ve ondan veri gönderme ve alma şeklinizi büyük ölçüde basitleştiren bir kütüphanedir.

Not: “Ethereum düğümü” ve “Ethereum istemcisi” birbirinin yerine kullanılan terimlerdir. Her iki durumda da, Ethereum ağındaki bir katılımcının çalıştırdığı yazılım ifade edilir. Bu yazılım blok verilerini okuyabilir, zincire yeni bloklar eklendiğinde güncellemeler alabilir, yeni işlemler yayımlayabilir ve daha fazlasını yapabilir. Teknik olarak istemci yazılımdır, düğüm ise yazılımı çalıştıran bilgisayardır.

Ethereum istemcileri; IPC(opens in a new tab), HTTP veya Websocket'ler tarafından erişilebilir olacak şekilde yapılandırılabilir, bu nedenle Web3.py'nin bu yapılandırmayı yansıtması gerekecek. Web3.py, bu bağlanma seçeneklerini sağlayıcı (provider) olarak ifade eder. Web3.py örneğini düğümünüze bağlamak için üç sağlayıcıdan birini seçmeniz gerekir.

Web3.py'nin uygulamanızı bir Ethereum düğümüne bağlamak için IPC'yi nasıl kullandığını gösteren bir diyagram

Ethereum düğümünü ve Web3.py'yi aynı protokol aracılığıyla iletişim kuracak şekilde yapılandırın, örneğin bu şemadaki IPC gibi.

Web3.py uygun şekilde yapılandırıldıktan sonra blok zinciri ile etkileşime başlayabilirsiniz. İşte karşılaşacaklarımızın bir ön izlemesi olarak birkaç Web3.py kullanım örneği:

1# read block data:
2w3.eth.get_block('latest')
3
4# send a transaction:
5w3.eth.send_transaction({'from': ..., 'to': ..., 'value': ...})
Kopyala

Kurulum

Bu örnekte, sadece bir Python yorumlayıcısı içinde çalışacağız. Herhangi bir dizin, dosya, sınıf veya fonksiyon oluşturmayacağız.

Not: Aşağıdaki örneklerde "$" ile başlayan komutların terminalde çalıştırılması amaçlanmıştır. ("$" işaretini yazmayınız, bu sadece satır başlangıcını belli etmek içindir.)

İlk olarak, deney yapabileceğiniz kullanıcı dostu bir ortam yaratmak için IPython(opens in a new tab) indirin. IPython, diğer özelliklerin yanı sıra tab tuşu ile tamamlama özelliği sunarak Web3.py içinde nelerin mümkün olduğunu görmeyi çok daha kolaylaştırır.

pip install ipython

Web3.py, web3 adı altında yayınlanmıştır. Şu şekilde kurun:

pip install web3

Bir şey daha: Daha sonra birkaç bağımlılık gerektiren bir blok zinciri simüle edeceğiz. Bunları şu şekilde yükleyebilirsiniz:

pip install 'web3[tester]'

Başlamaya hazırsınız!

Not: web3[tester] paketi Python 3.10.xx sürümüne kadar çalışır

Bir sanal alan (sandbox) başlatın

Terminalinizde ipython çalıştırarak yeni bir Python ortamı açın. Bu, python çalıştırmakla benzerdir ancak başka kullanışlı özellikleri de beraberinde getirir.

ipython

Bu, çalıştırmakta olduğunuz Python ve IPython sürümleri hakkında bazı bilgileri yazdıracaktır, ardından girdi bekleyen bir bilgi istemi görmelisiniz:

1In [1]:
Kopyala

Şu anda interaktif bir Python kabuğuna bakıyorsunuz. Aslında içinde oynamanız için bir sanal alandır. Buraya kadar geldiyseniz, Web3.py'yi içe aktarmanın zamanı geldi:

1In [1]: from web3 import Web3
Kopyala

Web3 modülü ile tanışın

Web3(opens in a new tab) modülü, Ethereum'a bir geçit olmanın yanı sıra birkaç kolaylık fonksiyonu sunar. Birkaçını keşfedelim.

Bir Ethereum uygulamasında, genellikle para birimlerini dönüştürmeniz gerekir. Web3 modülü bunun için birkaç yardımcı yöntem sağlar: wei_den(opens in a new tab) ve wei_ye(opens in a new tab).

Not: Bilgisayarlar, ondalık matematiği işlemede çok kötüdür. Bunu aşmak için geliştiriciler genellikle dolar tutarlarını sent olarak saklar. Örneğin fiyatı $5,99 olan bir ürün veritabanında 599 olarak saklanabilir.Ether bazındaki işlemler işlenirken benzer bir model kullanılır. Ancak, ether'da iki ondalık nokta yerine 18 ondalık nokta bulunur! Ether'ın en küçük birimine wei denir, bu nedenle işlem gönderirken belirtilen değer budur.

1 ether = 1000000000000000000 wei

1 wei = 0,000000000000000001 ether

Bazı değerleri wei'ye ve wei'den dönüştürmeyi deneyin. Ether ve wei arasındaki çok sayıda birim için isimler olduğunu(opens in a new tab) unutmayın. Bunlar arasında daha iyi bilinenlerden biri gwei'dir, çünkü genellikle işlem ücretleri bu şekilde gösterilir.

1In [2]: Web3.to_wei(1, 'ether')
2Out[2]: 1000000000000000000
3
4In [3]: Web3.from_wei(500000000, 'gwei')
5Out[3]: Decimal('0.5')
Kopyala

Web3 modülündeki diğer yardımcı program yöntemleri arasında veri formatı dönüştürücüleri (örneğin, toHex(opens in a new tab)), adres yardımcıları (örneğin, isAddress(opens in a new tab)) ve karma fonksiyonları (örneğin, keccak(opens in a new tab)) bulunur. Bunların çoğu serinin devamında ele alınacaktır. Kullanılabilir tüm yöntemleri ve özellikleri görüntülemek için Web3. yazıp noktadan sonra iki kez tab tuşuna basarak IPython'un otomatik tamamlama özelliğinden faydalanın.

Zincirle konuşun

Kolaylık sağlayan bu yöntemler güzel olsa da artık blokzincire geçelim. Sonraki adım, Web3.py'yi bir Ethereum düğümü ile iletişim kuracak şekilde yapılandırmaktır. Burada IPC, HTTP veya Websocket sağlayıcılarını kullanma seçeneğimiz bulunuyor.

Bu yolu kullanmayacağız ancak HTTP Sağlayıcısını kullanan eksiksiz bir iş akışı örneği şöyle görünebilir:

  • Bir Ethereum düğümü indirin, örneğin Geth(opens in a new tab).
  • Geth'i bir terminal penceresinde başlatın ve ağı senkronize etmesini bekleyin. Varsayılan HTTP portu 8545'tir, ancak bu değiştirilebilir.
  • Web3.py'ye localhost:8545 üzerindeki HTTP aracılığıyla düğüme bağlanmasını söyleyin. w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545'))
  • Düğüm ile etkileşime geçmek için w3 oluşumunu kullanın.

Bu, bunu yapmanın "gerçek" bir yolu olsa da, senkronizasyon işlemi saatler sürer ve yalnızca bir geliştirme ortamı istiyorsanız gereksizdir. Web3.py bu amaç için dördüncü bir sağlayıcı sunar: EthereumTesterProvider. Bu test sağlayıcısı, rahat izinlere ve oynamak için sahte para birimine sahip simüle edilmiş bir Ethereum düğümüne bağlanır.

Web3.py uygulamanızı simüle edilmiş bir Ethereum düğümüne bağlayan EthereumTesterProvider'ı gösteren bir diyagram

EthereumTesterProvider, simüle edilmiş bir düğüme bağlanır ve hızlı geliştirme ortamları için kullanışlıdır.

Bu simüle edilmiş düğüme eth-tester(opens in a new tab) denir; bu düğümü, pip install web3[tester] komutunun bir parçası olarak kurduk. Web3.py'yi bu test sağlayıcısını kullanacak şekilde yapılandırmak şu kadar basittir:

1In [4]: w3 = Web3(Web3.EthereumTesterProvider())
Kopyala

Artık zincirde sörf yapmaya hazırsınız! İnsanlar buna sörf yapmak demezler. Bunu az önce kafamdan uydurdum. Hadi hızlı bir tur atalım.

Hızlı tur

İlk önce önemli bir şeyi aradan çıkaralım, bir akıl sağlığı kontrolü:

1In [5]: w3.isConnected()
2Out[5]: True
Kopyala

Test sağlayıcısını kullandığımız için bu çok değerli bir test değildir ancak başarısız olursa, muhtemelen w3 değişkenini başlatırken yanlış bir şeyler yazmışsınızdır. İç parantezleri dahil ettiğinizi iki kez kontrol edin, yani Web3.EthereumTesterProvider() şeklinde olsun.

1. tur durağı: hesaplar

Kolaylık sağlamak için test sağlayıcısı bazı hesaplar oluşturdu ve bunları test ether'i ile önceden yükledi.

İlk olarak, bu hesapların bir listesini görelim:

1In [6]: w3.eth.accounts
2Out[6]: ['0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
3 '0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF',
4 '0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69', ...]
Kopyala

Bu komutu çalıştırırsanız, 0x ile başlayan on dizelik bir liste görmelisiniz. Her biri bir herkese açık adrestir ve bazı yönlerden çek hesabındaki hesap numarasına benzer. Bu adresi size ether göndermek isteyen birine verirsiniz.

Belirtildiği gibi, test sağlayıcısı bu hesapların her birine bir miktar test ether'ini önceden yüklemiştir. İlk hesapta ne kadar olduğunu öğrenelim:

1In [7]: w3.eth.get_balance(w3.eth.accounts[0])
2Out[7]: 1000000000000000000000000
Kopyala

Bir sürü sıfır var! Güle oynaya sahte bankaya doğru gitmeden önce para birimleriyle ilgili eski dersi hatırlayın. Ether değerleri, en küçük birim olan wei ile temsil edilir. Bunu ether'e çevirin:

1In [8]: w3.from_wei(1000000000000000000000000, 'ether')
2Out[8]: Decimal('1000000')
Kopyala

Bir milyon test ether'ı, yine de az buz para değil.

2. tur durağı: blok verisi

Simüle edilmiş blok zincirinin durumuna bir göz atalım:

1In [9]: w3.eth.get_block('latest')
2Out[9]: AttributeDict({
3 'number': 0,
4 'hash': HexBytes('0x9469878...'),
5 'parentHash': HexBytes('0x0000000...'),
6 ...
7 'transactions': []
8})
Kopyala

Bir blok hakkında birçok bilgi döndürülür, ancak burada dikkat edeceğimiz sadece birkaç şey var:

  • Test cihazı sağlayıcısını ne kadar süre önce yapılandırmış olursanız olun, blok numarası sıfırdır . Yaklaşık her 12 saniyede bir yeni bir blok oluşturan gerçek Ethereum ağının aksine, bu simülasyon, siz ona biraz iş verene kadar bekleyecektir.
  • Henüz hiçbir şey yapmadığımız için transactions da aynı nedenden dolayı boş bir listedir. Bu ilk blok, sadece zinciri başlatmak için kullanılan bir boş bloktur.
  • parentHash'in sadece birkaç tane boş bayt olduğuna dikkat edin. Bu, başlangıç bloğu (genesis block) olarak da bilinen, zincirdeki ilk blok olduğu anlamına gelir.

3. tur durağı: işlemler

Bekleyen bir işlem olana kadar sıfır blokta kalacağımız için ona bir işlem verelim. Bir hesaptan diğerine birkaç test ether'ı gönderin:

1In [10]: tx_hash = w3.eth.send_transaction({
2 'from': w3.eth.accounts[0],
3 'to': w3.eth.accounts[1],
4 'value': w3.to_wei(3, 'ether'),
5 'gas': 21000
6})
Kopyala

Bu noktada genellikle işleminizin yeni bir bloğa dahil edilmesi için birkaç saniye beklersiniz. Tam süreç hemen hemen şöyle işler:

  1. Bir işlem gönderin ve işlem hash değerini tutun. İşlemi içeren blok oluşturulup yayınlanıncaya kadar işlem "beklemede" kalır. tx_hash = w3.eth.send_transaction({ … })
  2. İşlemin bir bloğa dahil edilmesini bekleyin: w3.eth.wait_for_transaction_receipt(tx_hash)
  3. Uygulama mantığına devam edin. Başarılı işlemi görüntülemek için: w3.eth.get_transaction(tx_hash)

Simüle edilmiş ortamımız, işlemi anında yeni bir bloğa ekleyecektir, böylece işlemi hemen görebiliriz:

1In [11]: w3.eth.get_transaction(tx_hash)
2Out[11]: AttributeDict({
3 'hash': HexBytes('0x15e9fb95dc39...'),
4 'blockNumber': 1,
5 'transactionIndex': 0,
6 'from': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
7 'to': '0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF',
8 'value': 3000000000000000000,
9 ...
10})
Tümünü göster
Kopyala

Burada bazı tanıdık ayrıntılar göreceksiniz: from, to, ve value alanları, send_transaction çağrımızın girdileriyle eşleşmelidir. Diğer güven verici kısım, bu işlemin 1 numaralı blok içindeki ilk işlem ('transactionIndex': 0) olarak dahil edilmiş olmasıdır.

Ayrıca, ilgili iki hesabın bakiyelerini kontrol ederek bu işlemin başarısını kolayca doğrulayabiliriz. Üç ether, birinden diğerine geçmiş olmalıdır.

1In [12]: w3.eth.get_balance(w3.eth.accounts[0])
2Out[12]: 999996999979000000000000
3
4In [13]: w3.eth.get_balance(w3.eth.accounts[1])
5Out[13]: 1000003000000000000000000
Kopyala

İkincisi iyi gözüküyor! Bakiye, 1.000.000'dan 1.000.003 ether'a döndü. Peki ilk hesaba ne oldu? Üç ether'dan biraz daha fazlasını kaybetmiş görünüyor. Ne yazık ki, hayatta hiçbir şey bedava değildir ve Ethereum genel ağını kullanmak, eşlerinizi destekleyici rolleri için tazmin etmenizi gerektirir. İşlemi gönderen hesaptan küçük bir işlem ücreti kesildi - bu ücret, yakılan gaz miktarı (ETH transferi için 21000 birim gaz), ağ etkinliğine göre değişen bir taban ücret ile çarpılır ve işlemi bloğa ekleyen doğrulayıcıya giden bir bahşiş eklenerek hesaplanır.

Gaz hakkında daha fazla bilgi

Not: Genel ağda işlem ücretleri, ağ talebine ve bir işlemin ne kadar hızlı işlenmesini istediğinize göre değişir. Ücretlerin nasıl hesaplandığına dair bir belge görmek istiyorasanız, işlemlerin bir bloğa nasıl dahil edildiğine ilişkin önceki gönderime göz atabilirsiniz(opens in a new tab).

Ve derin bir nefes alın

Bir süredir bu işle uğraştığımız için şu anda biraz mola vermek iyi gelebilir. Derine dalmaya devam ediyoruz ve bu serinin ikinci bölümünde keşfe devam edeceğiz. Yakında ele alacağımız bazı kavramlar: gerçek bir düğüme bağlanma, akıllı sözleşmeler ve jetonlar. Yukarıdakilerle ilgili sorularınız mı var? Bana sorabilirsiniz! Geribildiriminiz konunun ilerleyişini etkileyecektir. Twitter(opens in a new tab) aracılığıyla isteklerinizi iletebilirsiniz.

Son düzenleme: @kaanmetu(opens in a new tab), 15 Ocak 2024

Bu rehber yararlı oldu mu?