Created
February 28, 2018 16:45
-
-
Save roychowdhuryrohit-dev/1fee318dfedb417b64c8c8287b945fa1 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 | |
import time | |
from json import dumps | |
# to define each blocks | |
class Block: | |
def __init__(self, data, prevHash=None): | |
self.data = data | |
# timestamp of block creation | |
self.time = time.time() | |
# to help in guessing the target during mining | |
self.nonce = 0 | |
# hash key of previous block | |
self.prevHash = prevHash | |
self.hash = self.calc_hash() | |
def calc_hash(self): | |
hash_object = None | |
input = self.data+str(self.time)+str(self.nonce) | |
if self.prevHash is not None: | |
input += self.prevHash | |
# to produce 256 bit hex digest using SHA algorithm | |
hash_object = sha256(input.encode('utf-8')) | |
digest = hash_object.hexdigest() | |
return digest | |
# to mine current block as proof-of-work | |
def mine_block(self): | |
# to mine until target is reached | |
while self.hash[:BlockChain.mining_difficulty] != BlockChain.target: | |
self.nonce += 1 | |
self.hash = self.calc_hash() | |
print("Block mined : {0} Nonce : {1}".format(self.hash, self.nonce)) | |
# to define block chain | |
class BlockChain: | |
# mining difficulty. For Bitcoin it is around 3,007,383,866,430 | |
mining_difficulty = 5 | |
target = "0"*mining_difficulty | |
def __init__(self, data): | |
self.block_chain = list() | |
# genesis block | |
gen_block = Block(data) | |
self.block_chain.append(gen_block) | |
# to check if the blockchain is valid | |
def checkChainValid(self): | |
i = 1 | |
while i < len(self.block_chain): | |
prev_block = self.block_chain[i-1] | |
cur_block = self.block_chain[i] | |
if cur_block.hash != cur_block.calc_hash(): | |
print("Current hash mismatch !") | |
return False | |
elif cur_block.prevHash != prev_block.hash: | |
print("Previous hash mismatch !") | |
return False | |
elif cur_block.hash[:BlockChain.mining_difficulty] != BlockChain.target: | |
print("Current block {0} is not mined !".format( | |
cur_block.hash)) | |
return False | |
i += 1 | |
return True | |
def getBlockChain(self): | |
return self.block_chain | |
# driver/test code | |
block_chain_obj = BlockChain("Genesis block") | |
block_chain = block_chain_obj.getBlockChain() | |
print("Mining block #0") | |
block_chain[0].mine_block() | |
block_chain.append(Block("Hello world", block_chain[0].hash)) | |
print("Mining block #1") | |
# block_chain[1].mine_block() | |
block_chain.append(Block("I am a block", block_chain[1].hash)) | |
print("Mining block #2") | |
block_chain[2].mine_block() | |
if block_chain_obj.checkChainValid(): | |
# produce json dump of valid blockchain | |
print(dumps([block.__dict__ for block in block_chain], | |
indent=4, sort_keys=True)) | |
else: | |
print("BlockChain is invalid !") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment