Python Geliştiricileri için Ethereum'a Giriş, Bölüm 1
Ş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.
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.
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.
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')34# 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.
İ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 Web3Kopyala
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).
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]: 100000000000000000034In [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.
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]: TrueKopyala
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.accounts2Out[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]: 1000000000000000000000000Kopyala
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': 210006})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:
- 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({ … })
- İşlemin bir bloğa dahil edilmesini bekleyin:
w3.eth.wait_for_transaction_receipt(tx_hash)
- 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österKopyala
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]: 99999699997900000000000034In [13]: w3.eth.get_balance(w3.eth.accounts[1])5Out[13]: 1000003000000000000000000Kopyala
İ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
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: @pettinarip(opens in a new tab), 15 Ocak 2024