def setUp(self): self.blockchain = Blockchain() self.chain = self.blockchain.chain self.mempool = self.blockchain.mempool self.network = self.blockchain.network self.wallet = Wallet() self.initial_address = self.wallet.addresses[0]
def main(): path = os.getcwd() print(path) try: print('trying to read') os.chdir(path + '/blk') with open('blkchain.pkl', 'rb') as fp: chain = pickle.load(fp) fp.close() except: check = int(input("Are you miner or wallet :")) if check: print('Miner/Wallet started') else: print('Creating genesis') number_of_candidates = int(input("Enter number of candidates :")) trs = [] for i in range(number_of_candidates): Name = input("Enter name :") age = input("Enter Age :") #usr = User(name=Name, age=age, publickey=sha256(Name.encode() + str(age).encode()).hexdigest(), privatekey=sha256(Name.encode() + str(age).encode()).hexdigest(), candidate=True) ts = Transaction(sha256(Name.encode() + str(age).encode()).hexdigest(), sha256(Name.encode() + str(age).encode()).hexdigest(), 0, name=Name) trs.append(ts) chain = Blockchain() chain.initialize_genesis(trs) os.mkdir('blk') os.chdir(path + '/blk') with open('blkchain.pkl', 'wb') as fp: pickle.dump(chain, fp) fp.close()
def test_should_hash_and_de_hash(self): block = { 'index': 1, 'timestamp': time(), 'transactions': [], 'proof': 1, 'previous_hash': 'abcd', } res = Blockchain.hash(block) assert res proof = 0 while Blockchain.valid_proof(1, proof) is False: proof += 1 assert isinstance(proof, int)
async def test_reorg_from_genesis(self): blocks = bt.get_consecutive_blocks(test_constants, 20, [], 9, b"0") store = FullNodeStore("fndb_test") await store._clear_database() b: Blockchain = Blockchain(store, test_constants) await b.initialize() for block in blocks: await b.receive_block(block) assert b.get_current_tips()[0].height == 20 # Reorg from genesis blocks_reorg_chain = bt.get_consecutive_blocks(test_constants, 21, [blocks[0]], 9, b"1") for reorg_block in blocks_reorg_chain: result = await b.receive_block(reorg_block) if reorg_block.height == 0: assert result == ReceiveBlockResult.ALREADY_HAVE_BLOCK elif reorg_block.height < 19: assert result == ReceiveBlockResult.ADDED_AS_ORPHAN else: assert result == ReceiveBlockResult.ADDED_TO_HEAD assert b.get_current_tips()[0].height == 21 # Reorg back to original branch blocks_reorg_chain_2 = bt.get_consecutive_blocks( test_constants, 3, blocks, 9, b"3") await b.receive_block(blocks_reorg_chain_2[20] ) == ReceiveBlockResult.ADDED_AS_ORPHAN assert (await b.receive_block(blocks_reorg_chain_2[21] )) == ReceiveBlockResult.ADDED_TO_HEAD assert (await b.receive_block(blocks_reorg_chain_2[22] )) == ReceiveBlockResult.ADDED_TO_HEAD
async def test_difficulty_change(self): num_blocks = 30 # Make it 5x faster than target time blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 2) b: Blockchain = Blockchain(test_constants) await b.initialize({}) for i in range(1, num_blocks): assert (await b.receive_block(blocks[i] )) == ReceiveBlockResult.ADDED_TO_HEAD diff_25 = b.get_next_difficulty(blocks[24].header_hash) diff_26 = b.get_next_difficulty(blocks[25].header_hash) diff_27 = b.get_next_difficulty(blocks[26].header_hash) assert diff_26 == diff_25 assert diff_27 > diff_26 assert (diff_27 / diff_26) <= test_constants["DIFFICULTY_FACTOR"] assert (b.get_next_ips( blocks[1].header_hash)) == constants["VDF_IPS_STARTING"] assert (b.get_next_ips(blocks[24].header_hash)) == (b.get_next_ips( blocks[23].header_hash)) assert (b.get_next_ips(blocks[25].header_hash)) == (b.get_next_ips( blocks[24].header_hash)) assert (b.get_next_ips(blocks[26].header_hash)) > (b.get_next_ips( blocks[25].header_hash)) assert (b.get_next_ips(blocks[27].header_hash)) == (b.get_next_ips( blocks[26].header_hash))
async def test1(self): store = FullNodeStore("fndb_test") await store._clear_database() blocks = bt.get_consecutive_blocks(test_constants, 10, [], 10) b: Blockchain = Blockchain(test_constants) await store.add_block(blocks[0]) await b.initialize({}) for i in range(1, 9): assert (await b.receive_block(blocks[i] )) == ReceiveBlockResult.ADDED_TO_HEAD await store.add_block(blocks[i]) full_node_1 = FullNode(store, b) server_1 = ChiaServer(21234, full_node_1, NodeType.FULL_NODE) _ = await server_1.start_server("127.0.0.1", None) full_node_1._set_server(server_1) full_node_2 = FullNode(store, b) server_2 = ChiaServer(21235, full_node_2, NodeType.FULL_NODE) full_node_2._set_server(server_2) await server_2.start_client(PeerInfo("127.0.0.1", uint16(21234)), None) await asyncio.sleep(2) # Allow connections to get made num_unfinished_blocks = 1000 start_unf = time.time() for i in range(num_unfinished_blocks): msg = Message("unfinished_block", peer_protocol.UnfinishedBlock(blocks[9])) server_1.push_message( OutboundMessage(NodeType.FULL_NODE, msg, Delivery.BROADCAST)) # Send the whole block ast the end so we can detect when the node is done block_msg = Message("block", peer_protocol.Block(blocks[9])) server_1.push_message( OutboundMessage(NodeType.FULL_NODE, block_msg, Delivery.BROADCAST)) while time.time() - start_unf < 300: if max([h.height for h in b.get_current_tips()]) == 9: print( f"Time taken to process {num_unfinished_blocks} is {time.time() - start_unf}" ) server_1.close_all() server_2.close_all() await server_1.await_closed() await server_2.await_closed() return await asyncio.sleep(0.1) server_1.close_all() server_2.close_all() await server_1.await_closed() await server_2.await_closed() raise Exception("Took too long to process blocks")
async def test_get_header_hashes(self): blocks = bt.get_consecutive_blocks(test_constants, 5, [], 9, b"0") b: Blockchain = Blockchain(test_constants) await b.initialize({}) for block in blocks: await b.receive_block(block) header_hashes = b.get_header_hashes(blocks[-1].header_hash) assert len(header_hashes) == 6 print(header_hashes) print([block.header_hash for block in blocks]) assert header_hashes == [block.header_hash for block in blocks]
async def initial_blockchain(self): """ Provides a list of 10 valid blocks, as well as a blockchain with 9 blocks added to it. """ blocks = bt.get_consecutive_blocks(test_constants, 10, [], 10) b: Blockchain = Blockchain(test_constants) await b.initialize({}) for i in range(1, 9): assert (await b.receive_block(blocks[i] )) == ReceiveBlockResult.ADDED_TO_HEAD return (blocks, b)
async def test_basic_blockchain(self): bc1: Blockchain = Blockchain() await bc1.initialize({}) assert len(bc1.get_current_tips()) == 1 genesis_block = bc1.get_current_tips()[0] assert genesis_block.height == 0 assert genesis_block.challenge assert (bc1.get_header_blocks_by_height( [uint32(0)], genesis_block.header_hash))[0] == genesis_block assert (bc1.get_next_difficulty( genesis_block.header_hash)) == genesis_block.challenge.total_weight assert bc1.get_next_ips(genesis_block.header_hash) > 0
def update_balances(self, chain): """ Update the balance for each address. :param chain: <list> The blockchain :return: None """ last_block_index = len(chain) for address in self.address_to_balance: balance = Blockchain.address_balance_at_block_index( address, chain, last_block_index) self.address_to_balance[address] = balance
async def test_get_header_hashes(self): blocks = bt.get_consecutive_blocks(test_constants, 5, [], 9, b"0") store = FullNodeStore("fndb_test") await store._clear_database() b: Blockchain = Blockchain(store, test_constants) await b.initialize() for block in blocks: await b.receive_block(block) header_hashes = b.get_header_hashes(blocks[-1].header_hash) assert len(header_hashes) == 6 print(header_hashes) print([block.header_hash for block in blocks]) assert header_hashes == [block.header_hash for block in blocks]
async def test_basic_blockchain(self): store = FullNodeStore("fndb_test") await store._clear_database() bc1: Blockchain = Blockchain(store) await bc1.initialize() assert len(bc1.get_current_tips()) == 1 genesis_block = bc1.get_current_tips()[0] assert genesis_block.height == 0 assert genesis_block.challenge assert (bc1.get_header_blocks_by_height( [uint32(0)], genesis_block.header_hash))[0] == genesis_block assert (await bc1.get_next_difficulty( genesis_block.header_hash)) == genesis_block.challenge.total_weight assert await bc1.get_next_ips(genesis_block.header_hash) > 0
async def initial_blockchain(self): """ Provides a list of 10 valid blocks, as well as a blockchain with 9 blocks added to it. """ store = FullNodeStore("fndb_test") await store._clear_database() blocks = bt.get_consecutive_blocks(test_constants, 10, [], 10) b: Blockchain = Blockchain(store, test_constants) await b.initialize() for i in range(1, 9): assert (await b.receive_block(blocks[i] )) == ReceiveBlockResult.ADDED_TO_HEAD return (blocks, b)
async def test2(self): num_blocks = 100 store = FullNodeStore("fndb_test") await store._clear_database() blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10) b: Blockchain = Blockchain(test_constants) await store.add_block(blocks[0]) await b.initialize({}) full_node_1 = FullNode(store, b) server_1 = ChiaServer(21236, full_node_1, NodeType.FULL_NODE) _ = await server_1.start_server("127.0.0.1", None) full_node_1._set_server(server_1) full_node_2 = FullNode(store, b) server_2 = ChiaServer(21237, full_node_2, NodeType.FULL_NODE) full_node_2._set_server(server_2) await server_2.start_client(PeerInfo("127.0.0.1", uint16(21236)), None) await asyncio.sleep(2) # Allow connections to get made start_unf = time.time() for i in range(1, num_blocks): msg = Message("block", peer_protocol.Block(blocks[i])) server_1.push_message( OutboundMessage(NodeType.FULL_NODE, msg, Delivery.BROADCAST)) while time.time() - start_unf < 300: if max([h.height for h in b.get_current_tips()]) == num_blocks - 1: print( f"Time taken to process {num_blocks} is {time.time() - start_unf}" ) server_1.close_all() server_2.close_all() await server_1.await_closed() await server_2.await_closed() return await asyncio.sleep(0.1) server_1.close_all() server_2.close_all() await server_1.await_closed() await server_2.await_closed() raise Exception("Took too long to process blocks")
async def test_basic_reorg(self): blocks = bt.get_consecutive_blocks(test_constants, 100, [], 9) b: Blockchain = Blockchain(test_constants) await b.initialize({}) for block in blocks: await b.receive_block(block) assert b.get_current_tips()[0].height == 100 blocks_reorg_chain = bt.get_consecutive_blocks(test_constants, 30, blocks[:90], 9, b"1") for reorg_block in blocks_reorg_chain: result = await b.receive_block(reorg_block) if reorg_block.height < 90: assert result == ReceiveBlockResult.ALREADY_HAVE_BLOCK elif reorg_block.height < 99: assert result == ReceiveBlockResult.ADDED_AS_ORPHAN elif reorg_block.height >= 100: assert result == ReceiveBlockResult.ADDED_TO_HEAD assert b.get_current_tips()[0].height == 119
async def test_lca(self): blocks = bt.get_consecutive_blocks(test_constants, 5, [], 9, b"0") b: Blockchain = Blockchain(test_constants) await b.initialize({}) for block in blocks: await b.receive_block(block) assert b.lca_block == blocks[3].header_block block_5_2 = bt.get_consecutive_blocks(test_constants, 1, blocks[:5], 9, b"1")[5] block_5_3 = bt.get_consecutive_blocks(test_constants, 1, blocks[:5], 9, b"2")[5] await b.receive_block(block_5_2) assert b.lca_block == blocks[4].header_block await b.receive_block(block_5_3) assert b.lca_block == blocks[4].header_block reorg = bt.get_consecutive_blocks(test_constants, 6, [], 9, b"3") for block in reorg: await b.receive_block(block) assert b.lca_block == blocks[0].header_block
async def test_lca(self): blocks = bt.get_consecutive_blocks(test_constants, 5, [], 9, b"0") store = FullNodeStore("fndb_test") await store._clear_database() b: Blockchain = Blockchain(store, test_constants) await b.initialize() for block in blocks: await b.receive_block(block) assert b.lca_block == blocks[3] block_5_2 = bt.get_consecutive_blocks(test_constants, 1, blocks[:5], 9, b"1")[5] block_5_3 = bt.get_consecutive_blocks(test_constants, 1, blocks[:5], 9, b"2")[5] await b.receive_block(block_5_2) assert b.lca_block == blocks[4] await b.receive_block(block_5_3) assert b.lca_block == blocks[4] reorg = bt.get_consecutive_blocks(test_constants, 6, [], 9, b"3") for block in reorg: await b.receive_block(block) assert b.lca_block == blocks[0]
class NetworkHandler: def __init__(self, first=False): self.other_nodes = {} self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.connected_clients = [] self.blockchain = None self.name = None self.server_host = get_local_ip() self.message_list = [] self.ip = str(get_local_ip()) # self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.keep_running_server = True self.manual_validation = False self.block_to_add = None self.wait = False self.client = None self.updateVisualizer() def create_blockchain(self, first): self.blockchain = Blockchain(first=first) def start_server(self): self.server.bind((self.server_host, SERVER_PORT)) self.server.listen(5) def add_node(self, ip, name): node = Node(ip, name) self.other_nodes[ip] = node self.updateVisualizer() def remove_node(self, ip): try: del self.other_nodes[ip] except KeyError: print(f"{ip} tried to be removed but not in list") self.updateVisualizer() def process_message(self, message, ip, i): print(f"\n\nRECEIVED from {ip} in {i} chunks: \n{message}\n\n") message_dict = {"sender": ip, "content": message} self.message_list.append(message_dict) self.updateVisualizerMessage() if message[:4] != "****": print("Error: bad request") elif message.split("|")[0][4:] == "join": self.join_protocol(ip, message) elif message[4:] == "leave": print("===== Remove node") self.remove_node(ip) elif message.split("|")[0][4:] == "join_resp": self.join_resp_protocol(ip, message) elif message.split("|")[0][4:] == "joined": self.add_node(ip, message.split("|")[1]) print("===== Nice to meet you") elif message[4:] == "ack": print("===== Welcome") elif message.split("|")[0][4:] == "mined_block": self.mined_block_protocol(message) elif message.split("|")[0][4:] == "accept": hash_block = message.split("|")[1] if self.blockchain.get_block(hash_block) is None: mess = "****askblock|" + hash_block send_message(ip, mess) print("===== Node accepted") elif message[4:] == "refuse": print("===== Node refused") elif message.split("|")[0][4:] == "blockchain": self.blockchain_protocol(message) elif message.split("|")[0][4:] == "ackdefault": print("==== This node may be defective") elif message.split("|")[0][4:] == "askblock": hash_block = message.split("|")[1] block_to_send = self.blockchain.get_block(hash_block) mess = "****" mess += "mined_block|" mess += json.dumps(block_to_send, cls=BlockEncoder) send_message(ip, mess) else: print("Error: bad request") print(f"Other nodes: {self.other_nodes}") def blockchain_protocol(self, message): blockchain = json.loads(message.split("|")[1]) leaves = json.loads(message.split("|")[2]) blockchain = [Block(**block) for block in blockchain] blockchain.sort() # The blocks are sorted by height. for block in blockchain: self.blockchain.new_block(block) def mined_block_protocol(self, message): block_info_json = json.loads(message.split("|")[1]) self.block_to_add = Block(**block_info_json) self.client.hiddenRefreshButton.click() if self.manual_validation: self.wait = True while self.wait: pass else: message = self.blockchain.new_block(self.block_to_add) for ip_node in self.other_nodes: send_message(ip_node, message) message_dict = {"sender": "Me", "content": message} self.message_list.append(message_dict) self.block_to_add = None self.client.hiddenRefreshButton.click() def join_resp_protocol(self, ip, message): nodes_dict_str = message.split("|")[1] nodes_dict = json.loads(nodes_dict_str) for node_dict in nodes_dict.values(): self.other_nodes[node_dict["ip"]] = Node(node_dict["ip"], node_dict["name"]) self.add_node(ip, message.split("|")[2]) for node in self.other_nodes.values(): send_message(node.ip_address, "****joined|" + self.name) message_dict = {"sender": "Me", "content": "****joined"} self.message_list.append(message_dict) def join_protocol(self, ip, message): print("===== Add node") mess = "****join_resp|" mess += json.dumps(self.other_nodes, cls=NodeEncoder) mess += "|" mess += self.name send_message(ip, mess) self.add_node(ip, message.split("|")[1]) message_dict = {"sender": "Me", "content": mess} self.message_list.append(message_dict) mess2 = "****blockchain|" list_blocks = [] leaves = self.blockchain.get_leaves() for leaf in leaves: leaf_block = self.blockchain.get_block(leaf["hash"]) current_block = leaf_block for i in range(0, leaf_block.index + 1): if current_block not in list_blocks: list_blocks.append(current_block) if current_block.index != 0: current_block = self.blockchain.get_block( current_block.previous_hash ) mess2 += json.dumps(list_blocks, cls=BlockEncoder) mess2 += "|" mess2 += json.dumps(leaves) if mess2 != "": send_message(ip, mess2) message_dict2 = {"sender": "Me", "content": mess2} self.message_list.append(message_dict) def send_message_to_all(self, message): self.updateVisualizerMessage() for ip in self.other_nodes.keys(): send_message(ip, message) def updateVisualizer(self): all_nodes = [] for node in self.other_nodes.values(): node_dic = {"name": node.name, "ip": node.ip_address} # "Prenom" to change all_nodes.append(node_dic) my_node = {"name": "You", "ip": self.ip} all_nodes.insert(0, my_node) nodes = {"nodes": all_nodes} nodes_json = json.dumps(nodes) with open("etc/visudata/nodes.json", "w") as file: file.write(nodes_json) def updateVisualizerMessage(self): messages = {"messages": self.message_list} messages_json = json.dumps(messages) with open("etc/visudata/messages.json", "w") as file: file.write(messages_json) def accept_mined_block(self): leaves = self.blockchain.get_leaves() leaves_hashes = [leaf["hash"] for leaf in leaves] if self.blockchain.nb_children(self.block_to_add.previous_hash) > 0: # The previous block is not a leaf, so we create a fork # if block.previous_hash in leaves_hashes: # Just to check # raise ValueError( # f"Inconsistent data: block {block.previous_hash} is " # "listed as a leaf but has at least one child block." # ) fork_id = self.blockchain.add_fork( self.block_to_add.hash, self.block_to_add.index ) self.block_to_add.branch_id = fork_id self.blockchain.add_block(self.block_to_add) else: # The previous block is a leaf, so we stay on the same branch parent_leaf = [ leaf for leaf in leaves if leaf["hash"] == self.block_to_add.previous_hash ] if len(parent_leaf) != 1: raise ValueError( f"Inconsistent data: block {block.previous_hash} is " f"the leaf block of {len(parent_leaf)} branches (should be 1)." ) parent_leaf = parent_leaf[0] self.block_to_add.branch_id = parent_leaf["fork_id"] self.blockchain.add_block(self.block_to_add) self.blockchain.update_fork( parent_leaf["fork_id"], self.block_to_add.hash, self.block_to_add.index ) self.send_message_to_all("****accept|" + self.block_to_add.hash) self.wait = False self.client.hiddenRefreshButton.click() def refuse_mined_block(self): self.send_message_to_all("****refuse") self.wait = False self.block_to_add = None self.client.hiddenRefreshButton.click() def run_server(self): while self.keep_running_server: incoming_connections, wlist, xlist = select.select( [self.server], [], [], LISTEN_TIME ) for connection in incoming_connections: client_connection, client_connection_info = connection.accept() self.connected_clients.append(client_connection) clients_to_be_read = [] try: clients_to_be_read, wlist, xlist = select.select( self.connected_clients, [], [], LISTEN_TIME ) except select.error: pass else: for client in clients_to_be_read: message = b"" chunks = 0 while True: chunks += 1 part = client.recv(RECV_SIZE) if len(part) == 0: # We have reached the end of the stream break message += part ip, port = client.getpeername() message = message.decode() self.process_message(message, ip, chunks) self.connected_clients.remove(client) client.close() for client in self.connected_clients: client.close()
def create_blockchain(self, first): self.blockchain = Blockchain(first=first)
parser.add_argument( '-o', type=str, help= 'output file without requiring an initial blockchain file to read from (default: \'blockchain.json\')' ) args = parser.parse_args() node_id = uuid() if __name__ == '__main__': # Load Blockchain File filename = args.file if filename: data = json.load(open(filename)) blockchain = Blockchain( list(map(lambda block: block['header'], data['chain']))) else: filename = args.o blockchain = Blockchain() node = SPVNode(name=args.n or f'node-{node_id}', port=args.p or 5000, blockchain=blockchain) try: print(f'Starting node-{node_id}') # Establish Connection while not node.ready: node.send('version', message=json.dumps(
from flask import Flask, jsonify, request, redirect, url_for from src.blockchain import Blockchain from src.wallet import Wallet app = Flask(__name__) blockchain = Blockchain('bank') @app.route('/add_transaction', methods=['POST']) def add_transaction(): json = request.get_json() transaction_keys = ['sender', 'receiver', 'amount'] if not all(key in json for key in transaction_keys): return 'Está faltando algum elemento.', 400 index = blockchain.add_transaction(json['sender'], json['receiver'], json['amount']) response = {'mensagem': f'Esta transação será adicionada ao bloco {index}'} return jsonify(response), 201 @app.route('/delete_transaction') def delete_transaction(): blockchain.delete_transaction() return jsonify({'mensagem':'Transação deletada!'}) @app.route('/mine_block/<hosting>', methods=['GET']) def mine_block(hosting): w = Wallet() if not w.read_wallet(hosting): return jsonify({'mensagem':'Falta hosting wallet!'}) blockchain.wallet = w
from src.block import Block from src.blockchain import Blockchain # genesis = Block.getGenesis() # bloque1 = Block.mine(genesis,'D4t4-Bloqu3_1') # bloque2 = Block.mine(bloque1,'D4t4-Bloqu3_2') # print(bloque1) # print(bloque2) print("Test 1 -Every blockchain has a Genesis Block") blockchain = Blockchain() genesis = blockchain.blocks[0] print(genesis) print("Test 2 - use addBlock") blockchain = Blockchain() data = 'd4t4-blk1' blockchain.addBlock(data) lastBlock = blockchain.blocks[-1] print(lastBlock.data == data) print(len(blockchain.blocks) == 2) print("Test 3 - replaces the chain with a valid chain") blockchain = Blockchain() blockchainb = Blockchain() data = 'd4t4-blk1' blockchainb.addBlock(data) blockchain.replaceBlock(blockchainb.blocks) print(blockchain.blocks == blockchainb.blocks) print("Test 4 - Does not replace with one with less blocks")
from flask import Flask, jsonify, request from flask_restful import reqparse, abort, Api, Resource from src.blockchain import Blockchain app = Flask(__name__) api = Api(app) blockchain = Blockchain('Alex') class Get_Chain(Resource): def get(self): response = {'chain': blockchain.chain, 'length': len(blockchain.chain)} return response, 200 class Add_Transaction(Resource): def post(self): parser = reqparse.RequestParser() parser.add_argument('sender', required=True, help='Obrigatório!') parser.add_argument('receiver', required=True, help='Obrigatório!') parser.add_argument('amount', type=float, required=True, help='Obrigatório!') args = parser.parse_args() index = blockchain.add_transaction(args['sender'], args['receiver'], args['amount']) response = { 'mensagem': f'Esta transação será adicionada ao bloco {index}'
class MainTestCase(TestCase): def setUp(self): self.blockchain = Blockchain() self.chain = self.blockchain.chain self.mempool = self.blockchain.mempool self.network = self.blockchain.network self.wallet = Wallet() self.initial_address = self.wallet.addresses[0] def test_initialize_blockchain(self): self.assertEqual(len(self.chain), 1) self.assertTrue(self.blockchain.valid_chain(self.chain)) self.assertFalse(self.mempool.current_transactions) self.assertFalse(self.network.nodes) def test_initialize_wallet(self): self.assertEqual(len(self.wallet.addresses), 1) self.assertEqual(len(self.wallet.address_to_keys), 1) self.assertEqual(len(self.wallet.address_to_balance), 1) self.assertEqual(self.wallet.address_to_balance[self.initial_address], 0) self.assertEqual(self.wallet.total_balance(), 0) self.assertEqual( privtopub(self.wallet.address_to_keys[self.initial_address][0]), self.wallet.address_to_keys[self.initial_address][1]) self.assertEqual( pubtoaddr(self.wallet.address_to_keys[self.initial_address][1]), self.initial_address) def test_wallet_generate_address(self): self.wallet.generate_address() new_address = self.wallet.addresses[1] self.assertEqual(len(self.wallet.addresses), 2) self.assertEqual(len(self.wallet.address_to_keys), 2) self.assertEqual(len(self.wallet.address_to_balance), 2) self.assertEqual(self.wallet.address_to_balance[new_address], 0) self.assertEqual(self.wallet.total_balance(), 0) self.assertEqual( privtopub(self.wallet.address_to_keys[new_address][0]), self.wallet.address_to_keys[new_address][1]) self.assertEqual( pubtoaddr(self.wallet.address_to_keys[new_address][1]), new_address) def test_wallet_sign_transaction(self): signed_transaction = self.wallet.sign_transaction( self.initial_address, '14peaf2JegQP5nmNQESAdpRGLbse8JqgJD', 0) signature = signed_transaction['signature'] transaction_content = { 'sender': self.initial_address, 'recipient': '14peaf2JegQP5nmNQESAdpRGLbse8JqgJD', 'amount': 0 } transaction_encoded = json.dumps(transaction_content, sort_keys=True).encode() transaction_hash = hashlib.sha256(transaction_encoded).hexdigest() self.assertEqual( signature, ecdsa_sign(transaction_hash, self.wallet.address_to_keys[self.initial_address][0])) def test_proof_of_work(self): transactions_hash = self.mempool.hash([]) previous_block_hash = self.blockchain.hash(self.blockchain.last_block) nonce = ProofOfWork.proof_of_work(transactions_hash, previous_block_hash) encoded = f'{transactions_hash}{previous_block_hash}{nonce}'.encode() hashed = hashlib.sha256(encoded).hexdigest() self.assertEqual(hashed[:4], '0000') self.assertTrue( ProofOfWork.valid_proof(transactions_hash, previous_block_hash, nonce)) def test_proof_of_work_invalid_nonce(self): transactions_hash = self.mempool.hash([]) previous_block_hash = self.blockchain.hash(self.blockchain.last_block) nonce = 12345 self.assertFalse( ProofOfWork.valid_proof(transactions_hash, previous_block_hash, nonce)) def test_mempool_add_valid_transaction(self): signed_transaction = self.wallet.sign_transaction( self.initial_address, '14peaf2JegQP5nmNQESAdpRGLbse8JqgJD', 0) self.assertTrue( self.mempool.valid_transaction(signed_transaction, self.blockchain)) self.assertTrue( self.mempool.add_transaction(signed_transaction, self.blockchain)) self.assertEqual(len(self.mempool.current_transactions), 1) def test_mempool_add_invalid_transaction(self): # too high amount of coins invalid_transaction = self.wallet.sign_transaction( self.initial_address, '14peaf2JegQP5nmNQESAdpRGLbse8JqgJD', 10) self.assertFalse( self.mempool.valid_transaction(invalid_transaction, self.blockchain)) self.assertFalse( self.mempool.add_transaction(invalid_transaction, self.blockchain)) self.assertEqual(len(self.mempool.current_transactions), 0) # negative amount of coins invalid_transaction = self.wallet.sign_transaction( self.initial_address, '14peaf2JegQP5nmNQESAdpRGLbse8JqgJD', -1) self.assertFalse( self.mempool.valid_transaction(invalid_transaction, self.blockchain)) self.assertFalse( self.mempool.add_transaction(invalid_transaction, self.blockchain)) self.assertEqual(len(self.mempool.current_transactions), 0) # invalid signature invalid_transaction = { 'sender': self.initial_address, 'recipient': '14peaf2JegQP5nmNQESAdpRGLbse8JqgJD', 'amount': 0, 'signature': 'GwQr4EOfrRUicb34fgB9ix69PNa8nMjSXEgZfBRFha9tWQCvgaWco5v8JlIU89WDHLX6gTLHn9qIIEaV0mzxFoM=' } self.assertFalse( self.mempool.valid_transaction(invalid_transaction, self.blockchain)) self.assertFalse( self.mempool.add_transaction(invalid_transaction, self.blockchain)) self.assertEqual(len(self.mempool.current_transactions), 0) def test_register_node(self): self.network.register_node('http://192.168.0.1:5000') self.assertIn('192.168.0.1:5000', self.network.nodes) self.assertEqual(len(self.network.nodes), 1) def test_register_duplicate_node(self): self.network.register_node('http://192.168.0.1:5000') self.network.register_node('http://192.168.0.1:5000') self.assertEqual(len(self.network.nodes), 1) def test_register_invalid_node(self): self.network.register_node('http//192.168.0.1:5000') self.assertNotIn('192.168.0.1:5000', self.network.nodes) self.assertEqual(len(self.network.nodes), 0) def test_create_block(self): signed_transaction = self.wallet.sign_transaction( self.initial_address, '14peaf2JegQP5nmNQESAdpRGLbse8JqgJD', 0) self.mempool.add_transaction(signed_transaction, self.blockchain) transactions_hash = self.mempool.hash( self.mempool.current_transactions) previous_block_hash = self.blockchain.hash(self.blockchain.last_block) nonce = ProofOfWork.proof_of_work(transactions_hash, previous_block_hash) self.blockchain.create_block(nonce, previous_block_hash, self.mempool.current_transactions) created_block = self.blockchain.last_block self.assertEqual(len(self.blockchain.chain), 2) self.assertEqual(created_block, self.blockchain.chain[-1]) self.assertEqual(created_block['index'], 2) self.assertIsNotNone(created_block['timestamp']) self.assertEqual(created_block['nonce'], nonce) self.assertEqual(created_block['transactions_hash'], transactions_hash) self.assertEqual(created_block['previous_block_hash'], previous_block_hash) self.assertEqual(created_block['transactions'], [signed_transaction]) self.assertEqual(len(self.mempool.current_transactions), 0) def test_block_hash(self): signed_transaction = self.wallet.sign_transaction( self.initial_address, '14peaf2JegQP5nmNQESAdpRGLbse8JqgJD', 0) self.mempool.add_transaction(signed_transaction, self.blockchain) transactions_hash = self.mempool.hash( self.mempool.current_transactions) previous_block_hash = self.blockchain.hash(self.blockchain.last_block) nonce = ProofOfWork.proof_of_work(transactions_hash, previous_block_hash) self.blockchain.create_block(nonce, previous_block_hash, self.mempool.current_transactions) created_block = self.blockchain.last_block block_encoded = json.dumps(created_block, sort_keys=True).encode() block_hash = hashlib.sha256(block_encoded).hexdigest() self.assertEqual(len(self.blockchain.hash(created_block)), 64) self.assertEqual(self.blockchain.hash(created_block), block_hash) def test_valid_chain(self): signed_transaction = self.wallet.sign_transaction( self.initial_address, '14peaf2JegQP5nmNQESAdpRGLbse8JqgJD', 0) self.mempool.add_transaction(signed_transaction, self.blockchain) transactions_hash = self.mempool.hash( self.mempool.current_transactions) previous_block_hash = self.blockchain.hash(self.blockchain.last_block) nonce = ProofOfWork.proof_of_work(transactions_hash, previous_block_hash) self.blockchain.create_block(nonce, previous_block_hash, self.mempool.current_transactions) self.assertTrue(self.blockchain.valid_chain(self.blockchain.chain)) def test_valid_chain_transactions(self): # Mine 10 coins to initial_address coinbase_transaction = { 'sender': '0', 'recipient': self.initial_address, 'amount': 10 } transactions_hash = self.mempool.hash([coinbase_transaction]) previous_block_hash = self.blockchain.hash(self.blockchain.last_block) nonce = ProofOfWork.proof_of_work(transactions_hash, previous_block_hash) self.blockchain.create_block(nonce, previous_block_hash, [coinbase_transaction]) # Spend the mined coins signed_transaction = self.wallet.sign_transaction( self.initial_address, '14peaf2JegQP5nmNQESAdpRGLbse8JqgJD', 10) self.mempool.add_transaction(signed_transaction, self.blockchain) transactions_hash = self.mempool.hash( self.mempool.current_transactions) previous_block_hash = self.blockchain.hash(self.blockchain.last_block) nonce = ProofOfWork.proof_of_work(transactions_hash, previous_block_hash) self.blockchain.create_block(nonce, previous_block_hash, self.mempool.current_transactions) self.assertTrue(self.blockchain.valid_chain(self.blockchain.chain)) def test_invalid_chain_prev_block_hash(self): signed_transaction = self.wallet.sign_transaction( self.initial_address, '14peaf2JegQP5nmNQESAdpRGLbse8JqgJD', 0) transactions_hash = self.mempool.hash( self.mempool.current_transactions) previous_block_hash = self.blockchain.hash(self.blockchain.last_block) nonce = ProofOfWork.proof_of_work(transactions_hash, previous_block_hash) block = { 'index': len(self.chain) + 1, 'timestamp': time(), 'nonce': nonce, 'transactions_hash': transactions_hash, 'previous_block_hash': '12345', 'transactions': [signed_transaction] } self.blockchain.chain.append(block) self.assertFalse(self.blockchain.valid_chain(self.blockchain.chain)) def test_invalid_chain_nonce(self): signed_transaction = self.wallet.sign_transaction( self.initial_address, '14peaf2JegQP5nmNQESAdpRGLbse8JqgJD', 0) transactions_hash = self.mempool.hash( self.mempool.current_transactions) previous_block_hash = self.blockchain.hash(self.blockchain.last_block) block = { 'index': len(self.chain) + 1, 'timestamp': time(), 'nonce': 12345, 'transactions_hash': transactions_hash, 'previous_block_hash': previous_block_hash, 'transactions': [signed_transaction] } self.blockchain.chain.append(block) self.assertFalse(self.blockchain.valid_chain(self.blockchain.chain)) def test_invalid_chain_coinbase_transaction_amount(self): coinbase_transaction = { 'sender': '0', 'recipient': self.initial_address, 'amount': 100 } transactions_hash = self.mempool.hash([coinbase_transaction]) previous_block_hash = self.blockchain.hash(self.blockchain.last_block) nonce = ProofOfWork.proof_of_work(transactions_hash, previous_block_hash) block = { 'index': len(self.chain) + 1, 'timestamp': time(), 'nonce': nonce, 'transactions_hash': transactions_hash, 'previous_block_hash': previous_block_hash, 'transactions': [coinbase_transaction] } self.blockchain.chain.append(block) self.assertFalse(self.blockchain.valid_chain(self.blockchain.chain)) def test_invalid_chain_coinbase_transaction_duplicate(self): coinbase_transaction = { 'sender': '0', 'recipient': self.initial_address, 'amount': 10 } transactions_hash = self.mempool.hash( [coinbase_transaction, coinbase_transaction]) previous_block_hash = self.blockchain.hash(self.blockchain.last_block) nonce = ProofOfWork.proof_of_work(transactions_hash, previous_block_hash) block = { 'index': len(self.chain) + 1, 'timestamp': time(), 'nonce': nonce, 'transactions_hash': transactions_hash, 'previous_block_hash': previous_block_hash, 'transactions': [coinbase_transaction, coinbase_transaction] } self.blockchain.chain.append(block) self.assertFalse(self.blockchain.valid_chain(self.blockchain.chain)) def test_invalid_chain_transactions(self): # Mine 10 coins to initial_address coinbase_transaction = { 'sender': '0', 'recipient': self.initial_address, 'amount': 10 } transactions_hash = self.mempool.hash([coinbase_transaction]) previous_block_hash = self.blockchain.hash(self.blockchain.last_block) nonce = ProofOfWork.proof_of_work(transactions_hash, previous_block_hash) self.blockchain.create_block(nonce, previous_block_hash, [coinbase_transaction]) # Include a transaction in block with to much coins spent signed_transaction = self.wallet.sign_transaction( self.initial_address, '14peaf2JegQP5nmNQESAdpRGLbse8JqgJD', 100) self.mempool.current_transactions.append(signed_transaction) transactions_hash = self.mempool.hash( self.mempool.current_transactions) previous_block_hash = self.blockchain.hash(self.blockchain.last_block) nonce = ProofOfWork.proof_of_work(transactions_hash, previous_block_hash) self.blockchain.create_block(nonce, previous_block_hash, self.mempool.current_transactions) self.assertFalse(self.blockchain.valid_chain(self.blockchain.chain))
async def main(): # Create the store (DB) and full node instance db_id = 0 if "-id" in sys.argv: db_id = int(sys.argv[sys.argv.index("-id") + 1]) store = FullNodeStore(f"fndb_{db_id}") blockchain = Blockchain(store) log.info("Initializing blockchain from disk") await blockchain.initialize() full_node = FullNode(store, blockchain) # Starts the full node server (which full nodes can connect to) host, port = parse_host_port(full_node) if full_node.config["enable_upnp"]: log.info(f"Attempting to enable UPnP (open up port {port})") try: upnp = miniupnpc.UPnP() upnp.discoverdelay = 5 upnp.discover() upnp.selectigd() upnp.addportmapping(port, "TCP", upnp.lanaddr, port, "chia", "") except Exception as e: log.warning(f"UPnP failed: {e}") server = ChiaServer(port, full_node, NodeType.FULL_NODE) full_node._set_server(server) _ = await server.start_server(host, full_node._on_connect) wait_for_ui, ui_close_cb = None, None def master_close_cb(): global server_closed if not server_closed: # Called by the UI, when node is closed, or when a signal is sent log.info("Closing all connections, and server...") full_node._shutdown() server.close_all() server_closed = True def signal_received(): if ui_close_cb: ui_close_cb() master_close_cb() asyncio.get_running_loop().add_signal_handler(signal.SIGINT, signal_received) asyncio.get_running_loop().add_signal_handler(signal.SIGTERM, signal_received) if "-u" in sys.argv: # Starts the UI if -u is provided index = sys.argv.index("-u") ui_ssh_port = int(sys.argv[index + 1]) from src.ui.prompt_ui import start_ssh_server wait_for_ui, ui_close_cb = await start_ssh_server( store, blockchain, server, port, ui_ssh_port, full_node.config["ssh_filename"], master_close_cb, ) connect_to_farmer = "-f" in sys.argv connect_to_timelord = "-t" in sys.argv full_node._start_bg_tasks() log.info("Waiting to connect to some peers...") await asyncio.sleep(3) log.info( f"Connected to {len(server.global_connections.get_connections())} peers." ) if connect_to_farmer and not server_closed: peer_info = PeerInfo( full_node.config["farmer_peer"]["host"], full_node.config["farmer_peer"]["port"], ) _ = await server.start_client(peer_info, None) if connect_to_timelord and not server_closed: peer_info = PeerInfo( full_node.config["timelord_peer"]["host"], full_node.config["timelord_peer"]["port"], ) _ = await server.start_client(peer_info, None) # Awaits for server and all connections to close await server.await_closed() # Awaits for all ui instances to close if wait_for_ui is not None: await wait_for_ui() await asyncio.get_running_loop().shutdown_asyncgens()
parser.add_argument( '-o', type=str, help= 'output file without requiring an initial blockchain file to read from (default: \'blockchain.json\')' ) args = parser.parse_args() node_id = uuid() if __name__ == '__main__': # Load Blockchain File filename = args.file if filename: data = json.load(open(filename)) blockchain = Blockchain(data['chain'], data['tx_info']) else: filename = args.o blockchain = Blockchain() node = MinerNode(name=args.n or f'node-{node_id}', port=args.p or 5000, blockchain=blockchain) try: print(f'Starting node-{node_id}') # Establish Connection while not node.ready: node.send('version', message=json.dumps(
def setUp(self): self.blockchain = Blockchain()
def __init__(self): self.transactions = {} self.blockchain = Blockchain()
from time import time from uuid import uuid4 from flask import Flask, jsonify, request from src.blockchain import Blockchain try: from urllib.parse import urlparse except ImportError: from urlparse import urlparse # instantiate our node app = Flask(__name__) # generate a globally unique adress for this node node_identifier = str(uuid4()).replace('-', '') cprint('> this node key: {}'.format(node_identifier), 'cyan') # instantiate the blockchain blockchain = Blockchain() # define routes @app.route('/mine', methods=['GET']) def mine(): # algorithm to get the next proof last_block = blockchain.last_block last_proof = last_block['proof'] proof = blockchain.proof_of_work(last_proof) # we must recieve a reward for finding the proof # the sender is "0" to signify that this node has mined a new coin blockchain.new_transaction(sender="Mined", recipient=node_identifier, amount=1) # forge the new block by adding it to the chain
from fastapi import APIRouter from src.blockchain import Blockchain from src.model import NewBlock, Transaction router = APIRouter() bc = Blockchain() @router.get("/last-block") async def get_last_block(): return bc.last_block @router.post("/new-block") async def new_block(block: NewBlock): return bc.new_block(block.proof, block.previous_hash) @router.post("/transaction") async def new_transaction(transaction: Transaction): return bc.new_transaction(transaction.sender, transaction.recipient, transaction.amount)