Skip to content

Instantly share code, notes, and snippets.

@Orbifold
Created August 23, 2018 09:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Orbifold/78baacdd4d9d6e1f00bec8e7309675ff to your computer and use it in GitHub Desktop.
Save Orbifold/78baacdd4d9d6e1f00bec8e7309675ff to your computer and use it in GitHub Desktop.
Poor man's basic blockchain implementation to grasp the principles.
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()
class Chain:
"""
The basic blockchain.
"""
def __init__(self):
self.head = Block(0, "Genesis", "0")
self.tail = self.head
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
# {
# "from": "public key 1",
# "to": "public key 2",
# "value": 45
# }
class Node:
def __init__(self):
self._address = str(uuid.uuid4())
self._chain = Chain()
self._peers = []
self._transactions = []
def add_transaction(self, tx):
self._transactions.append(tx)
def add_peer(self,url):
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
blocks = json.loads(blocks)
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",
"to": self._address,
"amount": 1
}
)
self._chain.append(proof)
return self._chain.last()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment