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) 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.') self.save_data() return True
def mine_block(self): """Create a new block and add open transactions to it.""" if self.hosting_node == None: return None # grab the the last hashed block last_block = self.__chain[-1] # hash the last block inorder to use it in the stored hash value hashed_block = hash_block( last_block ) # pass in the last block to hash it and set to be passed to newly mined block proof = self.proof_of_work() reward_transaction = Transaction('Mining', self.hosting_node, '', MINING_REWARD) # Copy transaction instead of manipulating the original open_transactions list # This ensures that if for some reason the mining should fail, we don't have the reward transaction stored in the open transactions # create a shallow copy of the open transactions copied_transactions = self.__open_transactions[:] # verify all transactions during mining for tx in copied_transactions: if not Wallet.verify_transaction(tx): return None # append the mining reward transaction to all current open txns copied_transactions.append(reward_transaction) # create the new block object block = Block(len(self.__chain), hashed_block, copied_transactions, proof) #append new block to the blockchain self.__chain.append(block) self.__open_transactions = [] self.save_data() return block
def mine_block(self): if self.public_key == None: return None '''create a new block and add open transactions to it''' last_block = self.__chain[-1] hashed_block = hash_block(last_block) proof = self.proof_of_work() # miners are to be rewarded reward_transaction = Transaction('MINING', self.public_key, '', MINING_REWARD) copied_transactions = self.__open_transactions[:] for tx in copied_transactions: if not Wallet.verify_transaction(tx): return None copied_transactions.append(reward_transaction) block = Block(len(self.__chain), hashed_block, copied_transactions, proof) self.__chain.append(block) self.__open_transactions = [] self.save_data() for node in self.__peer_nodes: url = 'http://{}/broadcast-block'.format(node) converted_block = block.__dict__.copy() converted_block['transactions'] = [ tx.__dict__ for tx in converted_block['transactions'] ] try: response = requests.post(url, json={'block': converted_block}) if response.status_code == 400 or response.status_code == 500: print('Block declined, needs resolving') if response.status_code == 409: self.resolve_conflicts = True except requests.exceptions.ConnectionError: continue return block
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_transactions, last_hash, proof): proof += 1 return proof
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 while not Verification.valid_proof(self.__open_transactions, last_hash, proof): proof += 1 return proof
def verify_chain(cls, blockchain): '''Verify if chain is still valid''' for (index, block) in enumerate(blockchain): if index == 0: continue if block.previous_hash != hash_block(blockchain[index - 1]): return False if not cls.valid_proof(block.transactions[:-1], block.previous_hash, block.proof): print('Proof of work is invalid') return False return True
def verify_chain(cls, blockchain): """ Verify the current blockchain and return True if it's valid, False otherwise.""" # loop through each block and compare each available block for (index, block) in enumerate( blockchain ): # Generate a destructured tuple with enumerate function if index == 0: continue # skip the validation of the genesis block if block.previous_hash != hash_block(blockchain[index - 1]): return False if not cls.valid_proof(block.transactions[:-1], block.previous_hash, block.proof): print("Proof of work is invalid") return False return True # return true to continue process if all blocks are valid