Created
April 22, 2021 02:40
-
-
Save frodo821/6d827d6cba61bac0b1e006eca9ae3b22 to your computer and use it in GitHub Desktop.
A minimal test implementation of blockchain (proof of works). p2p based protocols are not implemented.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from hashlib import sha256 | |
from datetime import datetime | |
from json import dumps | |
class Block: | |
def __init__(self, nonce, data, prevHash=None, difficulty=20): | |
self.nonce = nonce | |
self.data = data | |
self.timestamp = datetime.now().timestamp() | |
self.prevHash = prevHash | |
self.difficulty = difficulty | |
def toJSON(self): | |
return dumps(self.toDict()) | |
def toDict(self): | |
return { | |
"nonce": self.nonce, | |
"timestamp": self.timestamp, | |
"data": self.data, | |
"prev": self.prevHash, | |
"difficulty": self.difficulty | |
} | |
def toJSONData(self): | |
return dumps(self.toDict()) | |
def toDictData(self): | |
return { | |
"nonce": self.nonce, | |
"data": self.data, | |
"prev": self.prevHash, | |
"difficulty": self.difficulty | |
} | |
def validate(self): | |
return int(self.hash, 16) < (1 << (256 - self.difficulty)) | |
@property | |
def hash(self): | |
return sha256(self.toJSONData().encode('utf-8')).hexdigest() | |
class Chain: | |
def __init__(self): | |
self.blocks = {} | |
def get_head_block_hash(self): | |
non_scanned = [*self.blocks] | |
head = None | |
head_len = -1 | |
while non_scanned: | |
current_head = non_scanned.pop() | |
current_head_len = 0 | |
current = current_head | |
while True: | |
current_head_len += 1 | |
prev = self.blocks[current].prevHash | |
if prev is not None: | |
current = non_scanned.pop(non_scanned.index(prev)) | |
else: | |
break | |
if current_head_len > head_len: | |
head = current_head | |
head_len = current_head_len | |
return head | |
def add_block(self, block): | |
if not block.validate(): | |
return False | |
self.blocks[block.hash] = block | |
return True | |
def mine(self, data): | |
head = self.get_head_block_hash() | |
nonce = -1 | |
while True: | |
nonce += 1 | |
block = Block(nonce, data, head) | |
if self.add_block(block): | |
return block |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment