Exemplo n.º 1
0
    def mine_block(self):
        if self.hosting_node is None:
            return False

        last_block = self.__chain[-1]
        hashed_block = hash_block(last_block)
        # print(hashed_block)
        proof = self.proof_of_work()
        # Miners should be rewarded for there work.
        reward_transaction = Transaction("MINING", self.hosting_node, '',
                                         MINING_REWARD)

        # Copy transaction instead of manipulating the orignal
        # "open_transactions".
        copied_transaction = self.__open_transaction[:]

        for tx in copied_transaction:
            if not Wallet.verify_transaction(tx):
                return False

        copied_transaction.append(reward_transaction)
        block = Block(len(self.__chain), hashed_block, copied_transaction,
                      proof)

        self.__chain.append(block)
        # Resets the open_transaction to an empty list.
        self.__open_transaction = []
        self.save_data()
        return True
Exemplo n.º 2
0
 def mine_block(self, node):
     proof = self.proof_of_work()
     # OrderedDict so that the order of the transactions dicrionary will always be the same.
     reward_transaction = Transaction('MINING', node, '', self.reward)
     # We copy in case our block will be deined, this way we do not override directly our open_transactions.
     copied_transactions = self.open_transactions[:]
     # Verify block transactions
     for tx in copied_transactions:
         if not Wallet.verifty_tx_sign(tx):
             return False
     copied_transactions.append(reward_transaction) # Reward miner transaction
     block = Block(len(self.chain),  hash_block(self.chain[-1]), copied_transactions, proof)
     self.chain.append(block)
     self.open_transactions = []
     self.save_data()
     converted_block = block.__dict__.copy()
     converted_block['transactions'] = [tx.__dict__ for tx in converted_block['transactions']]
     for node in self.peer_nodes:
         try:
             resp = requests.post(f'http://{node}/broadcast-block', json={
                 'block': converted_block
             })
             if resp.status_code == 400 or resp.status_code == 500:
                 print('Block declined, needs resolving')
             if resp.status_code == 409:
                 self.resolve_conflicts = True
         except requests.exceptions.ConnectionError:
             print(f'Peer {node} broadcast-block failed')
             continue
     return block
Exemplo n.º 3
0
    def add_block(self, block):
        # converting the received dictionary transactions to transaction objects
        transactions = [
            Transaction(tx['sender'], tx['recipient'], tx['amount'],
                        tx['signature']) 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)
        # Removing transaction from open_transaction if they are in the mined 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 alredy removed')

        self.save_data()
        return True
Exemplo n.º 4
0
    def mine_block(self):
        # prevent adding transaction when no wallet loaded
        if self.public_key is None:
            return None

        # index [-1] accesses the last block of the chain
        last_block = self.__chain[-1]

        hashed_block = hash_block(last_block)
        # We copy the list open_transaction with the ':' range selector to
        # copy the whole list
        # In complex objects like lists,tuples,sets,dictionary just assigning
        # a new value
        # with '=' just copies the reference. So if we change the copied list
        # it will also be changed in the original
        copied_open_transactions = self.__open_transactions[:]

        # We calculate the proof number without the mining reward.
        # To validate the chain we need to remove the reward_transaction
        # before validating it
        proof = self.proof_of_work()

        # verify each open_transactions signatures. if one signature doesn't
        # verify correctly we abort the mining
        # this is done without the MINING transaction
        for tx in copied_open_transactions:
            if not Wallet.verify_transaction_signature(tx):
                return None

        reward_transaction = Transaction('MINING', self.public_key,
                                         MINING_REWARD, '')
        copied_open_transactions.append(reward_transaction)
        block = Block(len(self.__chain), hashed_block,
                      copied_open_transactions, proof)

        self.__chain.append(block)

        # Empty open transaction files and save the datas
        self.__open_transactions = []
        self.save_data()
        # Broadcasting new block
        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!')
                # when broadcasting block to peers returns a 409 message then
                # set reolve_conflicts. see node.py broadcast_block
                if response.status_code == 409:
                    self.resolve_conflicts = True

            except requests.exceptions.ConnectionError:
                continue

        return block
Exemplo n.º 5
0
 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
     print(f"The proof number is: {proof}")
     return proof
Exemplo n.º 6
0
 def validate_blockchain(cls, blockchain):
     """ Validates the blockchain. """
     is_valid = True
     print("Validating the blockchain...")
     for i, block in enumerate(blockchain):
         if i == 0:
             continue
         else:
             prev_block = blockchain[i - 1]
             prev_block_hash = hash_block(prev_block)
             print(f"[debug]: Comparing current block[{i}] ({block})")
             print(
                 f"[debug]:      and previous block[{i-1}] ({prev_block})")
             print(
                 f"[debug]: Current",
                 f"block[prev_block_hash] == prev_block_hash",
                 f"({block.prev_block_hash} == {prev_block_hash})? ",
                 end="",
             )
             if block.prev_block_hash == prev_block_hash:
                 print(f"{GRN}Match!{NRM}")
             else:
                 print(f"{RED}MIS-MATCH{NRM}!")
                 is_valid = False
             print(f"[debug]: Verifying proof of block[{i}] ({block})")
             print(
                 f"[debug]:   Comparing first {cls.POW_DIGITS} digits",
                 f"to match '{cls.POW_PATTERN}' in the hash created from:",
             )
             txs_without_mining_reward = block.transactions[:-1]
             print(
                 f"[debug]:   Transactions ({txs_without_mining_reward})",
                 f"last block hash ({block.prev_block_hash}) and proof",
                 f"({block.proof})",
             )
             if cls.valid_proof(
                     txs_without_mining_reward,
                     block.prev_block_hash,
                     block.proof,
             ):
                 proof_succeeded = True
             else:
                 proof_succeeded = False
                 is_valid = False
             print()
             guess_str = cls.generate_guess_string(
                 txs_without_mining_reward,
                 block.prev_block_hash,
                 block.proof,
             )
             print(f"[debug]: guess_str: ({guess_str})")
             if proof_succeeded:
                 print(f"[debug]:   Proof {GRN}Succeeded{NRM}!")
             else:
                 print(f"[debug]:   Proof {RED}FAILED{NRM}!")
     return is_valid
Exemplo n.º 7
0
 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
Exemplo n.º 8
0
 def verify_chain(cls, blockchain):
     """Verifies whether the block are matching or not."""
     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
Exemplo n.º 9
0
 def verify_chain(cls, get_balance, difficulty, chain):
     chain_copy = chain[:]
     for idx, block in enumerate(chain_copy):
         if idx > 0:
             if block.previous_hash != hash_block(chain_copy[idx - 1]):
                 return False
             if not cls.valid_proof(block.transactions[:-1],
                                    block.previous_hash, block.proof,
                                    difficulty):
                 return False
             if not all([
                     Verification.verify_tx(tx, get_balance)
                     for tx in block.transactions[:-1]
             ]):
                 return False
     return True
Exemplo n.º 10
0
 def verify_chain(cls, blockchain):
     # With enumerate we change the list to a Tuple so we can unpack it
     # with idx-value pairs
     for (index, block) in enumerate(blockchain):
         if index < 1:
             continue
         if block.previous_hash != hash_block(blockchain[index - 1]):
             print("Previous hash is invalid!")
             return False
         # We remove the last transaction with the range operator [:-1].
         # It's the mining reward
         # When we mine we don't include it in the proof of work
         if not cls.valid_proof(block.transactions[:-1],
                                block.previous_hash, block.proof):
             print("Proof of work is invalid")
             return False
     return True
Exemplo n.º 11
0
 def mine_block(self):
     """ Adds a block of current transactions to the blockchain. """
     if self.hosting_node is None:
         return None
     # reward the miner
     reward_tx = Transaction(MINING_OWNER, self.hosting_node, None,
                             MINING_REWARD)
     # make a copy in order to preserve open_txs
     new_txs = self.__open_txs[:]
     # verify the new transactions before adding the reward transaction
     for tx in new_txs:
         if not Wallet.verify_tx(tx):
             return None
     new_txs.append(reward_tx)
     # add the current transactions
     last_block = self.__chain[-1]
     last_block_hash = hash_block(last_block)
     proof = self.proof_of_work(self.__open_txs, last_block_hash)
     block = Block(len(self.__chain), last_block_hash, proof, new_txs)
     self.__chain.append(block)
     self.__participants.add(self.hosting_node)
     self.__open_txs = []
     self.save_data()
     return block
Exemplo n.º 12
0
 def add_block(self, block):
     txs = [Transaction(tx['sender'], tx['recipient'], tx['signature'], tx['amount']) for tx in block['transactions']]
     # Check proof is correct and previous hashes matches
     # The txs[-1] is so to skip our reward tx because we calculate the proof without it.
     if not Verification.valid_proof(txs[:-1], block['previous_hash'], block['proof'], self.difficulty) or not hash_block(self.chain[-1]) == block['previous_hash']:
         return False
     self.chain.append(Block(block['index'], block['previous_hash'], txs, block['proof'], block['timestamp']))
     
     # If we got a block with some of our opentx's inside we need to remove these open tx's
     stored_txs = self.open_transactions[:]
     for itx in block['transactions']:
         for opentx in stored_txs:
             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
Exemplo n.º 13
0
 def proof_of_work(self):
     proof = 0
     while not Verification.valid_proof(self.open_transactions, hash_block(self.chain[-1]), proof, self.difficulty):
         proof += 1
     return proof