예제 #1
0
def getBlockchain(my_peers):

    block_num = 0
    peer = 'https://iitkbucks.pclub.in'
    r = requests.get(peer + '/getBlock/0')
    #print(r.content)
    #block0 = open('block0', 'rb').read()
    genesis_block = block()
    genesis_block.from_bytes(r.content)
    #genesis_block.from_bytes(block0)
    my_Blockchain = Blockchain(my_peers)
    my_Blockchain.block_reward = genesis_block.transactions[0].outputs[0].amount
    flag = my_Blockchain.addBlock(genesis_block)
    block_num += 1
    flag = True
    
    while flag:
        #peer = random.choice(my_peers)
        r = requests.get(peer + '/getBlock/' + str(block_num))
        if r.status_code == 200:
            nblock = block()
            nblock.from_bytes(r.content)
            flag = my_Blockchain.addBlock(nblock) 
            if flag == 0: flag = True
            block_num += 1
        else:
            flag = False
    
    return my_Blockchain
예제 #2
0
 def setUp(self):
     self.blockchain = Blockchain()
     self.buffer = Buffer(self.blockchain)
     self.buffer.add('1 transaction')
     self.buffer.generate_block()
     self.buffer.add('2 transaction')
     self.buffer.generate_block()
     self.buffer.add('3 transaction')
     self.buffer.generate_block()
     self.blockchain.save_chain()
예제 #3
0
    def get(self):
        idx = int(request.args.get('idx'))
        with self.node.resolve_lock:
            blockchain = Blockchain(
                self.node.blockchain.block_list[idx:]).to_dict()['block_list']

        return json.dumps({'blockchain': blockchain}), 200
예제 #4
0
def Worker(Blockchain, queueflag):

    print('\nSTARTED WORKER THREAD!')

    PUBLICKEY = open('my_pk.pem', 'rb').read()

    while True:
        while not len(Blockchain.PendingTxns._list_) > 0:
            time.sleep(5)
            print('\nWaiting......')
            #Blockchain.PendingTxns.get(Blockchain.peers, Blockchain.unused_outputs)

        #Blockchain.PendingTxns.sort(Blockchain.unused_outputs)
        accumulator = bytes()
        BlockFees = 0
        num_txns = 1

        unused_outputs = copy.deepcopy(Blockchain.unused_outputs)
        flag = True
        for i, txn in enumerate(Blockchain.PendingTxns._list_):
            flag, unused_outputs = txn.VerifyTxn(unused_outputs)
            if flag:
                accumulator += (txn.size + txn._bytes_)
                if not len(accumulator) < 10**6 - 520:
                    accumulator -= (txn.size + txn._bytes_)
                    break
                else:
                    BlockFees += txn.getTxnFees(Blockchain.unused_outputs)
                    num_txns += 1

        coinbase_output = Output(BlockFees + Blockchain.block_reward,
                                 PUBLICKEY)
        coinbase = Tx()
        coinbase.newTxn([], [coinbase_output])
        body = num_txns.to_bytes(
            4, 'big') + coinbase.size + coinbase._bytes_ + accumulator

        my_block = block()
        my_block.new(Blockchain, body)

        flag = my_block.mine(queueflag)
        if flag:
            Blockchain.addBlock(my_block)
        else:
            return False
예제 #5
0
    def inform_bootstrap(self):
        url = 'http://' + self.bootstrap_ip + ':' + self.bootstrap_port + '/hello_bootstrap'
        while True:
            try:
                response = r.post(url,
                                  data={'node': json.dumps(self.node_dict)})
                code = response.status_code
            except r.exceptions.RequestException as e:
                print(e)
                code = 404
            if code != 404: break
            else: sleep(3)
        if response.status_code != 200:
            print('Bootstrap says: "' + json.loads(response.json())['msg'] +
                  '"')
            exit()
        else:
            response = json.loads(response.json())
            self.id = response['id']
            self.blockchain = Blockchain(response['blockchain']['block_list'])
            self.node_dict['utxos'] = OrderedDict(response['utxos'])
            print("I am in with id " + str(self.id))

            valid, msg = self.blockchain.validate(self.difficulty)
            if not valid:
                print(msg)
                exit()
            while True:
                try:
                    response = r.get('http://' + self.bootstrap_ip + ':' +
                                     self.bootstrap_port + '/broadcast_ring',
                                     params={'idx': self.id})
                    code = response.status_code
                except r.exceptions.RequestException as e:
                    print(e)
                    code = 401
                sleep(3)
                if code == 200: break
            if self.transactions:
                self.start_transactions()
예제 #6
0
def connect():
    global node
    if (not node):
        print(request.host)
        port = request.host.split(':', 1)[1]
        print(port)
        if (port == BOOTSTRAP_PORT):
            node = Node(HOST, port, index=0)
            node.wallet = node.create_wallet()
            node.NBCs.append({
                'id': '0',
                'recipient_address': node.wallet.public_key,
                'amount': NUM_OF_NODES * 100
            })
            node.ring.append({
                'id': node.index,
                'port': port,
                'public_key': node.wallet.public_key
            })
            print("Bootstrap node successfully added!")
            print("My id: " + str(node.index))
        else:
            node = Node(HOST, port)
            node.wallet = node.create_wallet()
            response = requests.get("http://" + HOST + ":" + BOOTSTRAP_PORT +
                                    "/init_node?port=" + port +
                                    "&public_key=" + node.wallet.public_key)
            if (response.status_code == 200):
                nid = response.json()['id']
                node.index = int(nid)
                blockchain_json = response.json()['blockchain']
                node.chain = Blockchain(
                    node.index, blockchain_json['unconfirmed_transactions'],
                    blockchain_json['chain'])
                response = requests.post("http://" + HOST + ":" +
                                         BOOTSTRAP_PORT +
                                         "/first_transaction?id=" + str(nid))
                if (response.status_code == 200):
                    output = response.json()['output']
                    node.NBCs.append(output)
                    print("Median node added successfully!")
        if (node.index == NUM_OF_NODES - 1):
            print("Oops! It was the last one!")
            response = requests.post("http://" + HOST + ":" + BOOTSTRAP_PORT +
                                     "/nodes_ready")

            #for node in other_nodes:
            #node.ring=bootstrap_node.ring
        return "Node Added! Your port is: " + port, 201
    else:
        return "Homepage!", 200
예제 #7
0
 def resolve_conflicts(self):
     success, conflict_data = self.broadcast(data={},
                                             endpoint='/resolve_conflict')
     if success:
         conflict_data.sort(key=lambda x: x[0], reverse=True)
         for length, hashchain, node_index in conflict_data:
             if length <= self.blockchain.length():
                 break
             idx = self.blockchain.index_of_fork(hashchain)
             try:
                 response = r.get('http://' + self.ring[node_index]['ip'] +
                                  ':' + self.ring[node_index]['port'] +
                                  '/resolve_conflict',
                                  params={'idx': idx})
             except r.exceptions.RequestException as e:
                 continue
             rest_of_the_blockchain = json.loads(
                 response.json())['blockchain']
             blockchain = Blockchain(self.blockchain.block_list[:idx] +
                                     rest_of_the_blockchain,
                                     update_time=False)
             if blockchain.validate(self.difficulty)[0]:
                 if self.mining_thread and self.mining_thread.is_alive():
                     self.mining_thread.hash_found.set()
                 with self.resolve_lock:
                     old_txs = self.blockchain.all_transactions(idx)
                     new_txs = self.blockchain.all_transactions()
                     self.blockchain = blockchain
                     with self.utxo_lock:
                         with self.tx_pool_lock:
                             self.ring = self.resolve_tx(old_txs=old_txs,
                                                         new_txs=new_txs,
                                                         resolve=True)[1]
                 return 200, ", node " + str(
                     node_index) + " gave me the correct blockchain"
         return 200, ", but it was just a false alarm, I have the largest valid blockchain"
     else:
         return 400, ", I couldn't ask all nodes to resolve the conflict"
예제 #8
0
파일: node.py 프로젝트: Eleniii/Blockchain
    def __init__(self, ip, port, index=None, chain=None):
        self.index = index
        if (index == 0):
            self.chain = Blockchain(index)
            self.current_id_count = self.index + 1

        else:
            self.chain = chain

        self.NBCs = []
        self.ip = ip
        self.port = port
        self.wallet = None
        self.ring = []
예제 #9
0
class TestIntegrity(TestCase):
    def setUp(self):
        self.blockchain = Blockchain()
        self.buffer = Buffer(self.blockchain)
        self.buffer.add('1 transaction')
        self.buffer.generate_block()
        self.buffer.add('2 transaction')
        self.buffer.generate_block()
        self.buffer.add('3 transaction')
        self.buffer.generate_block()
        self.blockchain.save_chain()

    # fixme - this test overwrites blockchain.txt
    def test_edit_one_block(self):
        self.blockchain._blocks[1]._transactions[0] = 'aaa'
        self.assertEqual(self.blockchain.check_integrity(), False)
        self.assertEqual(self.blockchain.save_chain(), 'Inconsistent blockchain')

    # fixme - this test overwrites blockchain.txt
    def test_add_new_block(self):
        self.buffer.add('4 transaction')
        self.buffer.generate_block()
        self.assertEqual(self.blockchain.check_integrity(), True)
        self.assertEqual(self.blockchain.save_chain(), None)
예제 #10
0
from block import Blockchain, Buffer

if __name__ == '__main__':
    blockchain = Blockchain()
    buffer = Buffer(blockchain)
    blockchain.load_chain()
    help_text = '''
add \t- add transaction to the buffer
buf \t- show the buffer
gen \t- generate block from transactions in buffer and clean buffer
get \t- get the specific block
stat \t- statistics for blockchain
write \t- write blockchain to disk
load \t- load blockchain from disk
exit \t- close program'''
    s = ''
    print('Type "help" to see all options')
    while s != 'exit':
        s = input('>>> ')

        if s == 'help':
            print(help_text)

        if s == 'add':
            add_s = input('Transaction: ')
            buffer.add(add_s)
            print(f'Transaction "{add_s}" was added to the buffer.')

        if s == 'buf':
            print('TRANSACTIONS IN THE BUFFER:')
            buffer.show()
예제 #11
0
 def i_am_bootstrap(self):
     self.id = 0
     self.node_dict['utxos'] = OrderedDict()
     self.ring = OrderedDict({self.id: self.node_dict})
     self.blockchain = Blockchain([self.genesis_block()])
예제 #12
0
    # get global testset by train
    global_x_test = x_train[:num_global_testset]
    global_y_test = y_train[:num_global_testset]
    x_train = x_train[num_global_testset:]
    y_train = y_train[num_global_testset:]

    """set FL model"""
    flmodel = create_model(features)

    """set blockchain"""
    if preTrained == -1:
        file_list = os.listdir("./data/blocks")
        preTrained = len(file_list) - 1
        genesis = readBlock("./data/blocks", 0)
        flchain = Blockchain(genesis)  # set blockchain with genesis block
        for i in range(1, preTrained + 1):
            flblock = readBlock("./data/blocks", i)
            flchain.append(flblock)  # append next block
    elif preTrained == 0:
        init_weights = flmodel.get_weights()
        genesis = Block(
            0,
            "0" * 64,
            init_weights,
            (global_x_test, global_y_test),
            [],
            int(time.time())
        )
        flchain = Blockchain(genesis)  # set blockchain with genesis block
        # writeBlockchain("./data", flchain)  # save blockchain
예제 #13
0
def sessions():
    global node
    print("Let's go!")
    if (not node):
        print(request.host)
        ip = request.host.split(':', 1)[0]
        port = request.host.split(':', 1)[1]
        if (ip == BOOTSTRAP_IP and port == BOOTSTRAP_PORT):
            node = Node(ip, port, index=0)
            node.wallet = node.create_wallet()
            node.NBCs.append({
                'id': '0',
                'recipient_address': node.wallet.public_key,
                'amount': NUM_OF_NODES * 100
            })
            node.ring.append({
                'id': node.index,
                'ip': ip,
                'port': port,
                'public_key': node.wallet.public_key
            })
            print("Bootstrap node successfully added!")
            print("My id: " + str(node.index))
        else:
            node = Node(ip, port)
            node.wallet = node.create_wallet()
            while True:
                response = requests.get("http://" + BOOTSTRAP_IP + ":" +
                                        BOOTSTRAP_PORT + "/init_node?ip=" +
                                        ip + "&port=" + port + "&public_key=" +
                                        node.wallet.public_key)
                if response.status_code != 503:
                    break
            if (response.status_code == 200):
                nid = response.json()['id']
                node.index = int(nid)
                blockchain_json = response.json()['blockchain']
                node.chain = Blockchain(
                    node.index, blockchain_json['unconfirmed_transactions'],
                    blockchain_json['chain'])
                if (node.valid_chain()):
                    print("I got a valid blockchain!")
                else:
                    print("My first blockchain is false :( ")
                while True:
                    response = requests.post("http://" + BOOTSTRAP_IP + ":" +
                                             BOOTSTRAP_PORT +
                                             "/first_transaction?id=" +
                                             str(nid))
                    if response.status_code != 503:
                        break
                if (response.status_code == 200):
                    output = response.json()['output']
                    node.NBCs.append(output)
                    print("Median node added successfully!")
        if (node.index == NUM_OF_NODES - 1):
            print("Oops! It was the last one!")
            while True:
                response = requests.post("http://" + BOOTSTRAP_IP + ":" +
                                         BOOTSTRAP_PORT + "/nodes_ready")
                if response.status_code != 503:
                    break
    return render_template('homepage.html'), 200
예제 #14
0
 def setUp(self):
     self.blockchain = Blockchain()
     self.buffer = Buffer(self.blockchain)
예제 #15
0
from flask import Flask
from flask import request
from block import Block
from block import Blockchain
import copy
import datetime as time
import json

node = Flask(__name__)

this_node_transactions = []
peer_nodes = [
    "localhost:5000",
]
mining = True
this_chain = Blockchain()


@node.route("/txion", methods=['POST'])
def transaction():
    if request.method == 'POST':
        new_txion = request.get_json()
        this_node_transactions.append(new_txion)
        print("New transaction")
        print("FROM: {}".format(new_txion['from']))
        print("TO: {}".format(new_txion['to']))
        print("AMOUNT: {}".format(new_txion['amount']))
        return "Transction submission successful\n"


miner_address = "q3nf394hjg-random-miner-address-34nf3i4nflkn3oi"
예제 #16
0
#!/usr/local/bin/python python
# -*- coding: UTF-8 -*-
from uuid import uuid4
from flask import Flask, jsonify, request
from flask_cors import CORS
from block import Blockchain

# ノードを作る
# Flaskについて詳しくはこちらを読んでほしい http://flask.pocoo.org/docs/0.12/quickstart/#a-minimal-application
app = Flask(__name__)
CORS(app, supports_credentials=True)
# このノードのグローバルにユニークなアドレスを作る
node_identifire = str(uuid4()).replace('-', '')
# ブロックチェーンクラスをインスタンス化する
blockchain = Blockchain()


