Blockchain: leren door er eentje te maken

Er is veel te doen over Blockchain. Ik hoor al lange tijd dat Blockchain de wereld gaat veranderen. Dat banken het nauwlettend in de gaten houden en dat overheden al aan het bedenken zijn hoe ze het kunnen beheersen. Blockchain-goeroe's komen als paddestoelen uit de grond. Er zijn vele artikelen en YouTube video's aan gewijd, maar toch blijft het vrij abstract allemaal.

Aan definities geen gebrek. Zo vond ik bijvoorbeeld "a digital ledger in which transactions made in bitcoin or another cryptocurrency are recorded chronologically and publicly.". Het is dus een digitaal grootboek waarin financiele transacties zowel chronologisch als openbaar worden geregistreerd. Op Wikipedia wordt gesproken over een gedistribueerde database gehard tegen vervalsing. Goed en wel allemaal, maar misschien is de beste manier om Blockchain te doorgronden wel de meest technische: gewoon eentje bouwen. Dankzij blockgeeks kwam ik erachter dat een Blockchain in veel verschillende talen ontwikkeld kan worden met minimale code. Ook met Python, de taal die uitblinkt in leesbaarheid en eenvoud. Hieronder de uitwerking. En voor de niet-programmeurs: haak nog niet af, want volgens mij is het goed te volgen.

Ik begin met het importeren (import) van modules hashlib en datetime. Hierin zijn niet-basis Python functies opgenomen die ik nodig heb voor het programma. Vervolgens maak ik een klasse (class) Block aan. Binnen Python en andere object-georienteerde talen is het gebruikelijk om klassen aan te maken. Alle objecten (in dit geval zijn het de Blocks van de Blockchain) bevatten een index, datum, omschrijving, vorige hash en hash. Binnen de klasse Block zijn twee functies gedefinieerd: def __init__ en def hash_block. De eerste functie roept de parameters aan en bij de tweede wordt met behulp van de hash module een "hash" aangemaakt: de unieke sleutel van dit Block die is gebaseerd op zijn index, datum, data en vorige hash.

import hashlib as hasher import datetime as date class Block: def __init__(self, index, datum, omschrijving, vorige_hash): self.index = index self.datum = datum self.omschrijving = omschrijving self.vorige_hash = vorige_hash self.hash = self.hash_block() def hash_block(self): sha = hasher.sha256() sha.update(str(self.index).encode('utf-8')\ + str(self.datum).encode('utf-8')\ + str(self.omschrijving).encode('utf-8')\ + str(self.vorige_hash).encode('utf-8')) return sha.hexdigest()

Hieronder maak ik een eerste Block object aan door de verplichte parameters index, datum, data en vorige hash in te vullen. De hash van dit Block wordt dus automatisch gegenereerd op basis van de overige parameters.

block_1 = Block(1, '2018-01-01', 'eerste block', 0)

Als ik het eerste Block object print op het scherm zien we het volgende:


Als ik de omschrijving van block_1 verander in 'tweede block' dan verandert de hash. Hieruit wordt meteen duidelijk dat indien iemand een specifiek Block aanpast dan hebben alle opvolgende Blocks een incorrecte hash en is de keten verbroken.


Aangezien elke chain een start moet hebben maak ik een genesis_block functie aan met index 0 en vorige hash 0.

def genesis_block(): return Block(0, date.datetime.now(), "Genesis Block", "0")

De functie volgend_block maakt een Block object aan waarbij de index steeds met 1 wordt verhoogd en het huidige tijdstip als datum heeft.

def volgend_block(last_block): index = vorig_block.index + 1 tijdstip = date.datetime.now() omschrijving = "Nieuw Block met index " + str(index) hash = vorig_block.hash return Block(index, tijdstip, omschrijving, hash)

Vervolgens maak ik een "for loop" waarbij 5 Blocks worden gegenereerd en print ik de Blocks op het scherm. De vorige hash is dus steeds de hash van het voorgaande Block.

blockchain = [genesis_block()] vorig_block = blockchain[0] for i in range(5): block_toevoeging = volgend_block(vorig_block) blockchain.append(block_toevoeging) vorig_block = block_toevoeging attrs = vars(block_toevoeging) print('\n'.join("%s: %s" % item for item in attrs.items()))

De Blocks zijn hieronder te zien. Elk Block begint met een index en bevat de hash van het vorige Block die mede de hash van het huidige block bepaalt.


Tot zover mijn eerste echte Blockchain. Ik heb er een hoop van geleerd hoewel ik bijvoorbeeld het mining aspect achterwege heb gelaten. Ook zien we weer de veelzijdigheid van Python. Ik hoop dat je ook wat wijzer bent geworden van zowel Blockchain als Python en dat als iemand het volgende keer over een "immutable chain" heeft je gelijk weet wat ie bedoelt. Mischien zelfs beter dan die persoon zelf.

Hieronder volgt de complete code.

Met vriendelijke groet,

Robin Bakker

import hashlib as hasher import datetime as date class Block: def __init__(self, index, datum, omschrijving, vorige_hash): self.index = index self.datum = datum self.omschrijving = omschrijving self.vorige_hash = vorige_hash self.hash = self.hash_block() def hash_block(self): sha = hasher.sha256() sha.update(str(self.index).encode('utf-8')\ + str(self.datum).encode('utf-8')\ + str(self.omschrijving).encode('utf-8')\ + str(self.vorige_hash).encode('utf-8')) return sha.hexdigest() def genesis_block(): return Block(0, date.datetime.now(), "Genesis Block", "0") def volgend_block(last_block): index = vorig_block.index + 1 tijdstip = date.datetime.now() omschrijving = "Nieuw Block met index " + str(index) hash = vorig_block.hash return Block(index, tijdstip, omschrijving, hash) blockchain = [genesis_block()] vorig_block = blockchain[0] for i in range(5): block_toevoeging = volgend_block(vorig_block) blockchain.append(block_toevoeging) vorig_block = block_toevoeging attrs = vars(block_toevoeging) print('\n'.join("%s: %s" % item for item in attrs.items()))