def add_transaction(self, transaction: SignedRawTransaction, is_receiving: bool = False) -> int: """ Creates a new transaction to go into the next mined Block :param transaction: <SignedRawTransaction> A single Transaction :param is_receiving: Optional <bool> Use to determine if the transaction was created by this node or another on the network :return: <int> The index of the Block that will hold this transaction """ if Verification.verify_transaction(transaction, self.get_balance, self.get_last_tx_nonce): final_tx = FinalTransaction( transaction_hash=Verification.hash_transaction(transaction), transaction_id=Verification.hash_transaction(transaction), signed_transaction=transaction, ) self.__open_transactions.append(final_tx) self.save_data() if not is_receiving: self.__broadcast_transaction(transaction, "open") else: raise ValueError( "The sender does not have enough coin to make this " "transaction. We may want to change this to not raise " "an exception later, but for now, we should break.") return self.last_block.index + 1
def add_block(self, block: Block) -> Tuple[bool, Optional[str]]: """ When a new block is received via a broadcast, the receiving nodes must validate the block to make sure it is valid, and then add it to their chains. This also makes sure that there are not open transactions on any of the nodes that match a transaction in the broadcasted block. """ if not Verification.valid_nonce(block.header): return False, "Nonce is not valid" if (not Verification.hash_block_header(self.last_block.header) == block.header.previous_hash): return ( False, "Hash of last block does not equal previous hash in the current block", ) self.add_block_to_chain(block) # Always work off a copy as to not disrupt the current list of open transactions stored_transactions = self.__open_transactions[:] for itx in block.transactions: for opentx in stored_transactions: if opentx.transaction_hash == itx: try: self.__open_transactions.remove(opentx) except ValueError: logger.warning("Item was already removed: %s", opentx) self.save_data() return True, "success"
def add_transaction(self, recipient, sender, amount=1.0): transaction = Transaction(sender, recipient, amount) verifier = Verification() if verifier.verify_transaction(transaction, self.get_balance): self.open_transactions.append(transaction) self.save_data() return True return False
def proof_of_work(self): last_block = self.chain[-1] last_hash = hash_block(last_block) proof = 0 v = Verification() while not v.valid_proof(self.open_transactions, last_hash, proof): proof += 1 return proof
def proof_of_work(): last_block = blockchain[-1] last_hash = hash_block(last_block) proof = 0 verifier = Verification() while not verifier.valid_proof(open_transactions, last_hash, proof): proof += 1 return proof
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 test_correct_nonce(): timestamp = datetime.utcfromtimestamp(0) block_one = Block( index=0, block_hash="", size=0, header=Header( timestamp=timestamp, transaction_merkle_root="", nonce=100, previous_hash="", difficulty=4, version=1, ), transaction_count=0, transactions=[], ) previous_hash = Verification.hash_block_header(block_one.header) open_transactions = [ SignedRawTransaction( details=Details( sender="test2", recipient="test", amount=2.5, nonce=0, timestamp=timestamp, public_key="pub_key", ), signature="sig", ) ] block_header = Header( version=1, difficulty=4, timestamp=datetime.utcfromtimestamp(1), transaction_merkle_root=get_merkle_root(open_transactions), previous_hash=previous_hash, nonce=0, ) block_header = Verification.proof_of_work(block_header) block_two = Block( index=1, block_hash="", size=0, header=block_header, transaction_count=len(open_transactions), transactions=[ Verification.hash_transaction(t) for t in open_transactions ], ) assert Verification.valid_nonce(block_two.header)
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 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 proof_of_work(self): """Increment the proof number""" last_block = self.chain[-1] last_hash = hash_block(last_block) proof = 0 verifier = Verification() while not verifier.valid_proof(self.open_transactions, last_hash, proof): proof += 1 return proof
def broadcast_transaction(): # pylint: disable=unused-variable """ Broadcasts a new transaction to all the nodes Returns a status message Methods ----- POST Parameters ----- transaction : SignedRawTransaction as hex Returns application/json ----- Return code : 201, 400, 500 Response : message : str transaction : optional Transaction as Dict """ values = request.get_json() if not values: response = {"message": "No data found."} return jsonify(response), 400 required = ["transaction", "type"] if not all(key in values for key in required): response = {"message": "Some data is missing."} return jsonify(response), 400 t = SignedRawTransaction.ParseFromHex(values["transaction"]) try: if values["type"] == "mining" or values["type"] == "confirmed": tx = FinalTransaction( transaction_hash=Verification.hash_transaction(t), transaction_id=Verification.hash_transaction(t), signed_transaction=t, ) FinalTransaction.SaveTransaction(blockchain.data_location, tx, values["type"]) response = { "message": f"Successfully saved {values['type']} transaction.", "transaction": values["transaction"], } return jsonify(response), 201 block_index = blockchain.add_transaction(t, is_receiving=True) response = { "message": "Successfully added transaction.", "transaction": values["transaction"], "block": block_index, } return jsonify(response), 201 except ValueError as e: response = { "message": "Creating a transaction failed.", "error": str(e) } return jsonify(response), 500
def add_transaction(recipient, sender=owner, amount=1.0): transaction = Transaction(sender, recipient, amount) verifier = Verification() if verifier.verify_transaction(transaction, get_balance): open_transactions.append(transaction) participants.add(sender) participants.add(recipient) save_data() return True return False
def main(argv=None): verification = Verification() testCases = TestCases(verification) testCases.execute() verification.closeFile() verification.createExecutable() verification.executeFile() verification.debugFile() if not verification.isOk(): sys.exit(1)
def proof_of_work(self): """Generate a proof of work for the open transactions, the hash of the previous block and a random number (which is guessed until it fits).""" last_block = self.chain[-1] last_hash = hash_block(last_block) proof = 0 # Try different PoW numbers and return the first valid one verifier = Verification() while not verifier.valid_proof(self.open_transactions, last_hash, proof): proof += 1 return proof
def listen_for_input(self): """Starts the node and waits for user input.""" 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.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': # 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!') 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.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 createUser(): global cookies #print("fields: ", request.form) UUID = Token_generator.new_crypto_bytes(16).hex() verification_code = Token_generator.new_crypto_bytes(16).hex() username = request.form.get("usernameInput") password = request.form.get("passwordInput") + P_VALUE email = request.form.get("emailInput") forename = request.form.get("forenameInput") surname = request.form.get("surnameInput") DOB = request.form.get("dobInput") ip = request.environ['REMOTE_ADDR'] password_blacklist = [ "uea", "pirate", "cove", "piratecove", "password", "topsecret", "123", "12345", "qwerty", "abc", email, forename, surname, username ] flag, level, mess = checkValidPassword(password, password_blacklist) if flag == False: ret = {"code": level, "reason": mess} return jsonify(ret) captcha_code = request.form.get("g-recaptcha-response") captcha_resp = Verification.verifyCaptchaCode(captcha_code, ip) if captcha_resp == False: ret = {"code": "warning", "reason": "Captcha failed"} return jsonify(ret) print("Passed captcha veri") salt = Token_generator.new_crypto_bytes(20) salted_pwd = pbkdf2(password, salt).digest() x1 = DB_Manager.execute( "ALTER", '''INSERT INTO Users VALUES ('%s', '%s', '%s', '%s', '%s', '%s')''', UUID, username, email, forename, surname, DOB) x2 = DB_Manager.changePassword(username, salted_pwd, salt.hex(), verification_code) if x1 == None or x2 == None: ret = { "code": "warning", "reason": "There was an issue with your request" } return jsonify(ret) else: Verification.sendVerificationEmail(email, forename, verification_code) ret = {"code": "success"} return jsonify(ret) ret = {"code": "warning", "reason": "There was an issue with your request"} return jsonify(ret)
def test_all_values_result_in_64_characters(): short_str = "a short string" assert len(short_str) < 64 assert len(Verification.hash_bytes_256(short_str.encode("utf-8"))) == 64 long_str = ( "a longer than 64 character string in order to test to make sure that" "the result of the hash is still only 64 characters exactly") assert len(long_str) > 64 assert len(Verification.hash_bytes_256(long_str.encode("utf-8"))) == 64
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 add_transaction(recipient, sender=owner, amount=1.0): """ Append a new value as well as the last blockchain value """ # transaction = { # 'sender': sender, # 'recipient': recipient, # 'amount': amount # } transaction = Transaction(sender, recipient, amount) verifier = Verification() if verifier.verify_transaction(transaction, get_balance): open_transactions.append(transaction) save_data() return True return False
def add_block(self, block): transactions = [ Transaction(tx['sender'], tx['recipient'], tx['signature'], tx['amount']) for tx in block['transactions'] ] proof_is_valid = Verification.valid_proof(transactions[:-1], block['previous_hash'], block['proof']) hashes_match = hash_block(self.chain[-1]) == block['previous_hash'] if not proof_is_valid or not hashes_match: return False converted_block = Block(block['index'], block['previous_hash'], transactions, block['proof'], block['timestamp']) self.__chain.append(converted_block) self.save_data() stored_transactions = self.__open_transactions[:] for itx in block['transactions']: for opentx in stored_transactions: if opentx.sender == itx['sender'] and opentx.recipient == itx['recipient'] and\ opentx.amount == itx['amount'] and opentx.signature == itx['signature']: try: self.__open_transactions.remove(opentx) except ValueError: print('Item was already removed') return True
def mine_block(self): if self.public_key is None: return None hashed_block = hash_block(self.__chain[-1]) proof = self.proof_of_work() reward_transaction = Transaction('MINING', self.public_key, '', MINING_REWARD) copied_transactions = self.get_open_transactions() for tx in copied_transactions: if not Verification.verify_transaction(tx): return None copied_transactions.append(reward_transaction) block = Block(index=len(self.__chain), previous_hash=hashed_block, transactions=copied_transactions, proof=proof) self.__chain.append(block) self.__open_transactions = [] self.save_data() for node in self.__peer_nodes: converted_block = block.__dict__.copy() converted_block['transactions'] = [ tx.__dict__ for tx in converted_block['transactions'] ] url = 'http://{}/broadcast-block'.format(node) try: response = requests.post(url, json={'block': converted_block}) if response.status_code == 500 or response.status_code == 400: print('Block declined, need resolving') except requests.ConnectionError: continue return block
def add_transaction(self, sender, recipient, signature, amount=1, is_receiving=False): transaction = Transaction(sender, recipient, signature, amount) if Verification().checking_transaction(transaction=transaction, get_balance=self.get_balance): self.__open_transactions.append(transaction) self.save_data() if not is_receiving: for node in self.__peer_nodes: url = 'http://{}/broadcast-transaction'.format(node) try: response = requests.post(url, json={ 'sender': sender, 'recipient': recipient, 'signature': signature, 'amount': amount }) if response.status_code == 400 or response.status_code == 500: print('Transaction declined, needs resolving') return False except requests.ConnectionError: continue return True return False
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 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_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 add_transaction(self, recipient, sender, amount=1.0): """ append a new value and last BC value to BC Arguments: :sender: the sender of the coins. :recipient: the recipient of the coins. :amount: the amount of coins sent with the transaction (default=1.0) """ transaction = Transaction(sender, recipient, amount) verifier = Verification() if verifier.verify_transaction(transaction, self.get_balance): self.open_transactions.append(transaction) #Benefit of sets is here that if we add another Sophia which is already in the set it will ignore that #Hence sets make sure that we have only unique values in the set self.save_data() return True return False
def proof_of_work(self): last_block = self.__chain[-1] last_hash = hash_util.hash_block(last_block) proof = 0 while not Verification.valid_proof(self.__open_transactions, last_hash, proof): proof += 1 return proof
def changePassword(): usr_cookie = request.cookies.get("S_ID") ip = request.environ['REMOTE_ADDR'] user_UUID = cookies.getUUID(usr_cookie, ip) csrf_token = request.form.get("token") if user_UUID == None: return logoutResponse({ "code": "danger", "reason": "You have been automatically logged out. Please log in again." }) captcha_code = request.form.get("g-recaptcha-response") captcha_resp = Verification.verifyCaptchaCode(captcha_code, ip) if captcha_resp != True: ret = {"code": "warning", "reason": "Captcha failed"} return jsonify(ret) elif not cookies.validateCSRF(usr_cookie, csrf_token): ret = {"code": "warning", "reason": "CSRF Error."} else: old_password = request.form.get("old_p") + P_VALUE new_password = request.form.get("new_p") + P_VALUE veri_password = request.form.get("ver_p") + P_VALUE if new_password != veri_password: ret = {"code": "warning", "reason": "New passwords do not match"} else: username = DB_Manager.getUsername(user_UUID) u_salt = DB_Manager.execute( "AUTH", '''SELECT salt FROM User_Auth WHERE (UUID = '%s');''', user_UUID) if (len(u_salt) == 0): ret = {"code": "warning", "reason": "Unknown error"} else: u_salt = u_salt[0][0] u_salt = bytearray.fromhex(u_salt) e_password = pbkdf2(old_password, u_salt).digest() if DB_Manager.authenticateUser(username, e_password) == True: new_salt = Token_generator.new_crypto_bytes(20) salted_pwd = pbkdf2(new_password, new_salt).digest() veri_code = Token_generator.new_crypto_bytes(16).hex() x2 = DB_Manager.changePassword(username, salted_pwd, new_salt.hex(), veri_code) if x2 == None: ret = { "code": "warning", "reason": "Error with new password" } else: ret = {"code": "success"} else: ret = {"code": "warning", "reason": "Old password incorrect."} return jsonify(ret)
def proof_of_work(self): """ Initiates the proof of work function to allow mining """ last_block = self.__chain[-1] last_hash = hash_block(last_block) proof = 0 while not Verification.valid_proof(self.__open_transactions, last_hash, proof): proof += 1 return proof
def proof_of_work(self): last_block = self.__chain[-1] last_hash = hash_block(last_block) proof = 0 while not Verification.valid_proof(self.__open_transaction, last_hash, proof): proof += 1 # Printing the number of hashes done to check the proof. print(proof) return proof