def proof_of_work():
    last_block = blockchain[-1]
    last_hash = get_hash_of_block(last_block)
    proof = 0
    while not is_valid_proof(open_transactions, last_hash, proof):
        proof += 1
    return proof
def mine_block():
    last_block = blockchain[-1]
    hash_of_block = get_hash_of_block(last_block)
    proof = proof_of_work()
    # we are excluding the reward_transaction from proof_of_work()
    # reward_transaction = {
    #     'sender': 'MINING',
    #     'recipient': owner,
    #     'amount': MINIG_REWARD
    # }
    reward_transaction = OrderedDict([('sender', 'MINING'),
                                      ('recipient', owner),
                                      ('amount', MINIG_REWARD)])
    # Copying open transaction just in case the open transaction fails, we should not loose open transactions chain
    copied_transactions = open_transactions[:]
    copied_transactions.append(reward_transaction)
    block = {
        'previous_hash': hash_of_block,
        'index': len(blockchain),
        'transactions': copied_transactions,
        'proof': proof
    }
    blockchain.append(block)
    save_data()
    return True
def verify_chain():
    print(blockchain)
    for (index, block) in enumerate(blockchain):
        if index == 0:
            continue
        print(block)
        if block['previous_hash'] != get_hash_of_block(blockchain[index - 1]):
            return False
        if not is_valid_proof(block['transactions'][:-1],
                              block['previous_hash'], block['proof']):
            print('proof of work is invalid')
            return False
    return True