Skip to content

Instantly share code, notes, and snippets.

@MrCrambo
Created March 7, 2019 15:24
Show Gist options
  • Save MrCrambo/64984e50de2eb526c77aa563083ddbe1 to your computer and use it in GitHub Desktop.
Save MrCrambo/64984e50de2eb526c77aa563083ddbe1 to your computer and use it in GitHub Desktop.
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