Python dili ile basit Blokzincir uygulaması yazma

Ali Orhun Akkirman - May 17 '21 - - Dev Community

Bir süredir boş vakitlerimde blokzincir'e bakıyordum. Tabi ki birikim olarak "coin"'ler değil de biraz daha teknik konular. Bu kapsamda hem öğrenmek için hem de aktarabilmek için küçük bir blokzincir uygulaması yapmak istedim.

Herhangi bir algoritmanın en hızlı şekilde uygulanması için Python dilinin kullanılmasının çok hoş olduğunu düşünerek bu dille yapılan örnekleri inceledim ve olabildiğince basit olanı seçmeye çalıştım. Bu nedenle bu yazıyı büyük bir "coin" altyapısı olarak değil öğrenme olarak düşünmeniz gerekir.

Python ile blokzincir'e giriş

Python ile belki onlarca çeşit alternatif olmasına rağmen belgelendirmede şifreleme algoritmaları için hashlib kütüphanesi kullanılmış. Bloklarımız ise json formatında tutulması için yine bu kütüphane kullanılıyor. Çeşitli yerlerde de time kütüphanesiyle zaman ile ilgili işlemler yapılacaktır.

Blokzincir sınıfı oluşturma

En temelinde basit bir sınıf oluşturmamız gerekir. Aşağıdaki gibi bir sınıf oluşturalım. Bu sınıf ilk oluşturulurken içinde zincir ve bekleyen işlemler diye 2 dizi oluşmakta. Ve tabi ki temel bir yeni blok eklenmekte.

class Blockzincir(object):
    def __init__(self):
        self.zincir = []
        self.bekleyen_islemler = []
        self.yeni_blok(onceki_saglama="Herhangi bir içerik", delil=100)
Enter fullscreen mode Exit fullscreen mode

Yeni blok ekleme fonksiyonu

Yeni adımda sınıfta giriş olarak kullandığımız yeni_blok() fonksiyonunu oluşturarak başlıyoruz. Yeni blok oluşturulurken bekleyen işlemleri görüyor ve bu işlemleri blok içinde ekliyor. (işlemler adı altında) Ve tabi ki bunun bir zaman damgası ve bir önceki sağlama fonksiyonun kontrolü sağlanıyor.

    def yeni_blok(self, delil, onceki_saglama=None):
        blok = {
            'index': len(self.zincir) + 1,
            'timestamp': time(),
            'transactions': self.bekleyen_islemler,
            'proof': delil,
            'previous_hash': onceki_saglama or self.saglama(self.zincir[-1]),
        }
        self.bekleyen_islemler = []
        self.zincir.append(blok)

        return blok
Enter fullscreen mode Exit fullscreen mode

Son blok'u çekme fonksiyonu

Yeni bir işlem fonksiyonunda kullanılacak son_blok() fonksiyonunu zincir dizisindeki son blok json'unu almak için hazırlıyoruz.

    @property
    def son_blok(self):
        return self.zincir[-1]
Enter fullscreen mode Exit fullscreen mode

Yeni bir işlem fonksiyonu

Şimdi gönderici, alıcı ve gönderilecek büyüklüğün girildiği bir yeni işlem fonksiyonu oluşturuyoruz.

    def yeni_islem(self, gonderici, alici, miktar):
        islem = {
            'gönderici': gonderici,
            'alıcı': alici,
            'miktar': miktar
        }
        self.bekleyen_islemler.append(islem)
        return self.son_blok['index'] + 1
Enter fullscreen mode Exit fullscreen mode

Görüldüğü gibi aslında işlem fonksiyonu işlemi sadece bekleyen işlemlere eklemekte.

Sağlama (hash) fonksiyonu

Sağlama, yani hash kısmı tüm uygulamamızın en önemli kısımlarından birisi. Burada çok basit şekilde sha256'lı bir şifreleme yöntemi seçildi. Sağlama fonksiyonu bir blok değeri girdisini alıp sağlama hex değeri çıktısı vermekte. Ve bu fonksiyonu, yeni blok ekleme fonksiyonu içinde zincirdeki son blok değerine göre sağlama yapılması için kullanılıyor.

    def saglama(self, blok):
        string_object = json.dumps(blok, sort_keys=True)
        blok_string = string_object.encode()

        raw_saglama = hashlib.sha256(blok_string)
        hex_saglama = raw_saglama.hexdigest()

        return hex_saglama
Enter fullscreen mode Exit fullscreen mode

Ve Uygulama

Ve şimdi uygulama yaparsak örneğin her bir blok içinde 3 işlem yaptığımızı düşünelim ve her 3 işlemden sonra bir blok oluşturup zincire ekliyoruz. Daha sonradan bu blok içindeki tüm işlemlerin sağlaması yapılıp bir sonraki zincir bloğuna eklenmiş oluyor. Ayrıca örnekteki yeni blok oluştururken delil (proof) oluşturmak da konuya bir açı daha katmakta. Bunu yapmadan da geliştirilen basit algoritmalar bulunmakta.

blokzincir = Blockzincir()
t1 = blokzincir.yeni_islem("Ali", "Veli", '5 bloklira')
t2 = blokzincir.yeni_islem("Zeki", "Deli", '1 bloklira')
t3 = blokzincir.yeni_islem("Deli", "Ali", '3 bloklira')
blokzincir.yeni_blok(12345)

t4 = blokzincir.yeni_islem("Ali", "Deli", '0.5 bloklira')
t5 = blokzincir.yeni_islem("Veli", "Zeki", '3 bloklira')
t6 = blokzincir.yeni_islem("Zeki", "Deli", '1 bloklira')
blokzincir.yeni_blok(6789)

jsonStr = json.dumps(blokzincir.zincir)
print(jsonStr)

## blockid sağlaması kontrolü
#print(blokzincir.saglama(blokzincir.zincir[0]))
Enter fullscreen mode Exit fullscreen mode

Çıktı

Çıktı aşağıdaki gibi olması gerekmekte

[
  {
    "index": 1,
    "timestamp": 1621265942.8971791,
    "transactions": [],
    "proof": 100,
    "previous_hash": "Herhangi bir içerik olsun"
  },
  {
    "index": 2,
    "timestamp": 1621265942.8971846,
    "transactions": [
      {
        "gönderici": "Ali",
        "alıcı": "Veli",
        "miktar": "5 bloklira"
      },
      {
        "gönderici": "Zeki",
        "alıcı": "Deli",
        "miktar": "1 bloklira"
      },
      {
        "gönderici": "Deli",
        "alıcı": "Ali",
        "miktar": "3 bloklira"
      }
    ],
    "proof": 12345,
    "previous_hash": "f9a5874b5b3415ea7a9ab323a24de7104cc076c1e34ef24e386235feb2b8d67d"
  },
  {
    "index": 3,
    "timestamp": 1621265942.8972323,
    "transactions": [
      {
        "gönderici": "Ali",
        "alıcı": "Deli",
        "miktar": "0.5 bloklira"
      },
      {
        "gönderici": "Veli",
        "alıcı": "Zeki",
        "miktar": "3 bloklira"
      },
      {
        "gönderici": "Zeki",
        "alıcı": "Deli",
        "miktar": "1 bloklira"
      }
    ],
    "proof": 6789,
    "previous_hash": "6e92837e2be20a929e85a976eb93222ada2050b273324fffa5a77081b6f4d78e"
  }
]
Enter fullscreen mode Exit fullscreen mode

Kaynak

https://medium.com/coinmonks/python-tutorial-build-a-blockchain-713c706f6531

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .