# Blockchain Explained in 7 Simple Functions

Posted by Shanaka DeSoysa on Sun 03 March 2019

# Blockchain Explained in 7 Simple Functions¶

Practical hands-on guide to implement your own blockchain with 7 simple Python functions.

## Hashing Function¶

At the heart of the blockchain is the hashing function. Without encryption, the blockchain will be easily manipulable and transactions will be able to be fraudulently inserted. Here we're using a simple MD5 hashing algorithm. If you're interested in what's actually being used in bitcoin, read here.

In [0]:
import hashlib
import json

def hash_function(k):
"""Hashes our transaction."""
if type(k) is not str:
k = json.dumps(k, sort_keys=True)

return hashlib.sha256(k).hexdigest()

In [2]:
hash_function('www.myENDVR.com')

Out[2]:
'b26fe188c8c174c752aebea4e4fc42afe2b2e9ce6c6c94c5351bdaf76e8437e7'

## State Management¶

The ‘state’ is the record of who owns what. For example, myENDVR Inc have 100 coins and give 5 to John Smith, then the state will be the value of the dictionary below.

{‘transaction’: {‘myENDVR’: 95, ‘John Smith’: 5}}

In [0]:
def update_state(transaction, state):
state = state.copy()

for key in transaction:
if key in state.keys():
state[key] += transaction[key]
else:
state[key] = transaction[key]

return state


## Transaction Validation¶

The important thing to note is that overdrafts cannot exist. If there are only 10 coins in existence, then I cannot give 11 coins to someone. The below function verifies that the transaction we attempt to make is indeed valid. Also, a transaction must balance. I cannot give 5 coins and have the recipient receive 4 coins, since that would allow the destruction and creation of coins.

In [0]:
def valid_transaction(transaction, state):
"""A valid transaction must sum to 0."""
if sum(transaction.values()) is not 0:
return False

for key in transaction.keys():
if key in state.keys():
account_balance = state[key]
else:
account_balance = 0

if account_balance + transaction[key] < 0:
return False

return True


## Make Block¶

Now, we can make our block. The information from the previous block is read, and used to link it to the new block. This, too, is central to the idea of blockchain. Seemingly valid transactions can be attempted to fraudulently be inserted into the blockchain, but decrypting all the previous blocks is computationally (nearly) impossible, which preserves the integrity of the blockchain.

In [0]:
def make_block(transactions, chain):
"""Make a block to go into the chain."""
parent_hash = chain[-1]['hash']
block_number = chain[-1]['contents']['block_number'] + 1

block_contents = {
'block_number': block_number,
'parent_hash': parent_hash,
'transaction_count': block_number + 1,
'transaction': transactions
}

return {'hash': hash_function(block_contents), 'contents': block_contents}


## Check Block Hash¶

Below is a small helper function to check the hash of the previous block:

In [0]:
def check_block_hash(block):
expected_hash = hash_function(block['contents'])

if block['hash'] is not expected_hash:
raise

return


## Block Validity¶

Once we have assembled everything together, its time to create our block. We will now update the blockchain.

In [0]:
def check_block_validity(block, parent, state):
parent_number = parent['contents']['block_number']
parent_hash = parent['hash']
block_number = block['contents']['block_number']

for transaction in block['contents']['transaction']:
if valid_transaction(transaction, state):
state = update_state(transaction, state)
else:
raise

check_block_hash(block)  # Check hash integrity

if block_number is not parent_number + 1:
raise

if block['contents']['parent_hash'] is not parent_hash:
raise


## Check Blockchain¶

Before we are finished, the chain must be verified:

In [0]:
def check_chain(chain):
"""Check the chain is valid."""
if type(chain) is str:
try:
assert (type(chain) == list)
except ValueError:
# String passed in was not valid JSON
return False
elif type(chain) is not list:
return False

state = {}

for transaction in chain[0]['contents']['transaction']:
state = update_state(transaction, state)

check_block_hash(chain[0])
parent = chain[0]

for block in chain[1:]:
state = check_block_validity(block, parent, state)
parent = block

return state


Finally, need a transaction function, which hangs all of the above together:

In [0]:
def add_transaction_to_chain(transaction, state, chain):
if valid_transaction(transaction, state):
state = update_state(transaction, state)
else:
raise Exception('Invalid transaction.')

my_block = make_block(state, chain)
chain.append(my_block)

for transaction in chain:
check_chain(transaction)

return state, chain


## Example¶

So, now we have our 7 functions. How do we interact with it? Well, first we need to start our chain with a Genesis Block. This is the inception of our new coin (or stock inventory, etc).

For the purposes of this article, I will say that I, Tom, will start off with 10 coins. Let's say we start off with 100 coins for myENDVR Inc.

In [0]:
genesis_block = {
'hash': hash_function({
'block_number': 0,
'parent_hash': None,
'transaction_count': 1,
'transaction': [{'myENDVR': 100}]
}),
'contents': {
'block_number': 0,
'parent_hash': None,
'transaction_count': 1,
'transaction': [{'myENDVR': 100}]
},
}

block_chain = [genesis_block]
chain_state = {'myENDVR': 100}


Now, look what happens when myENDVR Inc give some coins to user John Smith:

In [0]:
chain_state, block_chain = add_transaction_to_chain(transaction={'myENDVR': -5, 'John Smith': 5}, state=chain_state, chain=block_chain)

In [12]:
chain_state

Out[12]:
{'John Smith': 5, 'myENDVR': 95}
In [13]:
block_chain

Out[13]:
[{'contents': {'block_number': 0,
'parent_hash': None,
'transaction': [{'myENDVR': 100}],
'transaction_count': 1},
'hash': '4609f57859df784026c25fc42a9d0e40ebaa2a5b0e7c03b45c2c3d11da01829e'}]