def test_chain_constructor(self): test_chain = Chain() assert len(test_chain.chain) == 1 assert type(test_chain.get_latest_block()) == Block assert test_chain.get_latest_block().data == 'first Block' assert test_chain.get_latest_block().index == 0
def test_all_blocks_are_valid(self): test_chain = Chain() test_chain.add_new_block('Block one') test_chain.add_new_block('Block two') valid = test_chain.all_blocks_valid() assert valid is True
def test_changed_data_detected(self): test_chain = Chain() test_chain.add_new_block('Block one') test_chain.add_new_block('Block two') test_chain.chain[1].data = 'Block 42' valid = test_chain.all_blocks_valid() assert valid is False
def test_changed_time_stamp_detected(self): test_chain = Chain() test_chain.add_new_block('Block one') test_chain.add_new_block('Block two') test_chain.chain[1].time_stamp = '2017-08-14T06:16:23.225877' valid = test_chain.all_blocks_valid() assert valid is False
def test_changed_hash_detected(self): test_chain = Chain() test_chain.add_new_block('Block one') test_chain.add_new_block('Block two') test_chain.chain[1].hash = '76af6354wronghash' valid = test_chain.all_blocks_valid() assert valid is False
def test_changed_index_or_deleted_block_detected(self): test_chain = Chain() test_chain.add_new_block('Block one') test_chain.add_new_block('Block two') del test_chain.chain[1] valid = test_chain.all_blocks_valid() assert valid is False
def __init__(self, filename: str = 'chain'): self.filename = filename if os.path.isfile(filename): with open(filename, 'r') as file: stored_chain = file.read() file.close() self.chain = Chain.from_json(json.loads(stored_chain)) else: self.chain = Chain() self.chain.validate()
def test_add_new_block(self): test_chain = Chain() data = 'New Block' test_chain.add_new_block(data) assert len(test_chain.chain) == 2 assert type(test_chain.get_latest_block()) == Block assert test_chain.get_previous_block().data == 'first Block' assert test_chain.get_latest_block().data == 'New Block' assert test_chain.get_previous_block().index == 0 assert test_chain.get_latest_block().index == 1
def make_chain(): chain = Chain() sender, recipient = Key(), Key() trx = Transaction(sender.address, sender.public_key, recipient.address, "Hi") trx.sign(sender.private_key) genesis = Node.mine_block(0, 0, [trx]) chain.add_block(genesis) for _ in range(1, 2): trx = Transaction(sender.address, sender.public_key, recipient.address, "Hi") trx.sign(sender.private_key) block = Node.mine_block(chain.height, chain.last_block.hash, [trx]) chain.add_block(block) return chain
class Peer: def __init__(self, filename: str = 'chain'): self.filename = filename if os.path.isfile(filename): with open(filename, 'r') as file: stored_chain = file.read() file.close() self.chain = Chain.from_json(json.loads(stored_chain)) else: self.chain = Chain() self.chain.validate() def store_data(self, data) -> None: self.chain.store_data(data) def keep_chain(self, n: int, verbose: bool): for _ in tqdm(range(n)): self.chain.add_block(verbose) with open(self.filename, "w") as file: file.write(self.chain.to_json()) file.close()
def validate_block(block, previous_block): """Validate correctness of block by defined rules. This module doesn't check if there are transactions since the demo will generate blocks without transactions. """ if not previous_block: return False # Index is incremented by 1 if block.index != previous_block.index + 1: logger.info( "Wrong index, block index {}, index of last block {}".format( block.index, previous_block.index)) return False # New block references old one if block.previous_block != previous_block.hash: logger.info( ("New block does not reference previous one, block hash" " {}, hash of last block {}").format(block.hash, previous_block.hash)) return False # Matching versions if block.version < CONFIG.version: logger.info("Older version, block version {}, chain version {}".format( block.version, CONFIG.version)) return False # Timestamp not in the future if block.timestamp > int(time()): logger.info("Timestamp of the new block is in the future") return False # Valid signature content_to_sign = str.encode(block._get_content_for_signing()) signature = key_utils.hex_to_bytes(block.signature) public_key = key_utils.bytes_to_rsa(block.public_key) valid = verify(content_to_sign, signature, public_key) if not valid: logger.info("Signature is not valid, block must be altered") return False # Check if all transactions are valid admissions, doctors, vaccines = Chain().\ get_registration_caches_by_blockhash(block.previous_block) for transaction in block.transactions: if not transaction.validate(admissions, doctors, vaccines): logger.info("Block contains invalid transactions") return False # WONTFIX: Actually, a block should never be empty. However, we leave this # check disabled for demo purposes. # Block has no transactions # if len(block.transactions) == 0: # logger.info("Block does not contain any transaction") # return False # Number of transactions exceeds the maximum if len(block.transactions) > CONFIG.block_size: logger.info( "Too many transactions, block has {}, maximum is {}".format( len(block.transactions), CONFIG.block_size)) return False # Duplicate transactions distinct_transactions = len(set([repr(tx) for tx in block.transactions])) if len(block.transactions) > distinct_transactions: logger.info("Block contains duplicate transactions") return False # Block hash valid content_to_hash = block.get_content_for_hashing() sha = sha256() sha.update(content_to_hash.encode("utf-8")) if block.hash != sha.hexdigest(): logger.info("Hash is not valid, block must be altered") return False return True
def full_client(): Chain(init=True) full_client = FullClient() yield full_client
def __init__(self, host='127.0.0.1', port=5000): self.host = host self.port = port self._peers = set() self._chain = Chain()
class Peer(object): def __init__(self, host='127.0.0.1', port=5000): self.host = host self.port = port self._peers = set() self._chain = Chain() def start(self): server = socketserver.ThreadingTCPServer((self.host, self.port), _PeerRequestHandler) server.peer = self try: server.serve_forever() except KeyboardInterrupt as _: server.server_close() def connect_to_peer(self, host, port): if (host, port) in self._peers: return self._peers.add((host, port)) peers = self._request_peers(host, port) self._add_peers(json.loads(peers)) self._request_connection() self._broadcast_chain() def mine(self, data): self._chain.mine(data) self._broadcast_chain() def replace_chain(self, chain): self._chain.replace_chain(chain) @property def chain(self): return self._chain @property def peers(self): return [{'host': host, 'port': port} for (host, port) in self._peers] def _add_peers(self, peers): for peer in peers: host = peer['host'] port = peer['port'] if host == self.host and port == self.port: continue if (host, port) in self._peers: continue self._peers.add((host, port)) # Communication def _request_connection(self): message = {'type': 'CONNECT', 'host': self.host, 'port': self.port} return self._broadcast(message) def _request_peers(self, host, port): message = {'type': 'PEERS', 'host': self.host, 'port': self.port} return self._unicast(host, port, message) def _broadcast_chain(self): message = {'type': 'CHAIN', 'chain': self._chain.to_dict()} return self._broadcast(message) # Base communication def _unicast(self, host, port, message): pool = multiprocessing.Pool(1) result = pool.apply_async(self._send_message, args=(host, port, message)) pool.close() pool.join() return result.get() def _broadcast(self, message): results = [] pool = multiprocessing.Pool(5) for (host, port) in self._peers: results.append( pool.apply_async(self._send_message, args=(host, port, message))) pool.close() pool.join() return [result.get() for result in results] def _send_message(self, host, port, message): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect((host, port)) s.sendall(json.dumps(message).encode('utf-8')) response = s.recv(655350, 0) return response.decode('utf-8')
def test_chain_is_singleton(): chain_1 = Chain(load_persisted=False) chain_2 = Chain(load_persisted=False) assert id(chain_1) == id(chain_2)
def chain(): chain = Chain(load_persisted=False, init=True) genesis = create_initial_block() chain.add_block(genesis) yield chain
import os import json import time from flask import Flask from twitter import Api from blockchain.chain import Chain app = Flask(__name__) USER_ID = 25073877 # This is Donald Trump CONSUMER_KEY = os.getenv("CONSUMER_KEY", None) CONSUMER_SECRET = os.getenv("CONSUMER_SECRET", None) ACCESS_TOKEN = os.getenv("ACCESS_TOKEN", None) ACCESS_TOKEN_SECRET = os.getenv("ACCESS_TOKEN_SECRET", None) trump_chain = Chain() @app.route("/") def hello(): return "Hello World!" @app.route("/check") def check(): return json.dumps(get_latest_tweets_sorted()) @app.route("/last") def get_last_block_data(): return trump_chain.get_latest_block().data