# Poor man’s blockchain

Gist

The blockchain industry is in full swing and the best way to understand how it functions is by creating it yourself. Simplistic examples can be revealing. Below you can find my own 5-cent implementation which helped me grasp the concepts.

A chain is a glorified linked-list with blocks keeping a hash of the previous block. As such one cannot fiddle with the content without cascading the effect down the list. Here a block definition:

import hashlib as hasher
import datetime as date
import requests
import time
import math
import uuid
import random

class Block:
"""
The basic unit of a blockchain.

"""

def __init__(self, index, data, previous_hash):
if index is None or not isinstance(index, int) or index < 0:
raise Exception("Given index is not acceptable.")

self.index = index
self.timestamp = date.datetime.now()
self.data = data
self.previous_hash = previous_hash
sha = hasher.sha256()
sha.update(str(self.index).encode('utf-8') + str(self.timestamp).encode(
'utf-8') + str(self.data).encode('utf-8') + str(self.previous_hash).encode('utf-8'))
self.hash = sha.hexdigest()


You don’t need to encode the whole package in the hash and a good hash is an art on its own.
The chain is really just linking blocks together:


class Chain:
"""
The basic blockchain.

"""

def __init__(self):
self._blocks = [self.tail]

def __iter__(self):
return self._blocks.__iter__()

def append(self, data: str):
self._blocks.append(Block(self.tail.index + 1,  data, self.tail.hash))
self.tail = self._blocks[-1]
return self.tail

def __str__(self):
return f"Chain of length {len(self._blocks)}"

def serialize(self):
coll = []
for block in self._blocks:
coll.append({
"index": str(block.index),
"timestamp": str(block.timestamp),
"data": str(block.data),
"hash": block.hash
})
return coll

def last(self):
return self.tail


A node is part of a peer network where each attempts to solve a puzzle. The type and complexity here is a whole topic related to attacks, spamming and balance between protecting and challenge. Let’s say that the puzzle should be fairly difficult and that whoever finds the solution is being rewarded. Note that if you are only after a blockchain storage solution you don’t need to solve any puzzle, the chain’s linked hashing is all you need. Once a peer is rewarded the other peers are notified and get an update. The puzzle is difficult to solve and easy to proof, hence the reason why cryptographic algorithms are perfect. It’s easy to show that a solution is right but it’s tough to find it.


class Node:
def __init__(self):

self._chain = Chain()
self._peers = []
self._transactions = []

self._transactions.append(tx)

self._peers.append(url)

def get_peer_chains(self):
coll = []
for node_url in self._peers:
try:
blocks = requests.get(f"{node_url}/blocks").content
coll.append(blocks)
except Exception:
pass
return coll

def get_blocks(self):
return self._chain.serialize()

def get_transactions(self):
return self._transactions

def consensus(self):
# accept the longest one
other_chains = self.get_peer_chains()
longest_chain = self._chain
for chain in other_chains:
if len(longest_chain) < len(chain):
longest_chain = chain

self._chain = longest_chain

def proof_of_work(self,last_proof):
#  compute something intense and return your supposedly good answer to the puzzle
time.sleep(2)
return random.randint(1, 1e12)

def mine(self):
last_block = self._chain.last()
last_proof = last_block.data
proof = self.proof_of_work(last_proof)

self._transactions.append(
{
"from": "network",