def test_mining_block(): node_id = uuid4() w = Wallet(test=True) chain = Blockchain(w.address, node_id, is_test=True) assert Verification.verify_chain(chain.chain) chain.mine_block() assert Verification.verify_chain(chain.chain) chain.mine_block() assert Verification.verify_chain(chain.chain)
def test_mining_block_with_open_transactions(): timestamp = datetime.utcfromtimestamp(0) node_id = uuid4() w1 = Wallet(test=True) w2 = Wallet(test=True) chain = Blockchain(w1.address, node_id, difficulty=1, is_test=True) tx_details_1 = Details( sender=w1.address, recipient=w2.address, nonce=0, amount=0.5, timestamp=timestamp, public_key=w1.public_key.hex(), ) transaction_1 = w1.sign_transaction(tx_details_1) tx_details_2 = Details( sender=w2.address, recipient=w1.address, nonce=0, amount=0.5, timestamp=timestamp, public_key=w2.public_key.hex(), ) transaction_2 = w2.sign_transaction(tx_details_2) assert Verification.verify_chain(chain.chain) # Need to give the w1 at least 1.0 coin in their balance chain.mine_block() assert Verification.verify_chain(chain.chain) chain.add_transaction(transaction_1, is_receiving=True) chain.mine_block() assert Verification.verify_chain(chain.chain) chain_transactions = [] for block in chain.chain: for tx in block.transactions: chain_transactions.append(tx) assert Verification.hash_transaction(transaction_1) in chain_transactions chain.add_transaction(transaction_2, is_receiving=True) chain.mine_block() chain_transactions = [] for block in chain.chain: for tx in block.transactions: chain_transactions.append(tx) assert Verification.hash_transaction(transaction_2) in chain_transactions
def listen(self): waiting_for_input = True while waiting_for_input: print('Please choose') print('1: Add a new transaction value') print('2: Mine a new block') print('3: Output the blockchain blocks') print('4: Check transaction validity') print('5: Create wallet') print('6: Load wallet') print('7: Save keys') print('q: Quit') user_choice = input('Selection: ') if user_choice == '1': tx_data = self.get_transaction_value() recipient, amount = tx_data if self.blockchain.add_transaction(recipient, self.id, amount=amount): print('Transaction Added') else: print('Transaction Failed') print(self.blockchain.open_transactions) elif user_choice == '2': self.blockchain.mine_block() elif user_choice == '3': self.print_blockchain_elements() elif user_choice == '4': if Verification.verify_transactions(self.blockchain.open_transactions, self.blockchain.get_balance): print('All transactions valid') else: print('Invalid transaction found!') print('Exiting!') break elif user_choice == '5': self.wallet.create_keys() self.blockchain = Blockchain(self.wallet.public_key) elif user_choice == '6': self.wallet.load_keys() self.blockchain = Blockchain(self.wallet.public_key) elif user_choice == '7': self.wallet.save_keys() elif user_choice == 'q': waiting_for_input = False else: print('Input was invalid, please pick a value from the list!') if not Verification.verify_chain(self.blockchain.chain): self.print_blockchain_elements() print('Invalid blockchain!') break print() print('Balance of {}: {:6.4f}'.format(self.wallet.public_key, self.blockchain.get_balance())) else: print('User left!') print('Done!')
def listen_for_input(self): waiting_for_input = True while waiting_for_input: print('Please choose') print('1: Add a new transaction value') print('2: Mine a new block') print('3: Output the blockchain blocks') print('4: Check transaction validity') # print('h: Manipulate the chain') print('q: Quit') user_choice = self.get_user_choice() if user_choice == '1': tx_data = self.get_transaction_value() recipient, amount = tx_data if self.blockchain.add_transaction(recipient, self.id, amount=amount): print('Added transaction!') else: print('Transaction failed!') print(self.blockchain.open_transactions) elif user_choice == '2': self.blockchain.mine_block() elif user_choice == '3': self.print_blockchain_elements() elif user_choice == '4': v = Verification() if v.verify_transactions(self.blockchain.open_transactions, self.blockchain.get_balance): print('All transactions are valid') else: print('There are invalid transactions') # elif user_choice == 'h': # if len(blockchain) >= 1: # blockchain[0] = { # 'previous_hash': '', # 'index': 0, # 'transactions': [{ # 'sender': 'Chris', # 'recipient': 'Will', # 'amount': 100.0 # }] # } elif user_choice == 'q': waiting_for_input = False else: print('Input was invalid, please pick a value from the list!') v = Verification() if not v.verify_chain(self.blockchain.chain): self.print_blockchain_elements() print('Invalid blockchain!') break print('Balance of {}: {:6.2f}'.format( self.id, self.blockchain.get_balance())) else: print('User left!') print('Done!')
def listen_for_input(self): awaiting_input = True while awaiting_input: print("Please choose:") print("1: Add a new transaction value") print("2: Mine a new block") print("3: Output the blockchain blocks") print("4: Check transaction validity") print("q: Quit") user_choice = self.get_user_choice() if user_choice == "1": tx_data = self.get_transaction_value() # one possibility is to unpack the tuple by following where the first element of the tuple will be assigned to the first variable (recipient): recipient, amount = tx_data # second possibility is to call the respective elements directly as argument as following: # add_transaction(owner, tx_data[0], tx_data[1]) # skip the optional sender argument my having a named argument of amount #I can check it like that with if since add_transaction returns either True or False if self.blockchain.add_transaction(recipient, self.id, amount=amount): print("Successfully added a transaction!") else: print("Transaction failed!") print(self.blockchain.open_transactions) elif user_choice == "2": #reset the block when successful mined since the transactions are then already processed and shouldn't be processed again self.blockchain.mine_block() elif user_choice == "3": self.print_blockchain_output() elif user_choice == "4": verifier = Verification() if verifier.verify_transactions( self.blockchain.open_transactions, self.blockchain.get_balance): print('All transactions are valid') else: print('There are invalid transactions') elif user_choice == "q": awaiting_input = False else: print( "Input was invalid, please pick one of the values 1 or 2.") """ Check if results of verify_chain (from the returned is_valid) is not True --> because "if verify_chain()" would check if True, which we would need if we want to continue, but here we want to have the case that in case it's false we want to exit the loop """ verifier = Verification() if not verifier.verify_chain(self.blockchain.chain): self.print_blockchain_output() print("Invalid blockchain!") break print('Balance of {}:{:6.2f}'.format( self.id, self.blockchain.get_balance())) print("done!")
def listen_for_input(self): waiting_for_input = True while waiting_for_input: print("Please Select:") print("1. Enter the transaction amount.") print("2. Mine a new block.") print("3. Output the blockchain block") print("4. Check transaction validity") print("q. Quit") user_choice = self.get_user_choice() print() if user_choice == '1': tx_data = self.get_transaction_value() recipient, amount = tx_data # Add the transaction amount to the blockchain. if self.blockchain.add_transaction(recipient, sender=self.id, amount=amount): print("Added Transaction!!") else: print("Transaction Failed!") print(self.blockchain.get_open_transaction()) elif user_choice == '2': self.blockchain.mine_block() elif user_choice == '3': self.print_blockchian_elements() elif user_choice == '4': if Verification.verify_transactions( self.blockchain.get_open_transaction(), self.blockchain.get_balance): print('All transactions are valid!') else: print('There are invalid transactions!') elif user_choice == 'q': waiting_for_input = False else: print("Invalid Input!!") print("Exiting after printing the blocks") self.print_blockchian_elements() break if not Verification.verify_chain(self.blockchain.get_chain()): self.print_blockchian_elements() print("Invalid Blockchain!") break print('Balance of {}: {:6.4f}'.format( self.id, self.blockchain.get_balance())) else: print("User Logged Out!")
def listen_for_input(self): waiting_for_input = True # A while loop for the user input interface # It's a loop that exits once waiting_for_input becomes False or when break is called while waiting_for_input: print('Please choose') print('1: Add a new transaction value') print('2: Mine a new block') print('3: Output the blockchain blocks') print('4: Check transaction validity') print('q: Quit') user_choice = self.get_user_choice() if user_choice == '1': tx_data = self.get_transaction_value() recipient, amount = tx_data # Add the transaction amount to the blockchain if self.blockchain.add_transaction(recipient, self.id, amount=amount): print('Added transaction!') else: print('Transaction failed!') print(self.blockchain.open_transactions) elif user_choice == '2': self.blockchain.mine_block() elif user_choice == '3': self.print_blockchain_elements() elif user_choice == '4': verifier = Verification() if verifier.verify_transactions( self.blockchain.open_transactions, self.blockchain.get_balance): print('All transactions are valid') else: print('There are invalid transactions') elif user_choice == 'q': # This will lead to the loop to exist because it's running condition becomes False waiting_for_input = False else: print('Input was invalid, please pick a value from the list!') verifier = Verification() if not verifier.verify_chain(self.blockchain.chain): self.print_blockchain_elements() print('Invalid blockchain!') # Break out of the loop break print('Balance of {}: {:6.2f}'.format( self.id, self.blockchain.get_balance())) else: print('User left!') print('Done!')
def listen_for_input(self): while True: print('Please choose') print('1: Add a new transcation value') print('2: Mine a new block') print('3: Output the blockchain blocks') print('4: Check transaction validity') print('5: Create wallet') print('6: Load wallet') print('7: Save wallet') print('q: Quit') user_choice = self.get_user_choice() if user_choice == '1': tx_data = self.get_transaction_value() recipient, amount = tx_data signature = self.wallet.sign_transaction(self.wallet.public_key, recipient, amount) if self.blockchain.add_transaction(recipient, self.wallet.public_key, signature, amount=amount): print('Added transaction!') else: print('Transaction failed!') print(self.blockchain.get_open_tx()) elif user_choice == '2': if not self.blockchain.mine_block(): print('No wallet, mining failed!') elif user_choice == '3': self.print_blockchain_elements() elif user_choice == '4': if Verification.verify_transactions(self.blockchain.get_open_tx(), self.blockchain.get_balance): print('All transactions are valid') else: print('There is invalid transaction') elif user_choice == '5': self.wallet.create_key() self.blockchain = Blockchain(self.wallet.public_key) elif user_choice == '6': self.wallet.load_keys() self.blockchain = Blockchain(self.wallet.public_key) elif user_choice == '7': self.wallet.save_keys() elif user_choice == 'q': break else: print('Input was invalid') if not Verification.verify_chain(self.blockchain.get_chain()): self.print_blockchain_elements() print('Invalid blockchain!') break print('Balacne of {}: {:6.2f}'.format(self.wallet.public_key, self.blockchain.get_balance())) else: print('User left!') print('Done!')
def test_broadcasting_block(): timestamp = datetime.utcfromtimestamp(0) node_id = uuid4() w1 = Wallet(test=True) w2 = Wallet(test=True) chain1 = Blockchain(w1.address, node_id, difficulty=1, is_test=True) chain2 = Blockchain(w2.address, node_id, difficulty=1, is_test=True) chain2.chain = chain1.chain assert chain1.chain == chain2.chain details = Details( sender=w1.address, recipient=w2.address, nonce=0, amount=0.5, timestamp=timestamp, public_key=w1.public_key.hex(), ) transaction_1 = w1.sign_transaction(details) assert Verification.verify_chain(chain1.chain) b = chain1.mine_block() result, _ = chain2.add_block(b) assert result assert Verification.verify_chain(chain1.chain) assert Verification.verify_chain(chain2.chain) chain1.add_transaction(transaction_1, is_receiving=True) chain1.mine_block() chain2.add_block(chain1.last_block) assert Verification.verify_chain(chain1.chain) assert Verification.verify_chain(chain2.chain) assert chain1.chain == chain2.chain
def listen_for_input(self): waiting_for_input = True while waiting_for_input: print('Please choose') print('1: Add a new transaction value') print('2: Mine a new block') print('3: Output the blockchain blocks') print('4: Check transaction validity') print('q: Quit') user_choice = self.get_user_choice() if user_choice == '1': tx_data = self.get_transaction_value() recipient, amount = tx_data if self.blockchain.add_transaction(recipient, self.id, amount=amount): print('Added transaction!') else: print('Transaction failed!') print(self.blockchain.get_open_transactions()) elif user_choice == '2': self.blockchain.mine_block() elif user_choice == '3': self.print_blockchain_elements() elif user_choice == '4': if Verification.verify_transactions( self.blockchain.get_open_transactions(), self.blockchain.get_balance): print('All transactions are valid') else: print('There are invalid transactions') # elif user_choice == 'h': # if len(blockchain) >= 1: # blockchain[0] = { # 'previous_hash': hashed_block, # 'index': len(blockchain), # 'transactions': [{'sender': 'Chris', 'recipient': 'Max', 'amount': 100.0}] # } elif user_choice == 'q': waiting_for_input = False else: raise (ValueError( 'Input was invalid, please pick a value from the list!')) print('Choice registered!') if not Verification.verify_chain(self.blockchain.blockchain): self.print_blockchain_elements() print('Invalid blockchain') break print(self.blockchain.get_balance()) print('Done!')
def listen_for_input(self): """ allows user to input choices and complete actions on the blockchain """ waiting_for_input = True while waiting_for_input: print('Please choose') print('1: Add a new transaction value') print('2: Mine a new block') print('3: Output the blockchain blocks') print('4: Check transaction validity') print('q: quit') user_choice = self.get_user_choice() if user_choice == '1': tx_data = self.get_transaction_value() recipient, amount = tx_data if self.blockchain.add_transaction(recipient, self.id, amount=amount): print('Added transaction!') else: print('Transaction failed!') print(self.blockchain.get_open_transactions()) elif user_choice == '2': self.blockchain.mine_block() elif user_choice == '3': self.print_blockchain_elements() elif user_choice == '4': if Verification.verify_transactions( self.blockchain.get_open_transactions(), self.blockchain.get_balance): print('All transactions are valid!') else: print('There are invalid transactions!') elif user_choice == 'q': waiting_for_input = False else: print('Input was invalid, please pick a value from the list!') if not Verification.verify_chain(self.blockchain.chain): self.print_blockchain_elements() print('Invalid blockchain!') break print('Balance of {}: {:6.2f}'.format( self.id, self.blockchain.get_balance())) else: print('User left!') print('Done!')
def listen_for_input(self): continue_loop = True while continue_loop: print('1. Add new transaction') print('2. Mine new block') print('3. Print blockchain') print('4. Check transactions') print('0. Exit') choice = self.get_user_input() if choice == 1: tx_data = self.get_transaction_value() recipient, amount = tx_data if self.blockchain.add_transaction(recipient=recipient, sender=self.node_id, amount=amount): print('Added transaction.') else: print('Transaction failed.') print(self.blockchain.get_open_transactions()) elif choice == 2: if self.blockchain.mine_block(): self.blockchain.save_data() elif choice == 3: self.print_blockchain() elif choice == 4: if Verification.check_transactions( self.blockchain.get_open_transactions(), self.blockchain.get_balance): print('All transactions are valid.') else: print('There are invalid transactions.') elif choice == 0: continue_loop = False else: print('Invalid choice. Please enter 1 - 3') if not Verification.verify_chain(self.blockchain.chain): print('Chain is invalid') break print('Balance of {} is {:6.2f}'.format( self.node_id, self.blockchain.get_balance(self.node_id))) else: print('Goodbye')
def listen_for_input(self): waiting_for_input = True while waiting_for_input: print('Please choose:') print('1: Add new transaction.') print('2: Mine a new block.') print('3: Output the blockchain blocks.') print('4: Check transaction validity.') print('q: Exit') user_choice = self.get_input() if user_choice == '1': tx_data = self.get_transaction_value() recipient, amount = tx_data if self.blockchain.add_transaction(recipient, self.id, amount=amount): print('Added transaction!') else: print('Transaction failed!!!') print(self.blockchain.get_open_transactions()) elif user_choice == '2': self.blockchain.mine_block() elif user_choice == '3': self.output_blockchain() elif user_choice == '4': if Verification.verify_transactions( self.blockchain.get_open_transactions(), self.blockchain.get_balance): print('All transactions are valid.') else: print('There are invalid transactions.') elif user_choice == 'q': waiting_for_input = False else: print('Invalid option. \n') if not Verification.verify_chain(self.blockchain.get_chain()): self.output_blockchain() print('Invalid blockchain!') waiting_for_input = False print("{}'s balance: {:6.2f} \n".format( self.id, self.blockchain.get_balance())) print('Done!')
def test_not_enough_coin(): timestamp = datetime.utcfromtimestamp(0) node_id = uuid4() w = Wallet(test=True) w2 = Wallet(test=True) chain = Blockchain(w.address, node_id, difficulty=1, is_test=True) tx_details = Details( sender=w.address, recipient=w2.address, nonce=0, amount=2995.0, timestamp=timestamp, public_key=w.public_key.hex(), ) transaction = w.sign_transaction(tx_details) assert Verification.verify_chain(chain.chain) try: chain.add_transaction(transaction, is_receiving=True) assert "This was expected to throw a ValueError exception but didn't" except ValueError: pass
def resolve(self): winner_chain = self.chain replace = False for node in self.__peer_nodes: url = 'http://{}/chain'.format(node) try: response = requests.get(url) node_chain = response.json() node_chain = [Block(block['index'], block['previous_hash'], [Transaction( tx['sender'], tx['recipient'], tx['signature'], tx['amount']) for tx in block['transactions']], block['proof'], block['timestamp']) for block in node_chain] node_chain_length = len(node_chain) local_chain_length = len(winner_chain) if node_chain_length > local_chain_length and Verification.verify_chain(node_chain): winner_chain = node_chain replace = True except requests.exceptions.ConnectionError: continue self.resolve_conflicts = False self.chain = winner_chain if replace: self.__open_transactions = [] self.save_data() return replace
node.blockchain.resolve() return jsonify(response), 200 else: response = { 'message': 'Blockchain seems to be shorter, block not added'} node.blockchain.sync(block) return jsonify(response), 409 if __name__=='__main__': from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument('-p', '--port', type=int, default=5000) args = parser.parse_args() port = args.port t1=threading.Thread(target=start_node, args=(port,)) t1.daemon = True t1.start() verifier=Verification() Nkey=Key() #Nkey.assign_key() node=Node(Nkey.key) if not verifier.verify_chain(node.blockchain.get_chain()): print("\nInvalid Blockchain!! Exiting.....\n") exit() node.listen_input() node.blockchain.save_data() exit()
def listen_for_input(self): waiting_for_input = True # A while loop for the user input interface # It's a loop that exits once waiting_for_input becomes False or when while waiting_for_input: print('Please choose') print('1: Add a new transaction value') print('2: Mine a new block') print('3: Output the blockchain blocks') print('4: Check transaction validity') print('5: Create wallet') print('6: Load wallet') print('7: Save keys') print('q: Quit') user_choice = self.get_user_choice() if user_choice == '1': tx_data = self.get_transaction_value() recipient, amount = tx_data # tuple unpacking! # Add the transaction amount to the blockchain signature = self.wallet.sign_transaction( self.wallet.public_key, recipient, amount) if self.blockchain.add_transaction(recipient, self.wallet.public_key, signature, amount=amount): print('Added transaction!') else: print('Transaction failed!') print(self.blockchain.get_open_transactions() ) # testing purpose only! elif user_choice == '2': if not self.blockchain.mine_block(): print('Mining failed. Got no wallet?') elif user_choice == '3': self.print_blockchain_elements() elif user_choice == '4': if Verification.verify_transactions( self.blockchain.get_open_transactions(), self.blockchain.get_balance): print('All transactions are valid') else: print('There are invalid transactions') elif user_choice == '5': self.wallet.create_keys() self.blockchain = Blockchain(self.wallet.public_key) elif user_choice == '6': self.wallet.load_keys() self.blockchain = Blockchain(self.wallet.public_key) elif user_choice == '7': self.wallet.save_keys() elif user_choice == 'q': waiting_for_input = False else: print('Unknown command. Please, enter choice from the list.') if not Verification.verify_chain(self.blockchain.chain): self.print_blockchain_elements() print('Invalid blockchain!') # Break out of the loop break print('Balance of {}: {:6.2f}'.format( self.wallet.public_key, self.blockchain.get_balance())) else: print('User left!') print('Done!')
elif user_choice == '2': if mine_block(): open_transactions = [] save_data() elif user_choice == '3': print_blockchain_elements() elif user_choice == '4': verifier = Verification() if verifier.verify_transactions(open_transactions, get_balance): print('All transactions are valid.') else: print('There are invalid transactions.') elif user_choice == 'q': waiting_for_input = False else: print('Input was invalid, please pick a value from the list!') verifier = Verification() if not verifier.verify_chain(blockchain): print_blockchain_elements() print('Blockchain no longer valid') break print('Balace of {}: {:6.2f}'.format('John', get_balance('John'))) else: print('User left!') print('Done!')
def resolve_conflicts(self) -> bool: """ This is our Consensus Algorithm. It resolves conflicts by replacing our chain with the longest one in the network. :return: <bool> True if our chain was replaces, False if not """ logger.debug("Resolving conflicts between the nodes if applicable") neighbours = self.nodes new_chain = None # We're only looking for chains longer than ours current_chain_length = len(self.chain) # Grab and verify the chains from all the nodes in our network for node in neighbours: response = requests.get(f"{node}/chain") if response.ok: length = response.json()["length"] chain_hashes = response.json()["chain"] chain = [] for b in chain_hashes: response = requests.get(f"{node}/block/{b}") if response.ok: parsed_block = Block.parse_raw(response.json()) chain.append(parsed_block) if (length == 1 and current_chain_length == 1 and Verification.verify_chain(chain)): logger.debug( "Chain's are both 1 length so preferring neighbour's") current_chain_length = length new_chain = chain # Ensure that the chain is sorted by index chain.sort(key=lambda x: x.index, reverse=False) if length <= current_chain_length: logger.warning("Neighbour's chain shorter than our node") continue logger.debug("Neighbour's chain is longer than ours") logger.debug("Verifying neighbour's chain") if not Verification.verify_chain(chain): logger.warning("Neighbour's chain failed verification") continue logger.debug("Neighbour's chain successfully verified") current_chain_length = length new_chain = chain for b in chain: for tx_hash in b.transactions: response = requests.get( f"{node}/transaction/{tx_hash}") if response.ok: t = FinalTransaction.parse_raw( response.json()["transaction"]) FinalTransaction.SaveTransaction( self.data_location, t, response.json()["type"]) # Replace our chain if we discovered a new, valid chain longer than ours if new_chain: logger.info("Replacing our chain with neighbour's chain") self.chain = new_chain Block.DeleteBlocks(self.data_location) else: logger.info("Keeping this node's chain. Now making sure its saved") self.save_data() return new_chain is not None and len(new_chain) > 0