# メソッドはGETで/mineエンドポイントを作る
@app.route('/mine', methods=['GET'])
def mine():
    # 次のプルーフを見つけるためプルーフ・オブ・ワークアルゴリズムを使用する
    last_block = blockchain.last_block
    last_proof = last_block['proof']
    proof = blockchain.proof_of_work(last_proof)

    # プルーフを見つけたことに対する報酬を得る
    # 送信者は、採掘者が新しいコインを採掘したことを表すために"0"とする
    blockchain.new_transaction(
        sender="0",
        recipient=node_identifire,
        amount=1,
예제 #17
0
class Node:
    def __init__(self, ip, port, is_bootstrap, max_nodes, NBC, capacity,
                 difficulty, bootstrap_ip, bootstrap_port, transactions):
        self.ip = ip
        self.port = port
        self.bootstrap = is_bootstrap
        self.max_nodes = max_nodes
        self.NBC = NBC
        self.capacity = capacity
        self.difficulty = difficulty
        self.bootstrap_ip = bootstrap_ip
        self.bootstrap_port = bootstrap_port
        self.transactions = transactions

        self.ring = {}
        self.wallet = Wallet()
        self.tx_pool = []
        self.node_dict = {
            'ip': self.ip,
            'port': self.port,
            'address': self.wallet.address,
            'ready': False
        }

        self.mining_thread = None
        self.utxo_lock = Lock()
        self.tx_pool_lock = Lock()
        self.chain_lock = Lock()
        self.resolve_lock = Lock()

        if self.bootstrap:
            self.i_am_bootstrap()
        else:
            t = Thread(target=self.inform_bootstrap)
            t.start()

    def i_am_bootstrap(self):
        self.id = 0
        self.node_dict['utxos'] = OrderedDict()
        self.ring = OrderedDict({self.id: self.node_dict})
        self.blockchain = Blockchain([self.genesis_block()])

    def genesis_block(self):
        amount = self.NBC * self.max_nodes
        transactions = [
            Transaction(sender_address='0',
                        sender_private_key=None,
                        receiver_address=self.wallet.address,
                        amount=amount,
                        ring=self.ring).to_dict()
        ]

        return Block(idx=0,
                     transactions=transactions,
                     previous_hash='1',
                     nonce='0')

    def inform_bootstrap(self):
        url = 'http://' + self.bootstrap_ip + ':' + self.bootstrap_port + '/hello_bootstrap'
        while True:
            try:
                response = r.post(url,
                                  data={'node': json.dumps(self.node_dict)})
                code = response.status_code
            except r.exceptions.RequestException as e:
                print(e)
                code = 404
            if code != 404: break
            else: sleep(3)
        if response.status_code != 200:
            print('Bootstrap says: "' + json.loads(response.json())['msg'] +
                  '"')
            exit()
        else:
            response = json.loads(response.json())
            self.id = response['id']
            self.blockchain = Blockchain(response['blockchain']['block_list'])
            self.node_dict['utxos'] = OrderedDict(response['utxos'])
            print("I am in with id " + str(self.id))

            valid, msg = self.blockchain.validate(self.difficulty)
            if not valid:
                print(msg)
                exit()
            while True:
                try:
                    response = r.get('http://' + self.bootstrap_ip + ':' +
                                     self.bootstrap_port + '/broadcast_ring',
                                     params={'idx': self.id})
                    code = response.status_code
                except r.exceptions.RequestException as e:
                    print(e)
                    code = 401
                sleep(3)
                if code == 200: break
            if self.transactions:
                self.start_transactions()

    def node_already_exists(self, new_node):
        msg = None
        for node in self.ring.values():
            if new_node['ip'] == node['ip'] and new_node['port'] == node[
                    'port']:
                msg = "You are already in with another wallet"
            if new_node['address'] == node['address']:
                msg = "I already have your wallet's address"
        return msg

    def register_node_to_ring(self, node_dict):
        if not self.bootstrap:
            return 400, "I am sorry, bootstrap is not here", None, None, None
        if self.max_nodes == len(self.ring):
            return 400, "Sorry we are full, " + str(
                self.max_nodes) + " nodes at a time", None, None, None
        msg = self.node_already_exists(node_dict)
        if msg:
            return 400, msg, None, None, None

        idx = len(self.ring)
        node_dict['utxos'] = OrderedDict()
        self.ring[idx] = node_dict
        success, error = self.create_transaction(node_dict['address'],
                                                 self.NBC)
        if not success:
            return 400, error, None, None, None
        else:
            return 200, "OK", idx, self.blockchain.to_dict(
            ), self.ring[idx]['utxos']

    def broadcast(self, data, endpoint):
        node_list = [
            node for node_id, node in self.ring.items()
            if node_id != self.id and node['ready']
        ]
        num_of_nodes = len(node_list)
        if num_of_nodes == 0:
            return True, []
        url_list = [
            'http://' + node['ip'] + ':' + node['port'] + endpoint
            for node in node_list
        ]
        data_list = [data] * num_of_nodes

        p = Pool(num_of_nodes)

        try:
            successes, msg_list = list(
                zip(*p.starmap(send_stuff, zip(url_list, data_list))))
            p.close()
            p.join()
        except r.exceptions.RequestException as e:
            print(e)
            p.close()
            p.join()
            exit()

        successful = sum(successes) == num_of_nodes
        return successful, list(msg_list)

    def broadcast_ring(self):
        while len([node for node in self.ring.values() if node['ready']
                   ]) != self.max_nodes - 1:
            print("Waiting for all nodes to get in")
            sleep(3)
        ring = self.ring.copy()
        ring[0]['ready'] = True
        success, msg_list = self.broadcast(data={'ring': json.dumps(ring)},
                                           endpoint='/broadcast_ring')
        if not success:
            print("Failed broadcasting ring")
            exit()
        else:
            print("All nodes are informed, let\'s start")
            if self.transactions:
                t = Thread(target=self.start_transactions)
                t.start()
            self.ring[0]['ready'] = True

    def broadcast_transaction(self, tx_dict):
        success, msg_list = self.broadcast(data={'tx': json.dumps(tx_dict)},
                                           endpoint='/validate_transaction')
        if success:
            msg = ("All nodes know about transaction now")
        else:
            msg = "Failed broadcasting transaction"
            for m in msg_list:
                print(m)

        return success, msg

    def broadcast_block(self, block_dict):
        success, msg_list = self.broadcast(
            data={'block': json.dumps(block_dict)}, endpoint='/validate_block')
        if success:
            msg = ("All nodes know about block " + str(block_dict['idx']) +
                   " now")
        else:
            msg = "Failed broadcasting block"
            for m in msg_list:
                print(m)

        return success, msg

    def start_transactions(self):
        filename = os.path.join('transactions',
                                str(self.max_nodes) + 'nodes',
                                'transactions' + str(self.id) + '.txt')
        with open(filename, 'r') as tx_file:
            txs = tx_file.readlines()
        start_time = time()
        successes = []
        for tx in txs:
            recipient = self.ring[int(tx.split()[0].strip('id'))]['address']
            amount = int(tx.split()[1])
            success, msg = self.create_transaction(recipient, amount)
            print(msg)
            successes.append(success)
        sful = sum(successes)
        end_time = time()
        dirname = os.path.join('results', str(self.max_nodes) + 'nodes')
        Path(dirname).mkdir(parents=True, exist_ok=True)
        filename = os.path.join(
            dirname, 'tx_' + str(self.id) + '_' + str(self.capacity) + '_' +
            str(self.difficulty) + '.txt')
        with open(filename, 'w') as file:
            file.write(
                str(sful) + ' Transactions in ' + str(end_time - start_time) +
                ' seconds, ' + str(len(txs) - sful) + ' failed\n')

    def create_transaction(self, recipient, amount):
        try:
            self.utxo_lock.acquire()
            tx_dict = Transaction(sender_address=self.wallet.address,
                                  sender_private_key=self.wallet.private_key,
                                  receiver_address=recipient,
                                  amount=amount,
                                  ring=self.ring).to_dict()
        except ValueError as e:
            self.utxo_lock.release()
            return False, str(e)

        self.utxo_lock.release()
        s, m = self.broadcast_transaction(tx_dict)
        self.add_transaction_to_pool(tx_dict)
        return s, m

    def add_transaction_to_pool(self, tx_dict):
        with self.tx_pool_lock:
            if tx_dict not in self.tx_pool + self.blockchain.all_transactions(
            ):
                self.tx_pool.append(tx_dict)
            poolsize = len(self.tx_pool)
            transactions = self.tx_pool[:self.capacity]
        if poolsize >= self.capacity:
            if (not self.mining_thread
                    or not self.mining_thread.is_alive()) and self.ring:
                self.create_new_block(transactions)

    def create_new_block(self, transactions):
        with self.chain_lock:
            next_index = self.blockchain.next_index()
            last_hash = self.blockchain.last_hash()
            if [
                    tx for tx in transactions
                    if tx in self.blockchain.all_transactions()
            ]:
                return
            block = Block(idx=next_index,
                          transactions=transactions,
                          previous_hash=last_hash)
        self.mining_thread = Mining(node=self, block=block)
        self.mining_thread.start()
        return

    def validate_transaction(self, tx_dict):
        try:
            self.utxo_lock.acquire()
            tx = Transaction(sender_address=tx_dict['sender_address'],
                             sender_private_key=None,
                             receiver_address=tx_dict['receiver_address'],
                             amount=tx_dict['amount'],
                             ring=self.ring,
                             signature=tx_dict['signature'],
                             inputs=tx_dict['inputs'],
                             outputs=tx_dict['outputs'],
                             tx_id=tx_dict['transaction_id'])
        except ValueError as e:
            self.utxo_lock.release()
            return 400, str(e)

        self.utxo_lock.release()
        self.add_transaction_to_pool(tx_dict)
        return 200, "Transaction validated"

    def validate_block(self, block_dict):
        block = Block(idx=block_dict['idx'],
                      transactions=block_dict['transactions'],
                      previous_hash=block_dict['prev_hash'],
                      nonce=block_dict['nonce'],
                      hash_=block_dict['hash'],
                      timestamp=block_dict['timestamp'],
                      start_time=block_dict['start_time'])
        if not hasattr(self, 'blockchain'):
            return 200, "I just came here, what are you expecting me to say?"
        self.chain_lock.acquire()
        valid, msg = block.validate(self.difficulty,
                                    self.blockchain.last_hash())
        if valid:
            # if self.ring:
            # 	with self.utxo_lock:
            # 		with self.tx_pool_lock:
            # 			if not self.resolve_tx(new_txs=block.transactions)[0]:
            # 				self.chain_lock.release()
            # 				return 400, "Block contains invalid transactions"
            with self.tx_pool_lock:
                self.tx_pool = [
                    tx for tx in self.tx_pool
                    if not tx in block_dict['transactions']
                ]
            if self.mining_thread and self.mining_thread.is_alive():
                self.mining_thread.hash_found.set()
            self.blockchain.add_block(block)
            self.chain_lock.release()
            return 200, msg
        elif "Previous hash does not match" in msg:
            if block in self.blockchain.block_list:
                self.chain_lock.release()
                return 200, msg + ", but I already have this block"
            code, resolve_msg = self.resolve_conflicts()
            self.chain_lock.release()
            return code, msg + resolve_msg
        else:
            self.chain_lock.release()
            return 400, msg

    def resolve_conflicts(self):
        success, conflict_data = self.broadcast(data={},
                                                endpoint='/resolve_conflict')
        if success:
            conflict_data.sort(key=lambda x: x[0], reverse=True)
            for length, hashchain, node_index in conflict_data:
                if length <= self.blockchain.length():
                    break
                idx = self.blockchain.index_of_fork(hashchain)
                try:
                    response = r.get('http://' + self.ring[node_index]['ip'] +
                                     ':' + self.ring[node_index]['port'] +
                                     '/resolve_conflict',
                                     params={'idx': idx})
                except r.exceptions.RequestException as e:
                    continue
                rest_of_the_blockchain = json.loads(
                    response.json())['blockchain']
                blockchain = Blockchain(self.blockchain.block_list[:idx] +
                                        rest_of_the_blockchain,
                                        update_time=False)
                if blockchain.validate(self.difficulty)[0]:
                    if self.mining_thread and self.mining_thread.is_alive():
                        self.mining_thread.hash_found.set()
                    with self.resolve_lock:
                        old_txs = self.blockchain.all_transactions(idx)
                        new_txs = self.blockchain.all_transactions()
                        self.blockchain = blockchain
                        with self.utxo_lock:
                            with self.tx_pool_lock:
                                self.ring = self.resolve_tx(old_txs=old_txs,
                                                            new_txs=new_txs,
                                                            resolve=True)[1]
                    return 200, ", node " + str(
                        node_index) + " gave me the correct blockchain"
            return 200, ", but it was just a false alarm, I have the largest valid blockchain"
        else:
            return 400, ", I couldn't ask all nodes to resolve the conflict"

    def resolve_tx(self, old_txs=[], new_txs=[], resolve=False):
        self.tx_pool = [tx for tx in self.tx_pool if not tx in new_txs]
        old_txs = [tx for tx in old_txs if not tx in new_txs]
        # self.tx_pool = old_txs + self.tx_pool

        temp_ring = deepcopy(self.ring)
        for node_dict in temp_ring.values():
            node_dict['utxos'] = OrderedDict()

        f = lambda tx: tx if isinstance(tx, dict) else tx.to_dict()
        transactions = [
            f(tx) for block in self.blockchain.block_list
            for tx in block.transactions
        ]

        address_dict = {v['address']: int(k) for k, v in self.ring.items()}

        if resolve:
            transactions = transactions + self.tx_pool
        for tx in transactions:
            inputs = tx['inputs']
            outputs = tx['outputs']

            for out_id, tx_out in outputs.items():
                receiver = temp_ring[address_dict[tx_out['recipient']]]
                receiver['utxos'][out_id] = tx_out

            if tx['signature'] == "genesis":
                continue

            sender = temp_ring[address_dict[tx['sender_address']]]
            for tx_in in inputs:
                if tx_in in sender['utxos']:
                    del sender['utxos'][tx_in]
                else:
                    return False, self.ring
        return True, temp_ring

    def write_block_times(self):
        avg, blocks = self.blockchain.block_time()
        dirname = os.path.join('results', str(self.max_nodes) + 'nodes')
        Path(dirname).mkdir(parents=True, exist_ok=True)
        filename = os.path.join(
            dirname, 'block_' + str(self.id) + '_' + str(self.capacity) + '_' +
            str(self.difficulty) + '.txt')
        with open(filename, 'w') as file:
            file.write('Average block time is  ' + str(avg) +
                       ' seconds, for ' + str(blocks) + 'blocks\n')

    def wallet_balance(self):
        with self.utxo_lock:
            balance = sum(utxo['amount']
                          for utxo in self.ring[self.id]['utxos'].values())
        return balance

    def view_transactions(self):
        with self.chain_lock:
            last = self.blockchain.last_transactions()
        return last