Created
March 7, 2019 15:24
-
-
Save MrCrambo/64984e50de2eb526c77aa563083ddbe1 to your computer and use it in GitHub Desktop.
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
import datetime | |
import hashlib | |
import time | |
class Message: | |
def __init__(self, data): | |
self.hash = None | |
self.prev_hash = None | |
self.timestamp = time.time() | |
self.size = len(data.encode('utf-8')) | |
self.data = data | |
self.payload_hash = self._hash_payload() | |
def _hash_payload(self): | |
return hashlib.sha256(bytearray(str(self.timestamp) + str(self.data), "utf-8")).hexdigest() | |
def _hash_message(self): | |
return hashlib.sha256(bytearray(str(self.prev_hash) + self.payload_hash, "utf-8")).hexdigest() | |
def link(self, message): | |
self.prev_hash = message.hash | |
def seal(self): | |
self.hash = self._hash_message() | |
def validate(self): | |
if self.payload_hash != self._hash_payload(): | |
raise InvalidMessage("Invalid payload hash in message: " + str(self)) | |
if self.hash != self._hash_message(): | |
raise InvalidMessage("Invalid message hash in message: " + str(self)) | |
class Block: | |
def __init__(self, *args): | |
self.messages = [] | |
self.timestamp = None | |
self.prev_hash = None | |
self.hash = None | |
if args: | |
for arg in args: | |
self.add_message(arg) | |
def _hash_block(self): | |
return hashlib.sha256(bytearray(str(self.prev_hash) + str(self.timestamp) + self.messages[-1].hash, "utf-8")).hexdigest() | |
def add_message(self, message): | |
if len(self.messages) > 0: | |
message.link(self.messages[-1]) | |
message.seal() | |
message.validate() | |
self.messages.append(message) | |
def link(self, block): | |
self.prev_hash = block.hash | |
def seal(self): | |
self.timestamp = time.time() | |
self.hash = self._hash_block() | |
def validate(self): | |
for i, msg in enumerate(self.messages): | |
try: | |
msg.validate() | |
if i > 0 and msg.prev_hash != self.messages[i-1].hash: | |
raise InvalidBlock("Invalid block: Message #{} has invalid message link in block: {}".format(i, str(self))) | |
except InvalidMessage as ex: | |
raise InvalidBlock("Invalid block: Message #{} failed validation: {}. In block: {}".format(i, str(ex), str(self))) | |
class SimpleChain: | |
def __init__(self): | |
self.chain = [] | |
def add_block(self, block): | |
if len(self.chain) > 0: | |
block.prev_hash = self.chain[-1].hash | |
block.seal() | |
block.validate() | |
self.chain.append(block) | |
def validate(self): | |
for i, block in enumerate(self.chain): | |
try: | |
block.validate() | |
except InvalidBlock as exc: | |
raise InvalidBlockchain("Invalid blockchain at block number {} caused by: {}".format(i, str(exc))) | |
return True |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment