Budujemy własny Blockchain - cz. 1 Pierwszy blok

Na wstępie pragnę zaznaczyć że w tej mini serii, wspólnie przetestujemy nowe podejście, polegające na nauce płynącej z czytania samego kodu. Nie będziemy omawiać wszystkiego krok po kroku, lecz skupimy się głównie na idei stworzenia w pełni działającego systemu od podstaw.


W części pierwszej skoncentrujemy się na stworzeniu pojedynczego bloku którego kod przedstawiam poniżej.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
from datetime import datetime
from hashlib import sha256


class Block(object):
"""It is a conceptual representation of the class of a simple block
fragment that makes up the entire blockchain.

:param index: int
:param transactions: array
:param timestamp: datetime
:param previous_hash: str
:param nonce: int, optional
"""

__name__ = "Mini block class"
__author__ = "Kamil Mirończuk"
__license__ = "GNU General Public License v3.0"
__version__ = "1.0"
__status__ = "production"

def __init__(
self, index, transactions, timestamp, previous_hash, nonce=0
):
"""Constructor method"""
super().__init__()
self.__index = index
self.__transactions = transactions
self.__timestamp = datetime.timestamp(timestamp)
self.__previous_hash = previous_hash
self.__nonce = nonce
self.hash = "0"*64

def __call__(self) -> str:
"""Return block main information.

:return: the index and stored transactions data
:rtype: str
"""
return "Block nr {} -> data {}".format(
self.__index, self.__transactions
)

@property
def compute_hash(self) -> str:
"""Generate actual block hash.

:return: block hash
:rtype: str
"""
block_string: str = json.dumps(
dict(
filter(
lambda elem: elem[0] != "_Block__hash",
self.__dict__.items(),
)
),
sort_keys=True,
)
return sha256(block_string.encode()).hexdigest()

@property
def hash(self) -> str:
"""Get actual block hash.

:return: block hash
:rtype: str
"""
return self.__hash

@hash.setter
def hash(self, value):
"""Set block hash.

:raises TypeError: Hash type is not valid
:raises ValueError: Hash character number is not valid
:return: block hash
:rtype: str
"""
if type(value) != str:
raise TypeError("Hash must be a string.")
if len(value) != 64:
raise ValueError("Hash must have 64 characters.")
self.__hash: str = value

@property
def index(self) -> int:
"""Get actual block index.

:return: block index
:rtype: int
"""
return self.__index

@property
def previous_hash(self) -> str:
"""Get last block hash.

:return: last block hash
:rtype: str
"""
return self.__previous_hash

@property
def transactions(self) -> str:
"""Get all stored transatcions

:return: all transactions
:rtype: str
"""
return self.__transactions

Sercem samej klasy jest metoda __init__(), która tworzy daną instancję. Przyjmuje ona takie dane jak:

  • aktualny indeks aktualnego bloku,
  • transakcje które chcemy w nim zapisać,
  • aktualną datę,
  • hash poprzedniej transakcji,
  • wartość nonce która przyda nam się podczas wydobywania bloku, celem potwierdzenia wykonanej pracy.

Dodatkowo klasa z ciekawszych czynności umożliwia nam wygenerowania aktualnego swojego hash-u za pomocą metody compute_hash, która pobierze wszystkie pola prócz oczywiście hash-a samego bloku i zwróci je następnie jako sumę kontrolną danego bloku. 


W następnej części, zajmiemy się już stworzeniem prawdziwej platformy która prócz zachowywania danych, będzie potrafiła wykonać pracę, celem udowodnienia że sam stworzony blokchain jest w pełni integralny i nikt przy nim nie majstrował :)

Kamil Mirończuk

I kiedy czegoś gorąco pragniesz, to cały wszechświat sprzyja potajemnie twojemu pragnieniu
~Paulo Coelho

Komentarze

Zostaw komentarz

Twój adres mailowy NIE zostanie opublikowany. W razie otrzymania zapytania, otrzymasz na niego odpowiedź.
Wymagane pola są oznaczone jako *