Beispiel #1
0
def main():
    bb = BlockBuilder()
    my_genesis_block = bb.generate_genesis_block()
    bm = BlockchainManager(my_genesis_block.to_dict())

    prev_block_hash = bm.get_hash(my_genesis_block.to_dict())
    print('genesis_block_hash :', prev_block_hash)

    transaction = {
            'sender': 'test',
            'recipient': 'test2',
            'value': 3
            }

    new_block = bb.generate_new_block(transaction, prev_block_hash)
    bm.set_new_block(new_block.to_dict())
   
    new_block_hash = bm.get_hash(new_block.to_dict())
    print('1st_block_hash :', new_block_hash)

    transaction = {
            'sender': 'test1',
            'recipient': 'test3',
            'value': 2
            }
    new_block2 = bb.generate_new_block(transaction, new_block_hash)
    bm.set_new_block(new_block2.to_dict())

    print(bm.chain)
    chain = bm.chain
    print(bm.is_valid(chain))
Beispiel #2
0
def main():
    global FLAG_STOP_BLOCK_BUILD

    bb = BlockBuilder()
    my_genesis_block = bb.generate_genesis_block()
    bm = BlockchainManager(my_genesis_block.to_dict())

    tp = TransactionPool()

    prev_block_hash = bm.get_hash(my_genesis_block.to_dict())
    print('genesis_block_hash :', prev_block_hash)

    transaction = {'sender': 'test1', 'recipient': 'test2', 'value': 3}

    tp.set_new_transaction(transaction)

    transaction2 = {'sender': 'test1', 'recipient': 'test3', 'value': 2}

    tp.set_new_transaction(transaction2)

    start_thread(tp, bb, bm, prev_block_hash)

    sleep(20)

    transaction3 = {'sender': 'test5', 'recipient': 'test6', 'value': 10}

    tp.set_new_transaction(transaction3)

    sleep(30)

    print('Stop the Thread for generate_block_with_tp')
    FLAG_STOP_BLOCK_BUILD = True
Beispiel #3
0
def main():
    bb = BlockBuilder()
    my_genesis_block = bb.generate_genesis_block()
    bm = BlockchainManager(my_genesis_block.to_dict())

    tp = TransactionPool()

    prev_block_hash = bm.get_hash(my_genesis_block.to_dict())
    print('genesis_block_hash :', prev_block_hash)

    transaction = {'sender': 'test', 'recipient': 'test2', 'value': 3}

    tp.set_new_transaction(transaction)

    transaction = {'sender': 'test1', 'recipient': 'test3', 'value': 2}

    tp.set_new_transaction(transaction)

    block_timer = threading.Timer(CHECK_INTERVAL,
                                  generate_block_with_tp,
                                  args=(tp, bb, bm, prev_block_hash))

    block_timer.start()

    time.sleep(11)

    transaction3 = {'sender': 'test5', 'recipient': 'test6', 'value': 10}
    tp.set_new_transaction(transaction3)
Beispiel #4
0
class ClientCore:
    def __init__(self,
                 my_port=50082,
                 core_host=None,
                 core_port=None,
                 callback=None,
                 mpmh_callback=None):
        self.client_state = STATE_INIT
        print('Initializing ClientCore...')
        self.my_ip = self.__get_myip()
        print('Server IP address is set to ... ', self.my_ip)
        self.my_port = my_port
        self.my_core_host = core_host
        self.my_core_port = core_port
        self.cm = ConnectionManager4Edge(self.my_ip, self.my_port, core_host,
                                         core_port, self.__handle_message)
        self.mpmh = MyProtocolMessageHandler()
        self.mpm_store = MessageStore()
        self.mpmh_callback = mpmh_callback

        self.bb = BlockBuilder()
        my_genesis_block = self.bb.generate_genesis_block()
        self.bm = BlockchainManager(my_genesis_block.to_dict())
        self.callback = callback

    def start(self, my_pubkey=None):
        self.client_state = STATE_ACTIVE
        self.cm.start()
        self.cm.connect_to_core_node(my_pubkey)

    def shutdown(self):
        self.client_state = STATE_SHUTTING_DOWN
        print('Shutdown edge node ...')
        self.cm.connection_close()

    def get_my_current_state(self):
        return self.client_state

    def send_message_to_my_core_node(self, msg_type, msg):
        msg_txt = self.cm.get_message_text(msg_type, msg)
        print(msg_txt)
        self.cm.send_msg((self.my_core_host, self.my_core_port), msg_txt)

    def send_req_full_chain_to_my_core_node(self):
        print('send_req_full_chain_to_my_core_node called')
        new_message = self.cm.get_message_text(MSG_REQUEST_FULL_CHAIN)
        self.cm.send_msg((self.my_core_host, self.my_core_port), new_message)

    def __client_api(self, request, msg):

        if request == 'pass_message_to_client_application':
            print('Client Core API: pass_message_to_client_application')
            self.mpm_store.add(msg)
            self.mpmh_callback(msg)
        elif request == 'api_type':
            return 'client_core_api'
        else:
            print('not implemented api was used')

    def get_my_protocol_messages(self):
        return self.my_protocol_message_store.get_list()

    def get_my_blockchain(self):
        return self.bm.get_my_blockchain()

    def get_stored_transactions_from_bc(self):
        return self.bm.get_stored_transactions_from_bc()

    def __handle_message(self, msg):
        if msg[2] == RSP_FULL_CHAIN:
            # ブロックチェーン送信要求に応じて返却されたブロックチェーンを検証し、有効なものか検証した上で
            # 自分の持つチェインと比較し優位な方を今後のブロックチェーンとして利用する
            new_block_chain = pickle.loads(msg[4].encode('utf8'))
            result, _ = self.bm.resolve_conflicts(new_block_chain)
            print('blockchain received form central', result)
            if result is not None:
                self.prev_block_hash = result
                print('callback called')
                self.callback()
            else:
                print('Received blockchain is useless...')

        elif msg[2] == MSG_ENHANCED:
            # P2P Network を単なるトランスポートして使っているアプリケーションが独自拡張したメッセージはここで処理する。
            # SimpleBitcoin としてはこの種別は使わない
            self.mpmh.handle_message(msg[4], self.__client_api, True)

    def __get_myip(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(('8.8.8.8', 80))
        return s.getsockname()[0]
class ServerCore:
    def __init__(self, my_port=50082, core_node_host=None, core_node_port=None):
        self.server_state = STATE_INIT
        print('Initializeing server...')
        self.my_ip = self.__get_myip()
        self.my_port = my_port
        print('Server IP address is set to ...', self.my_ip)
        print('Server Port is set to ...', self.my_port)
        self.cm = ConnectionManager(self.my_ip, self.my_port, self.__handle_message)
        self.core_node_host = core_node_host
        self.core_node_port = core_node_port
        self.mpmh = MyProtocolMessageHandler()
        self.my_protocol_message_store = []
        self.bb = BlockBuilder()
        my_genesis_block = self.bb.generate_genesis_block()
        self.bm = BlockchainManager(my_genesis_block.to_dict())
        self.prev_block_hash = self.bm.get_hash(my_genesis_block.to_dict())
        self.tp = TransactionPool()

    def start(self):
        self.server_state = STATE_STANDBY
        self.cm.start()

    def join_network(self):
        if self.core_node_host is not None:
            self.server_state = STATE_CONNECTED_TO_NETWORK
            self.cm.join_network(self.core_node_host, self.core_node_port)
        else:
            print('This server is runnning as Genesis Nore Node...')

    def shutdown(self):
        self.server_state = STATE_SHUTTING_DOWN
        print('Shutdown server...')
        self.cm.connection_close()

    def get_my_current_state(self):
        return self.server_state

    def __get_myip(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(('8.8.8.8', 80))
        return s.getsockname()[0]

    def __handle_message(self, msg, is_core, peer=None):
        """
        ConnectionManagerに引き渡すコールバックの中身
        """
        print('received message!!!!!!!!!!!!!!!!', msg, peer)
        if peer is not None:
            print('peer is not None')
            pass
            # TODO: 現状はMSG_REQUEST_FULL_CHAINの場合しかこの処理には入らない
            # とりあえず口だけ作る
        else:
            cmd = msg[2]
            if cmd == MSG_NEW_TRANSACTION:
                # 送信されてくるデータはバイナリ化したjson文字列とう前提で実装する
                new_transaction = json.loads(msg[4])
                print('received new_transaction', new_transaction)
                current_transactions = self.tp.get_stored_transactions()
                if new_transaction in current_transactions:
                    print('this is already pooled transaction:', t)
                    return
                self.tp.set_new_transaction(new_transaction)
                if not is_core:
                    new_message = self.cm.get_message_text(MSG_NEW_BLOCK,
                            json.dumps(new_block.to_dict()))
                    self.cm.send_msg_to_all_peer(new_message)
            elif cmd == MSG_NEW_BLOCK:
                # TODO: 新規ブロックを検証する処理を呼び出す
                pass
            elif cmd == RSP_FULL_CHAIN:
                # TODO: ブロックチェーン送信要求に応じて返却されたブロックチェーンを検証する処理を呼び出す
                pass
            elif cmd == MSG_ENHANCED:
                print('received enhanced message', msg[4])
                # P2P Networkを単なるトランスポートとして使っているアプリケーションが独自拡張したメッセージを処理する
                
                # 重複チェック
                # ここで同じメッセージを送らないようにしないと永遠と送り続けるループに入ってしまう
                current_message = self.my_protocol_message_store
                print('received messages', current_message)
                has_same = False
                if not msg[4] in current_message:
                    self.my_protocol_message_store.append(msg[4])
                    self.mpmh.handle_message(msg[4], self.__core_api)

    def __core_api(self, request, message):
        """
        MyProtocolMessageHandlerで呼び出すための拡張関数群
        """
        msg_type = MSG_ENHANCED

        if request == SEND_TO_ALL_EDGE:
            print('Sending all edge...')
            new_message = self.cm.get_message_text(msg_type, message)
            self.cm.send_msg_to_all_edge(new_message)
            return 'ok'
        elif request == SEND_TO_ALL_PEER:
            new_message = self.cm.get_message_text(msg_type, message)
            self.cm.send_msg_to_all_peer(new_message)
            return 'ok'
        elif request == 'api_type':
            return 'server_core_api'

    def __generate_block_with_tp(self):
    result = self.tp.get_stored_transactions()
    if len(result) == 0:
        print('Transaction Pool is empty')
    new_block = self.bb.generate_new_block(result, self.prev_block_hash)
    self.bm.set_new_block(new_block.to_dict())
    prev_block_hash = self.bm.get_hash(new_block.to_dict())
    # ブロック生成に成功したらTransaction Poolはクリアする
    index = len(result)
    self.tp.clear_my_transactions(index)
    print('Current Blockchain is ...', self.bm.chain)
    print('Current prev_block_hash is ...', self.prev_block_hash)

    self.bb_timer = threading.Timer(CHECK_INTERVAL,
            self.__generate_block_with_tp)
    self.bb_timer.start()
Beispiel #6
0
class ServerCore:
    def __init__(self,
                 my_port=50082,
                 core_node_host=None,
                 core_node_port=None,
                 pass_phrase=None):
        self.server_state = STATE_INIT
        print('Initializing server...')
        self.my_ip = self.__get_myip()
        print('Server IP address is set to ... ', self.my_ip)
        self.my_port = my_port
        self.cm = ConnectionManager(self.my_ip, self.my_port,
                                    self.__handle_message)
        self.mpmh = MyProtocolMessageHandler()
        self.core_node_host = core_node_host
        self.core_node_port = core_node_port
        self.bb = BlockBuilder()
        my_genesis_block = self.bb.generate_genesis_block()
        self.bm = BlockchainManager(my_genesis_block.to_dict())
        self.prev_block_hash = self.bm.get_hash(my_genesis_block.to_dict())
        self.tp = TransactionPool()
        self.is_bb_running = False
        self.flag_stop_block_build = False
        self.mpm_store = MessageStore()
        self.km = KeyManager(None, pass_phrase)
        self.rsa_util = RSAUtil()
        self.um = UTXOManager(self.km.my_address())

    def start_block_building(self):
        self.bb_timer = threading.Timer(CHECK_INTERVAL,
                                        self.__generate_block_with_tp)
        self.bb_timer.start()

    def stop_block_building(self):
        print('Thread for __generate_block_with_tp is stopped now')
        self.bb_timer.cancel()

    def start(self):
        self.server_state = STATE_STANDBY
        self.cm.start()
        self.start_block_building()

    def join_network(self):
        if self.core_node_host != None:
            self.server_state = STATE_CONNECTED_TO_CENTRAL
            self.cm.join_network(self.core_node_host, self.core_node_port)
        else:
            print('This server is runnning as Genesis Core Node...')

    def shutdown(self):
        self.server_state = STATE_SHUTTING_DOWN
        self.flag_stop_block_build = True
        print('Shutdown server...')
        self.cm.connection_close()
        self.stop_block_building()

    def get_my_current_state(self):
        return self.server_state

    def send_req_full_chain_to_my_peer(self):
        print('send_req_full_chain_to_my_central called')
        new_message = self.cm.get_message_text(MSG_REQUEST_FULL_CHAIN)
        self.cm.send_msg((self.core_node_host, self.core_node_port),
                         new_message)

    def get_all_chains_for_resolve_conflict(self):
        print('get_all_chains_for_resolve_conflict called')
        new_message = self.cm.get_message_text(MSG_REQUEST_FULL_CHAIN)
        self.cm.send_msg_to_all_peer(new_message)

    def __generate_block_with_tp(self):

        print('Thread for generate_block_with_tp started!')
        while not self.flag_stop_block_build:
            self.is_bb_running = True
            prev_hash = copy.copy(self.prev_block_hash)
            result = self.tp.get_stored_transactions()
            if len(result) == 0:
                print('Transaction Pool is empty ...')
                break
            new_tp = self.bm.remove_useless_transaction(result)
            self.tp.renew_my_transactions(new_tp)
            if len(new_tp) == 0:
                break
            # リワードとしてリストの先頭に自分宛のCoinbaseTransactionを追加する
            total_fee = self.tp.get_total_fee_from_tp()
            # TODO: インセンティブの値をここに直書きするのはイケてないのであとで対処する
            total_fee += 30
            my_coinbase_t = CoinbaseTransaction(self.km.my_address(),
                                                total_fee)
            transactions_4_block = copy.deepcopy(new_tp)
            transactions_4_block.insert(0, my_coinbase_t.to_dict())
            new_block = self.bb.generate_new_block(transactions_4_block,
                                                   prev_hash)
            # タイミングがどうしてもクロスするので念のため保存前に再度確認
            if new_block.to_dict()['previous_block'] == self.prev_block_hash:
                self.bm.set_new_block(new_block.to_dict())
                self.prev_block_hash = self.bm.get_hash(new_block.to_dict())
                msg_new_block = self.cm.get_message_text(
                    MSG_NEW_BLOCK, json.dumps(new_block.to_dict()))
                self.cm.send_msg_to_all_peer(msg_new_block)
                # ブロック生成に成功したらTransaction Poolはクリアする
                index = len(new_tp)
                self.tp.clear_my_transactions(index)
                break
            else:
                print('Bad block. It seems someone already win the PoW.')
                break

        print('Current Blockchain is ... ', self.bm.chain)
        print('Current prev_block_hash is ... ', self.prev_block_hash)
        self.flag_stop_block_build = False
        self.is_bb_running = False
        self.bb_timer = threading.Timer(CHECK_INTERVAL,
                                        self.__generate_block_with_tp)
        self.bb_timer.start()

    def _check_availability_of_transaction(self, transaction):
        """
        Transactionに含まれているTransactionInputの有効性(二重使用)を検証する
        """
        v_result, used_outputs = self.rsa_util.verify_sbc_transaction_sig(
            transaction)
        if v_result is not True:
            print('signature verification error on new transaction')
            return False

        for used_o in used_outputs:
            print('used_o', used_o)
            bm_v_result = self.bm.has_this_output_in_my_chain(used_o)
            tp_v_result = self.tp.has_this_output_in_my_tp(used_o)
            bm_v_result2 = self.bm.is_valid_output_in_my_chain(used_o)
            if bm_v_result:
                print('This TransactionOutput is already used', used_o)
                return False
            if tp_v_result:
                print(
                    'This TransactionOutput is already stored in the TransactionPool',
                    used_o)
                return False
            if bm_v_result2 is not True:
                print('This TransactionOutput is unknown', used_o)
                return False

        return True

    def _check_availability_of_transaction_in_block(self, transaction):
        """
        Transactionの有効性を検証する(Block用)
        """
        v_result, used_outputs = self.rsa_util.verify_sbc_transaction_sig(
            transaction)
        if v_result is not True:
            print('signature verification error on new transaction')
            return False

        print('used_outputs: ', used_outputs)

        for used_o in used_outputs:
            print('used_o: ', used_o)
            bm_v_result = self.bm.has_this_output_in_my_chain(used_o)
            bm_v_result2 = self.bm.is_valid_output_in_my_chain(used_o)
            if bm_v_result2 is not True:
                print('This TransactionOutput is unknown', used_o)
                return False
            if bm_v_result:
                print('This TransactionOutput is already used', used_o)
                return False

        return True

    def get_total_fee_on_block(self, block):
        """
        ブロックに格納されているbasicなTransaction全ての手数料の合計値を算出する
        """
        print('get_total_fee_on_block is called')
        transactions = block['transactions']
        result = 0
        for t in transactions:
            t = json.loads(t)
            is_sbc_t, t_type = self.um.is_sbc_transaction(t)
            if t_type == 'basic':
                total_in = sum(
                    i['transaction']['outputs'][i['output_index']]['value']
                    for i in t['inputs'])
                total_out = sum(o['value'] for o in t['outputs'])
                delta = total_in - total_out
                result += delta

        return result

    def check_transactions_in_new_block(self, block):
        """
        ブロック内のTranactionに不正がないか確認する
        """
        fee_for_block = self.get_total_fee_on_block(block)
        fee_for_block += 30
        print("fee_for_block: ", fee_for_block)

        transactions = block['transactions']

        counter = 0

        for t in transactions:
            t = json.loads(t)
            # basic, coinbase_transaction以外はスルーチェック
            is_sbc_t, t_type = self.um.is_sbc_transaction(t)
            if is_sbc_t:
                if t_type == 'basic':
                    if self._check_availability_of_transaction_in_block(
                            t) is not True:
                        print('Bad Block. Having invalid Transaction')
                        return False
                elif t_type == 'coinbase_transaction':
                    if counter != 0:
                        print('Coinbase Transaction is only for BlockBuilder')
                        return False
                    else:
                        insentive = t['outputs'][0]['value']
                        print('insentive', insentive)
                        if insentive != fee_for_block:
                            print(
                                'Invalid value in fee for CoinbaseTransaction',
                                insentive)
                            return False
            else:
                is_verified = self.rsa_util.verify_general_transaction_sig(t)
                if is_verified is not True:
                    return False

        print('ok. this block is acceptable.')
        return True

    def __core_api(self, request, message):

        if request == 'send_message_to_all_peer':
            new_message = self.cm.get_message_text(MSG_ENHANCED, message)
            self.cm.send_msg_to_all_peer(new_message)
            return 'ok'
        elif request == 'send_message_to_all_edge':
            new_message = self.cm.get_message_text(MSG_ENHANCED, message)
            self.cm.send_msg_to_all_edge(new_message)
            return 'ok'
        elif request == 'api_type':
            return 'server_core_api'
        elif request == 'send_message_to_this_pubkey_address':
            print('send_message_to_this_pubkey_address', message[0])
            msg_type = MSG_ENHANCED
            msg_txt = self.cm.get_message_text(msg_type, message[1])
            check_result, target_host, target_port = self.cm.has_this_edge(
                message[0])
            print('check_result', check_result)
            if check_result:
                print('sending cipher direct message to... ', target_host,
                      target_port)
                self.cm.send_msg((target_host, target_port), msg_txt)
                return 'ok'
            else:
                return None

    def __handle_message(self, msg, is_core, peer=None):
        if peer != None:
            if msg[2] == MSG_REQUEST_FULL_CHAIN:
                print('Send our latest blockchain for reply to : ', peer)
                mychain = self.bm.get_my_blockchain()
                chain_data = pickle.dumps(mychain, 0).decode()
                new_message = self.cm.get_message_text(RSP_FULL_CHAIN,
                                                       chain_data)
                self.cm.send_msg(peer, new_message)
        else:
            if msg[2] == MSG_NEW_TRANSACTION:
                new_transaction = json.loads(msg[4])
                print('received new_transaction', new_transaction)
                is_sbc_t, _ = self.um.is_sbc_transaction(new_transaction)
                current_transactions = self.tp.get_stored_transactions()
                if new_transaction in current_transactions:
                    print('this is already pooled transaction: ',
                          new_transaction)
                    return

                    if not is_sbc_t:
                        print('this is not SimpleBitcoin transaction: ',
                              new_transaction)
                    else:
                        # テスト用に最初のブロックだけ未知のCoinbaseTransactionを許すための暫定処置
                        if self.bm.get_my_chain_length() != 1:
                            checked = self._check_availability_of_transaction(
                                new_transaction)
                            if not checked:
                                print('Transaction Verification Error')
                                return
                    self.tp.set_new_transaction(new_transaction)

                    if not is_core:
                        new_message = self.cm.get_message_text(
                            MSG_NEW_TRANSACTION, json.dumps(new_transaction))
                        self.cm.send_msg_to_all_peer(new_message)
                else:
                    if not is_sbc_t:
                        print('this is not SimpleBitcoin transaction: ',
                              new_transaction)
                    else:
                        # テスト用に最初のブロックだけ未知のCoinbaseTransactionを許すための暫定処置
                        if self.bm.get_my_chain_length() != 1:
                            checked = self._check_availability_of_transaction(
                                new_transaction)
                            if not checked:
                                print('Transaction Verification Error')
                                return
                    self.tp.set_new_transaction(new_transaction)

                    if not is_core:
                        new_message = self.cm.get_message_text(
                            MSG_NEW_TRANSACTION, json.dumps(new_transaction))
                        self.cm.send_msg_to_all_peer(new_message)

            elif msg[2] == MSG_NEW_BLOCK:

                if not is_core:
                    print('block received from unknown')
                    return

                new_block = json.loads(msg[4])
                print('new_block: ', new_block)
                if self.bm.is_valid_block(self.prev_block_hash, new_block):
                    block_check_result = self.check_transactions_in_new_block(
                        new_block)
                    print('block_check_result : ', block_check_result)
                    if block_check_result is not True:
                        print(
                            'previous block hash is ok. but still not acceptable.'
                        )
                        self.get_all_chains_for_resolve_conflict()
                        return
                    # ブロック生成が行われていたら一旦停止してあげる(threadingなのでキレイに止まらない場合あり)
                    if self.is_bb_running:
                        self.flag_stop_block_build = True
                    self.prev_block_hash = self.bm.get_hash(new_block)
                    self.bm.set_new_block(new_block)
                else:
                    # ブロックとして不正ではないがVerifyにコケる場合は自分がorphanブロックを生成している
                    # 可能性がある
                    self.get_all_chains_for_resolve_conflict()

            elif msg[2] == RSP_FULL_CHAIN:

                if not is_core:
                    print('blockchain received from unknown')
                    return
                # ブロックチェーン送信要求に応じて返却されたブロックチェーンを検証し、有効なものか検証した上で
                # 自分の持つチェインと比較し優位な方を今後のブロックチェーンとして有効化する
                new_block_chain = pickle.loads(msg[4].encode('utf8'))
                result, pool_4_orphan_blocks = self.bm.resolve_conflicts(
                    new_block_chain)
                print('blockchain received')
                if result is not None:
                    self.prev_block_hash = result
                    if len(pool_4_orphan_blocks) != 0:
                        # orphanブロック群の中にあった未処理扱いになるTransactionをTransactionPoolに戻す
                        new_transactions = self.bm.get_transactions_from_orphan_blocks(
                            pool_4_orphan_blocks)
                        for t in new_transactions:
                            self.tp.set_new_transaction(t)
                else:
                    print('Received blockchain is useless...')

            elif msg[2] == MSG_ENHANCED:
                # アプリケーションがP2P Network を単なるトランスポートして使うために独自拡張したメッセージはここで処理する。
                # SimpleBitcoin としてはこの種別は使わない
                print('received enhanced message', msg[4])
                has_same = self.mpm_store.has_this_msg(msg[4])

                if has_same is not True:
                    self.mpm_store.add(msg[4])
                    self.mpmh.handle_message(msg[4], self.__core_api, is_core)

    def __get_myip(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(('8.8.8.8', 80))
        return s.getsockname()[0]
Beispiel #7
0
class ServerCore(object):
    def __init__(self,
                 my_port=50082,
                 core_node_host=None,
                 core_node_port=None):
        self.server_state = STATE_INIT
        print('Initializing server...')
        self.my_ip = self.__get_myip()
        print('Server IP address is set to ... ', self.my_ip)
        self.my_port = my_port
        self.cm = ConnectionManager(self.my_ip, self.my_port,
                                    self.__handle_message, self)
        self.mpmh = MyProtocolMessageHandler()
        self.core_node_host = core_node_host
        self.core_node_port = core_node_port
        self.bb = BlockBuilder()
        self.flag_stop_block_build = False
        self.is_bb_running = False
        my_genesis_block = self.bb.generate_genesis_block()
        self.bm = BlockchainManager(my_genesis_block.to_dict())
        self.prev_block_hash = self.bm.get_hash(my_genesis_block.to_dict())
        self.tp = TransactionPool()

        if core_node_host and core_node_port:
            self.plz_share_db()

    def start_block_building(self):
        self.bb_timer = threading.Timer(CHECK_INTERVAL,
                                        self.__generate_block_with_tp)
        self.bb_timer.start()

    def stop_block_building(self):
        print('Thread for __generate_block_with_tp is stopped now')
        self.bb_timer.cancel()

    def start(self):
        self.server_state = STATE_STANDBY
        self.cm.start()
        self.start_block_building()

    def join_network(self):
        if self.core_node_host is not None:
            self.server_state = STATE_CONNECTED_TO_NETWORK  # 状態:親ノードへ接続中
            self.cm.join_network(self.core_node_host, self.core_node_port)
        else:
            print('This server is running as Genesis Core Node...')

    def shutdown(self):
        self.server_state = STATE_SHUTTING_DOWN  # 状態:切断中
        print('Shutdown server...')
        self.cm.connection_close()
        self.stop_block_building()

    def get_my_current_state(self):
        return self.server_state

    def plz_share_db(self):
        print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")
        print("■■■■■■■■■■■■■■■■■■■■ plz_share_db ■■■■■■■■■■■■■■■■■■■■■■")
        print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")
        new_message = self.cm.get_message_text(SHARE_DB3)
        self.cm.send_msg((self.core_node_host, self.core_node_port),
                         new_message)
        print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")

    # TODO 接続時のアレコレ
    def get_all_chains_for_resolve_conflict(self):
        print('get_all_chains_for_resolve_conflict called')
        new_message = self.cm.get_message_text(MSG_REQUEST_FULL_CHAIN)
        self.cm.send_msg_to_all_peer(new_message)

    def __generate_block_with_tp(self):

        if DEBUG:
            print('Thread for generate_block_with_tp started!')
        while self.flag_stop_block_build is not True:

            result = self.tp.get_stored_transactions()

            if result is None:
                print('Transaction Pool is empty ...')
                break

            new_tp = self.bm.remove_useless_transaction(result)
            self.tp.renew_my_transactions(new_tp)
            # if len(new_tp) == 0:  # TODO TPが0のとき、終わるように。コメントアウトで切り替え
            #     break
            new_block = self.bb.generate_new_block(new_tp,
                                                   self.prev_block_hash)
            self.bm.set_new_block(new_block.to_dict())
            self.prev_block_hash = self.bm.get_hash(new_block.to_dict())
            message_new_block = self.cm.get_message_text(
                MSG_NEW_BLOCK, json.dumps(new_block.to_dict()))
            self.cm.send_msg_to_all_peer(message_new_block)
            index = len(result)
            self.tp.clear_my_transactions(index)
            break

        print(
            "■■■■■■■■■■■■■■■■■■■ Current BC ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■"
        )
        print(self.bm.chain)

        if len(self.bm.chain) >= 10:
            main_level.add_db(ldb_p=LDB_P,
                              param_p=PARAM_P,
                              zip_p=ZIP_P,
                              vals=self.bm.chain[:5])
            self.bm.chain = self.bm.chain[5:]
            print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")
            print("保存しました")
            print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")

        # print('Current prev_block_hash is ... ', self.prev_block_hash)
        self.flag_stop_block_build = False
        self.is_bb_running = False
        self.bb_timer = threading.Timer(CHECK_INTERVAL,
                                        self.__generate_block_with_tp)
        self.bb_timer.start()

    def __handle_message(self, msg, is_core, peer=None):

        if peer:
            if msg[2] == MSG_REQUEST_FULL_CHAIN:
                if DEBUG:
                    print('Send our latest blockchain for reply to : ', peer)
                mychain = self.bm.get_my_blockchain()
                if DEBUG:
                    print(mychain)
                chain_data = pickle.dumps(mychain, 0).decode()
                new_message = self.cm.get_message_text(RSP_FULL_CHAIN,
                                                       chain_data)
                self.cm.send_msg(peer, new_message)
        else:
            if msg[2] == MSG_NEW_TRANSACTION:
                # 新規transactionを登録する処理を呼び出す
                new_transaction = json.loads(msg[4])
                print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")
                print("transactions", self.tp.get_stored_transactions())
                print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")
                if DEBUG:
                    print("received new_transaction", new_transaction)
                current_transactions = self.tp.get_stored_transactions()
                if new_transaction in current_transactions:
                    if DEBUG:
                        print("this is already pooled transaction:",
                              new_transaction)
                    return
                if not is_core:
                    self.tp.set_new_transaction(new_transaction)
                    # new_message = self.cm.get_message_text(MSG_NEW_BLOCK, json.dumps(new_block.to_dict()))
                    new_message = self.cm.get_message_text(
                        MSG_NEW_TRANSACTION, json.dumps(new_transaction))
                    self.cm.send_msg_to_all_peer(new_message)
                else:
                    self.tp.set_new_transaction(new_transaction)

            elif msg[2] == MSG_NEW_BLOCK:

                if not is_core:
                    print('block received from unknown')
                    return

                # 新規ブロックを検証し、正当なものであればブロックチェーンに追加する
                # TODO
                new_block = json.loads(msg[4])
                if DEBUG:
                    print('new_block: ', new_block)
                if self.bm.is_valid_block(self.prev_block_hash, new_block):
                    # ブロック生成が行われていたら一旦停止してあげる(threadingなのでキレイに止まらない場合あり)
                    if self.is_bb_running:
                        self.flag_stop_block_build = True
                    self.prev_block_hash = self.bm.get_hash(new_block)
                    self.bm.set_new_block(new_block)
                else:
                    # ブロックとして不正ではないがVerifyにコケる場合は自分がorphanブロックを生成している
                    # 可能性がある
                    self.get_all_chains_for_resolve_conflict()

            elif msg[2] == RSP_FULL_CHAIN:

                if not is_core:
                    if DEBUG:
                        print('blockchain received from unknown')
                    return
                # ブロックチェーン送信要求に応じて返却されたブロックチェーンを検証し、有効なものか検証した上で
                # 自分の持つチェインと比較し優位な方を今後のブロックチェーンとして有効化する
                new_block_chain = pickle.loads(msg[4].encode('utf8'))
                print(new_block_chain)
                result, pool_4_orphan_blocks = self.bm.resolve_conflicts(
                    new_block_chain)
                if DEBUG:
                    print('blockchain received')
                if result is not None:
                    self.prev_block_hash = result
                    if len(pool_4_orphan_blocks) != 0:
                        # orphanブロック群の中にあった未処理扱いになるTransactionをTransactionPoolに戻す
                        new_transactions = self.bm.get_transactions_from_orphan_blocks(
                            pool_4_orphan_blocks)
                        for t in new_transactions:
                            self.tp.set_new_transaction(t)
                else:
                    if DEBUG:
                        print('Received blockchain is useless...')
            elif msg[2] == MSG_ENHANCED:
                # P2P Network を単なるトランスポートして使っているアプリケーションが独自拡張したメッセージはここで処理する。SimpleBitcoin としてはこの種別は使わない
                self.mpmh.handle_message(msg[4])

    def __get_myip(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(('8.8.8.8', 80))
        return s.getsockname()[0]
class ServerCore(object):
    def __init__(self,
                 my_port=50082,
                 core_node_host=None,
                 core_node_port=None):
        self.server_state = STATE_INIT
        print('Initializing server...')
        self.my_ip = self.__get_myip()
        print('Server IP address is set to ... ', self.my_ip)
        self.my_port = my_port
        self.cm = ConnectionManager(self.my_ip, self.my_port,
                                    self.__handle_message)
        self.mpmh = MyProtocolMessageHandler()
        self.core_node_host = core_node_host
        self.core_node_port = core_node_port
        self.bb = BlockBuilder()
        self.flag_stop_block_build = False
        self.is_bb_running = False
        my_genesis_block = self.bb.generate_genesis_block()
        self.bm = BlockchainManager(my_genesis_block.to_dict())
        self.prev_block_hash = self.bm.get_hash(my_genesis_block.to_dict())
        self.tp = TransactionPool()
        self.vl = VerifyLocinfo()
        # 位置情報の偽装を検知するようのカウンタ
        self.c_cnt = 0
        self.bc_cnt = 0
        self.false_cnt = 0

    def start_block_building(self):
        self.bb_timer = threading.Timer(CHECK_INTERVAL,
                                        self.__generate_block_with_tp)
        self.bb_timer.start()

    def stop_block_building(self):
        print('Thread for __generate_block_with_tp is stopped now')
        self.bb_timer.cancel()

    def start(self):
        self.server_state = STATE_STANDBY
        self.cm.start()
        self.start_block_building()

    def join_network(self):
        if self.core_node_host != None:
            self.server_state = STATE_CONNECTED_TO_NETWORK  # 状態:親ノードへ接続中
            self.cm.join_network(self.core_node_host, self.core_node_port)
        else:
            print('This server is running as Genesis Core Node...')

    def shutdown(self):
        self.server_state = STATE_SHUTTING_DOWN  # 状態:切断中
        print('Shutdown server...')
        self.cm.connection_close()
        self.stop_block_building()

    def get_my_current_state(self):
        return self.server_state

    def get_all_chains_for_resolve_conflict(self):
        print('get_all_chains_for_resolve_conflict called')
        new_message = self.cm.get_message_text(MSG_REQUEST_FULL_CHAIN)
        self.cm.send_msg_to_all_peer(new_message)

    def __generate_block_with_tp(self):

        print('Thread for generate_block_with_tp started!')
        while self.flag_stop_block_build is not True:

            result = self.tp.get_stored_transactions()

            if result == None:
                print('Transaction Pool is empty ...')
                break

            new_tp = self.bm.remove_useless_transaction(result)
            self.tp.renew_my_transactions(new_tp)
            if len(new_tp) == 0:
                break
            new_block = self.bb.generate_new_block(new_tp,
                                                   self.prev_block_hash)
            self.bm.set_new_block(new_block.to_dict())
            self.prev_block_hash = self.bm.get_hash(new_block.to_dict())
            message_new_block = self.cm.get_message_text(
                MSG_NEW_BLOCK, json.dumps(new_block.to_dict()))
            self.cm.send_msg_to_all_peer(message_new_block)
            index = len(result)
            self.tp.clear_my_transactions(index)
            break

        print('Current Blockchain is ... ', self.bm.chain)
        print('Current prev_block_hash is ... ', self.prev_block_hash)
        self.flag_stop_block_build = False
        self.is_bb_running = False
        self.bb_timer = threading.Timer(CHECK_INTERVAL,
                                        self.__generate_block_with_tp)
        self.bb_timer.start()

    def __handle_message(self, msg, is_core, peer=None):

        if peer != None:
            if msg[2] == MSG_REQUEST_FULL_CHAIN:
                print('Send our latest blockchain for reply to : ', peer)
                mychain = self.bm.get_my_blockchain()
                print(mychain)
                chain_data = pickle.dumps(mychain, 0).decode()
                new_message = self.cm.get_message_text(RSP_FULL_CHAIN,
                                                       chain_data)
                self.cm.send_msg(peer, new_message)
        else:
            if msg[2] == MSG_NEW_TRANSACTION:
                # 新規transactionを登録する処理を呼び出す
                new_transaction = json.loads(msg[4])
                print("received new_transaction", new_transaction)
                current_transactions = self.tp.get_stored_transactions()
                bc_transactions = self.bm.get_stored_transactions_from_bc()

                if new_transaction in current_transactions:
                    print("this is already pooled transaction:",
                          new_transaction)
                    return

                else:
                    # 車両から送られてきた位置情報を検知する
                    if len(current_transactions
                           ) > 0 and self.vl.verify_trlocinfo(
                               new_transaction, current_transactions):
                        self.c_cnt += 1
                        with open(
                                '/home/ryoichi/Templates/BlockchainProjects/result/result_c_cnt.txt',
                                'a') as f:
                            f.write(
                                str(self.my_port) + "," + str(self.c_cnt) +
                                "\n")
                        print("C_Counter", self.c_cnt)
                        self.tp.set_new_transaction(new_transaction)

                        if not is_core:
                            m_type = MSG_NEW_TRANSACTION
                            new_message = self.cm.get_message_text(
                                m_type, json.dumps(new_transaction))
                            self.cm.send_msg_to_all_peer(new_message)

                    elif len(bc_transactions) > 0 and self.vl.verify_trlocinfo(
                            new_transaction, bc_transactions):
                        self.bc_cnt += 1
                        with open(
                                '/home/ryoichi/Templates/BlockchainProjects/result/result_bc_cnt.txt',
                                'a') as f:
                            f.write(
                                str(self.my_port) + "," + str(self.bc_cnt) +
                                "\n")
                        print("BC_Counter", self.bc_cnt)
                        self.tp.set_new_transaction(new_transaction)

                        if not is_core:
                            m_type = MSG_NEW_TRANSACTION
                            new_message = self.cm.get_message_text(
                                m_type, json.dumps(new_transaction))
                            self.cm.send_msg_to_all_peer(new_message)

                    else:
                        self.false_cnt += 1
                        with open(
                                '/home/ryoichi/Templates/BlockchainProjects/result/result_false_cnt.txt',
                                'a') as f:
                            f.write(
                                str(self.my_port) + "," + str(self.false_cnt) +
                                "\n")
                        print("FALSE_Counter", self.false_cnt)
                        ntr = new_transaction['vehicleinfo']
                        process_time = time.time(
                        ) - new_transaction['sendtime']
                        ntr_id = [i['ID'] for i in ntr]
                        ntr_ID = ntr_id[0] if len(ntr_id) else ''
                        ntr_ts = [i['timestamp'] for i in ntr]
                        ntr_timestamp = ntr_ts[0] if len(ntr_ts) else ''
                        ntr_or = [i['TorF'] for i in ntr]
                        ntr_torf = ntr_or[0] if len(ntr_or) else ''
                        with open(
                                '/home/ryoichi/Templates/BlockchainProjects/result/result_new_transaction.txt',
                                'a') as f:
                            f.write(
                                str(self.my_port) + "," + str(ntr_ID) + "," +
                                str(ntr_timestamp) + "," + str(ntr_torf) +
                                "," + str(process_time) + "\n")
                        print("FALSE_Counter", self.false_cnt)
                        self.tp.set_new_transaction(new_transaction)

                        if not is_core:
                            m_type = MSG_NEW_TRANSACTION
                            new_message = self.cm.get_message_text(
                                m_type, json.dumps(new_transaction))
                            self.cm.send_msg_to_all_peer(new_message)

            elif msg[2] == MSG_NEW_BLOCK:

                if not is_core:
                    print('block received from unknown')
                    return

                # 新規ブロックを検証し、正当なものであればブロックチェーンに追加する
                new_block = json.loads(msg[4])
                block_processtime = self.vl.extract_newblockprocesstime(
                    new_block)
                with open(
                        '/home/ryoichi/Templates/BlockchainProjects/result/result_new_block_time.txt',
                        'a') as f:
                    f.write(
                        str(self.my_port) + "," + str(block_processtime) +
                        "\n")
                with open(
                        '/home/ryoichi/Templates/BlockchainProjects/result/result_new_block.txt',
                        'a') as f:
                    f.write(str(self.my_port) + "," + str(new_block) + "\n")
                print('new_block: ', new_block)

                if self.bm.is_valid_block(self.prev_block_hash, new_block):
                    # ブロック生成が行われていたら一旦停止してあげる(threadingなのでキレイに止まらない場合あり)
                    if self.is_bb_running:
                        self.flag_stop_block_build = True
                    self.prev_block_hash = self.bm.get_hash(new_block)
                    self.bm.set_new_block(new_block)
                else:
                    # ブロックとして不正ではないがVerifyにコケる場合は自分がorphanブロックを生成している
                    # 可能性がある
                    self.get_all_chains_for_resolve_conflict()

            elif msg[2] == RSP_FULL_CHAIN:

                if not is_core:
                    print('blockchain received from unknown')
                    return
                # ブロックチェーン送信要求に応じて返却されたブロックチェーンを検証し、有効なものか検証した上で
                # 自分の持つチェインと比較し優位な方を今後のブロックチェーンとして有効化する
                new_block_chain = pickle.loads(msg[4].encode('utf8'))
                print(new_block_chain)
                result, pool_4_orphan_blocks = self.bm.resolve_conflicts(
                    new_block_chain)
                print('blockchain received')
                if result is not None:
                    self.prev_block_hash = result
                    if len(pool_4_orphan_blocks) != 0:
                        # orphanブロック群の中にあった未処理扱いになるTransactionをTransactionPoolに戻す
                        new_transactions = self.bm.get_transactions_from_orphan_blocks(
                            pool_4_orphan_blocks)
                        for t in new_transactions:
                            self.tp.set_new_transaction(t)
                else:
                    print('Received blockchain is useless...')
            elif msg[2] == MSG_ENHANCED:
                # P2P Network を単なるトランスポートして使っているアプリケーションが独自拡張したメッセージはここで処理する。SimpleBitcoin としてはこの種別は使わない
                self.mpmh.handle_message(msg[4])

    def __get_myip(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(('8.8.8.8', 80))
        return s.getsockname()[0]

    def get_count(self):
        a = self.c_cnt
        b = self.bc_cnt
        c = self.false_cnt
        return a, b, c
Beispiel #9
0
class ServerCore(object):
    def __init__(self,
                 my_port=50082,
                 core_node_host=None,
                 core_node_port=None):
        self.server_state = STATE_INIT
        print('Initializing server...')
        self.my_ip = self.__get_myip()
        print('Server IP address is set to ... ', self.my_ip)
        self.my_port = my_port
        self.cm = ConnectionManager(self.my_ip, self.my_port,
                                    self.__handle_message)
        self.mpmh = MyProtocolMessageHandler()
        self.core_node_host = core_node_host
        self.core_node_port = core_node_port

        self.bb = BlockBuilder()
        my_genesis_block = self.bb.generate_genesis_block()
        self.bm = BlockchainManager(my_genesis_block.to_dict())
        self.prev_block_hash = self.bm.get_hash(my_genesis_block.to_dict())
        self.tp = TransactionPool()

    def start(self):
        self.server_state = STATE_STANDBY
        self.cm.start()

        self.bb_timer = threading.Timer(CHECK_INTERVAL,
                                        self.__generate_block_with_tp)
        self.bb_timer.start()

    def join_network(self):
        if self.core_node_host != None:
            self.server_state = STATE_CONNECTED_TO_NETWORK  # 状態:親ノードへ接続中
            self.cm.join_network(self.core_node_host, self.core_node_port)
        else:
            print('This server is runnning as Genesis Core Node...')

    def shutdown(self):
        self.server_state = STATE_SHUTTING_DOWN  # 状態:切断中
        print('Shutdown server...')
        self.cm.connection_close()

    def get_my_current_state(self):
        return self.server_state

    def __generate_block_with_tp(self):

        result = self.tp.get_stored_transactions()
        print('generate_block_with_tp called!')
        if len(result) == 0:
            print('Transaction Pool is empty ...')
        new_block = self.bb.generate_new_block(result, self.prev_block_hash)
        self.bm.set_new_block(new_block.to_dict())
        self.prev_block_hash = self.bm.get_hash(new_block.to_dict())
        # ブロック生成に成功したらTransaction Poolはクリアする
        index = len(result)
        self.tp.clear_my_transactions(index)

        print('Current Blockchain is ... ', self.bm.chain)
        print('Current prev_block_hash is ... ', self.prev_block_hash)

        self.bb_timer = threading.Timer(CHECK_INTERVAL,
                                        self.__generate_block_with_tp)
        self.bb_timer.start()

    def __handle_message(self, msg, is_core, peer=None):
        if peer != None:
            if msg[2] == MSG_REQUEST_FULL_CHAIN:
                # TODO: 現状はMSG_REQUEST_FULL_CHAINの時くらいしか想定してないけどとりあえず
                print('Send our latest blockchain for reply to : ', peer)
                pass
        else:
            if msg[2] == MSG_NEW_TRANSACTION:
                # 新規transactionを登録する処理を呼び出す
                new_transaction = json.loads(msg[4])
                print("received new_transaction", new_transaction)
                current_transactions = self.tp.get_stored_transactions()
                has_same = False
                if new_transaction in current_transactions:
                    print("this is already pooled transaction:", t)
                    return

                if not is_core:
                    self.tp.set_new_transaction(new_transaction)
                    new_message = self.cm.get_message_text(
                        MSG_NEW_TRANSACTION, json.dumps(new_transaction))
                    self.cm.send_msg_to_all_peer(new_message)
                else:
                    self.tp.set_new_transaction(new_transaction)

            elif msg[2] == MSG_NEW_BLOCK:
                # TODO: 新規ブロックを検証する処理を呼び出す
                pass
            elif msg[2] == RSP_FULL_CHAIN:
                # TODO: ブロックチェーン送信要求に応じて返却されたブロックチェーンを検証する処理を呼び出す
                pass
            elif msg[2] == MSG_ENHANCED:
                # P2P Network を単なるトランスポートして使っているアプリケーションが独自拡張したメッセージはここで処理する。SimpleBitcoin としてはこの種別は使わない
                self.mpmh.handle_message(msg[4])

    def __get_myip(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(('8.8.8.8', 80))
        return s.getsockname()[0]
Beispiel #10
0
class ServerCore(object):
    def __init__(self,
                 my_port=50082,
                 core_node_host=None,
                 core_node_port=None):
        self.server_state = STATE_INIT
        # self.main_window = GuiTest()
        print('Initializing server...')
        self.my_ip = self.__get_myip()
        print('Server IP address is set to ... ', self.my_ip)
        self.my_port = my_port
        self.cm = ConnectionManager(
            self.my_ip, self.my_port, self.__handle_message, self
        )  #, self.main_window.set_cnode_list, self.main_window.set_enode_list)
        self.mpmh = MyProtocolMessageHandler()
        self.core_node_host = core_node_host
        self.core_node_port = core_node_port
        self.bb = BlockBuilder()
        self.flag_stop_block_build = False
        self.is_bb_running = False
        my_genesis_block = self.bb.generate_genesis_block()
        self.bm = BlockchainManager(my_genesis_block.to_dict())
        self.prev_block_hash = self.bm.get_hash(my_genesis_block.to_dict())
        self.tp = TransactionPool()

        if core_node_host and core_node_port:
            self.plz_share_db()
            # self.get_all_chains_for_resolve_conflict()
        # self.main_window.set_port(self.my_port)

    """
	def start_gui(self):
		try:
			self.main_window.start()
		except:
			time.sleep(5)
	"""

    def start_block_building(self):
        self.bb_timer = threading.Timer(CHECK_INTERVAL,
                                        self.__generate_block_with_tp)
        self.bb_timer.start()

    def stop_block_building(self):
        print('Thread for __generate_block_with_tp is stopped now')
        self.bb_timer.cancel()

    def start(self):
        self.server_state = STATE_STANDBY
        self.cm.start()
        self.start_block_building()

    def join_network(self):
        if self.core_node_host != None:
            self.server_state = STATE_CONNECTED_TO_NETWORK  # 状態:親ノードへ接続中
            self.cm.join_network(self.core_node_host, self.core_node_port)
        else:
            print('This server is running as Genesis Core Node...')

    def shutdown(self):
        self.server_state = STATE_SHUTTING_DOWN  # 状態:切断中
        print('Shutdown server...')
        self.cm.connection_close()
        self.stop_block_building()

    def get_my_current_state(self):
        return self.server_state

    def plz_share_db(self):
        print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")
        print("■■■■■■■■■■■■■ plz_share_db ■■■■■■■■■■■■■■■■■■■■")
        print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")
        new_message = self.cm.get_message_text(Sync_DB3)
        self.cm.send_msg((self.core_node_host, self.core_node_port),
                         new_message)
        print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")

    def get_all_chains_for_resolve_conflict(self):
        print('get_all_chains_for_resolve_conflict called')
        new_message = self.cm.get_message_text(MSG_REQUEST_FULL_CHAIN)
        self.cm.send_msg_to_all_peer(new_message)

    def __generate_block_with_tp(self):

        print('Thread for generate_block_with_tp started!')
        if self.flag_stop_block_build is not True:

            result = self.tp.get_stored_transactions()

            if result == []:
                print('Transaction Pool is empty ...')
                #TODO:Create Empty Block
                new_block = self.bb.generate_new_block("",
                                                       self.prev_block_hash)
                self.bm.set_new_block(new_block.to_dict())
                self.prev_block_hash = self.bm.get_hash(new_block.to_dict())
                message_new_block = self.cm.get_message_text(
                    MSG_NEW_BLOCK,
                    json.dumps(new_block.to_dict(),
                               sort_keys=True,
                               ensure_ascii=False))
                self.cm.send_msg_to_all_peer(message_new_block)
                index = len(result)
                self.tp.clear_my_transactions(index)

            new_tp = self.bm.remove_useless_transaction(result)
            self.tp.renew_my_transactions(new_tp)
            if len(new_tp) == 0:
                pass
            else:
                new_block = self.bb.generate_new_block(new_tp,
                                                       self.prev_block_hash)
                self.bm.set_new_block(new_block.to_dict())
                self.prev_block_hash = self.bm.get_hash(new_block.to_dict())
                message_new_block = self.cm.get_message_text(
                    MSG_NEW_BLOCK,
                    json.dumps(new_block.to_dict(),
                               sort_keys=True,
                               ensure_ascii=False))
                self.cm.send_msg_to_all_peer(message_new_block)
                index = len(result)
                self.tp.clear_my_transactions(index)
        print('Current Blockchain is ... ', self.bm.chain)  # + 省略中")

        if len(self.bm.chain) >= 10:
            main_level.add_db(ldb_p=LDB_P,
                              param_p=PARAM_P,
                              zip_p=ZIP_P,
                              vals=self.bm.chain[:5])
            self.bm.chain = self.bm.chain[5:]
            print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")
            print("保存しました")
            print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")

        print('Current prev_block_hash is ... ', self.prev_block_hash)
        self.flag_stop_block_build = False
        self.is_bb_running = False
        self.bb_timer = threading.Timer(CHECK_INTERVAL,
                                        self.__generate_block_with_tp)
        self.bb_timer.start()

    def __handle_message(self, msg, is_core, peer=None):

        if peer != None:
            if msg[2] == MSG_REQUEST_FULL_CHAIN:
                print('Send our latest blockchain for reply to : ', peer)
                mychain = self.bm.get_my_blockchain()
                print(mychain)
                chain_data = pickle.dumps(mychain, 0).decode()
                new_message = self.cm.get_message_text(RSP_FULL_CHAIN,
                                                       chain_data)
                self.cm.send_msg(peer, new_message)
        else:
            if msg[2] == MSG_NEW_TRANSACTION:
                #msg[4]の型を確認
                if isinstance(msg[4], dict):  # dict
                    print("for_client_msg[4]")
                    # d = json.loads(msg[4]) # json.loads を使って dict に変換
                    b = base64.b64decode(
                        msg[4]['bin'].encode())  # base64 を使ってバイナリから復元
                    with open(
                            dirname +
                            "ZIP_busdata/accept_busdata/server_busdata.zip",
                            "wb") as f:
                        f.write(b)

                    with zipfile.ZipFile(
                            dirname +
                            "ZIP_busdata/accept_busdata/server_busdata.zip"
                    ) as zf:
                        zf.extractall(dirname + "ZIP_busdata/accept_busdata")

                    with open(dirname +
                              "ZIP_busdata/accept_busdata/msg_pub.txt") as f:
                        readdata = f.read().splitlines()
                        print("read txt")
                        new_transaction = json.loads(readdata[0])

                if isinstance(msg[4], str):  # str
                    print("for_server_msg[4]")
                    print(type(msg[4]))
                    new_transaction = json.loads(msg[4])

                else:
                    print("object has no attribute")
                    pass

                type(new_transaction)

                current_transactions = self.tp.get_stored_transactions()
                if new_transaction in current_transactions:
                    print("this is already pooled transaction:")
                    return

                if not is_core:  #from edge node
                    ds = CheckDigitalSignature(new_transaction)
                    CHECK_SIGNATURE = ds.get_flag(
                    )  #ds.check_signature(new_transaction)
                    if CHECK_SIGNATURE == False:
                        print('---------------------------------------')
                        print('DigitalSignature is False')
                        print('---------------------------------------')
                        return
                    else:
                        print('---------------------------------------')
                        print('DigitalSignature is True')
                        print('---------------------------------------')

                    self.tp.set_new_transaction(new_transaction)
                    new_message = self.cm.get_message_text(
                        MSG_NEW_TRANSACTION,
                        json.dumps(new_transaction,
                                   sort_keys=True,
                                   ensure_ascii=False))
                    self.cm.send_msg_to_all_peer(new_message)
                else:
                    self.tp.set_new_transaction(new_transaction)

            elif msg[2] == MSG_NEW_BLOCK:

                if not is_core:
                    print('block received from unknown')
                    return

                # 新規ブロックを検証し、正当なものであればブロックチェーンに追加する
                new_block = json.loads(msg[4])
                print('new_block: ', new_block)
                if self.bm.is_valid_block(self.prev_block_hash,
                                          new_block):  # is new block valid?
                    # ブロック生成が行われていたら一旦停止してあげる(threadingなのでキレイに止まらない場合あり)
                    if self.is_bb_running:
                        self.flag_stop_block_build = True
                    self.prev_block_hash = self.bm.get_hash(new_block)
                    self.bm.set_new_block(new_block)
                else:
                    # ブロックとして不正ではないがVerifyにコケる場合は自分がorphanブロックを生成している
                    # 可能性がある
                    self.get_all_chains_for_resolve_conflict()

            elif msg[2] == RSP_FULL_CHAIN:

                if not is_core:
                    print('blockchain received from unknown')
                    return
                # ブロックチェーン送信要求に応じて返却されたブロックチェーンを検証し、有効なものか検証した上で
                # 自分の持つチェインと比較し優位な方を今後のブロックチェーンとして有効化する
                new_block_chain = pickle.loads(msg[4].encode('utf-8'))
                print(new_block_chain)
                result, pool_4_orphan_blocks = self.bm.resolve_conflicts(
                    new_block_chain)
                print('blockchain received')
                if result is not None:
                    self.prev_block_hash = result
                    if len(pool_4_orphan_blocks) != 0:
                        # orphanブロック群の中にあった未処理扱いになるTransactionをTransactionPoolに戻す
                        new_transactions = self.bm.get_transactions_from_orphan_blocks(
                            pool_4_orphan_blocks)
                        for t in new_transactions:
                            self.tp.set_new_transaction(t)
                else:
                    print('Received blockchain is useless...')
                # self.main_window.set_chain(self.bm.chain)

            elif msg[2] == MSG_ENHANCED:
                # P2P Network を単なるトランスポートして使っているアプリケーションが独自拡張したメッセージはここで処理する。SimpleBitcoin としてはこの種別は使わない
                # self.mpmh.handle_message(msg[4])
                print("MSG_ENHANCED")

        print("")
        print("保存!!>!>!>!>!>!>!>!>!>!>>>!>!")
        print(self.bm.chain)
        print("保存!!>!>!>!>!>!>!>!>!>!>>>!>!")
        print("")

    def __get_myip(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(('8.8.8.8', 80))
        return s.getsockname()[0]
Beispiel #11
0
class ServerCore(object):
    def __init__(self,
                 my_port=50082,
                 core_node_host=None,
                 core_node_port=None):
        self.server_state = STATE_INIT
        print('Initializing server...')
        self.my_ip = self.__get_myip()
        print('Server IP address is set to ... ', self.my_ip)
        self.my_port = my_port
        self.cm = ConnectionManager(self.my_ip, self.my_port,
                                    self.__handle_message, self)
        self.mpmh = MyProtocolMessageHandler()
        self.core_node_host = core_node_host
        self.core_node_port = core_node_port
        self.bb = BlockBuilder()
        self.flag_stop_block_build = True
        self.is_bb_running = False
        if main_level.get_genesis(LDB_P):
            self.bm = BlockchainManager()
            latest_dbd_block = main_level.get_latest_block(LDB_P)
            self.prev_block_hash = self.bm.get_hash(latest_dbd_block)
            block_num = level_param.get_block_num(PARAM_P) + len(self.bm.chain)
            new_block = self.bb.generate_new_block({}, self.prev_block_hash,
                                                   str(block_num), ADDRESS, {},
                                                   self)
            self.bm.set_reconnect_block(new_block.to_dict())
            self.prev_block_hash = self.bm.get_hash(new_block.to_dict())
        else:
            my_genesis_block = self.bb.generate_genesis_block()
            self.bm = BlockchainManager(my_genesis_block.to_dict())
            self.prev_block_hash = self.bm.get_hash(my_genesis_block.to_dict())
        self.tp = TransactionPool()

        if core_node_host and core_node_port:
            self.plz_share_db()
        else:
            self.flag_stop_block_build = False

    def start_block_building(self):
        if RAND_INTERVAL:
            CHECK_INTERVAL = randint(39, 60)
        else:
            CHECK_INTERVAL = INTERVAL
        self.bb_timer = threading.Timer(CHECK_INTERVAL,
                                        self.__generate_block_with_tp)
        self.bb_timer.start()

        self.bb_timer = threading.Timer(CHECK_INTERVAL,
                                        self.__generate_block_with_tp)
        self.bb_timer.start()

    def stop_block_building(self):
        print('Thread for __generate_block_with_tp is stopped now')
        self.bb_timer.cancel()

    def start(self):
        self.server_state = STATE_STANDBY
        self.cm.start()
        self.start_block_building()

    def join_network(self):
        if self.core_node_host is not None:
            self.server_state = STATE_CONNECTED_TO_NETWORK  # 状態:親ノードへ接続中
            self.cm.join_network(self.core_node_host, self.core_node_port)
        else:
            print('This server is running as Genesis Core Node...')

    def shutdown(self):
        self.server_state = STATE_SHUTTING_DOWN  # 状態:切断中
        print('Shutdown server...')
        self.cm.connection_close()
        self.stop_block_building()

    def get_my_current_state(self):
        return self.server_state

    def plz_share_db(self):
        print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")
        print("■■■■■■■■■■■■■■■■■■■■ plz_share_db ■■■■■■■■■■■■■■■■■■■■■■")
        print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")
        new_message = self.cm.get_message_text(SHARE_DB3)
        self.cm.send_msg((self.core_node_host, self.core_node_port),
                         new_message)
        print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")

    def get_all_chains_for_resolve_conflict(self):
        print('get_all_chains_for_resolve_conflict called')
        new_message = self.cm.get_message_text(MSG_REQUEST_FULL_CHAIN)
        self.cm.send_msg_to_all_peer(new_message)

    # def save_block_2_db(self):
    #     # if self.is_bb_running:
    #     #     self.flag_stop_block_build = True
    #     saved_bc = []
    #
    #     if len(self.bm.chain) >= SAVE_BORDER:
    #         saved_bc = self.bm.chain[:SAVE_BORDER_HALF]
    #         self.bm.chain = self.bm.chain[SAVE_BORDER_HALF:]
    #         main_level.add_db(ldb_p=LDB_P, param_p=PARAM_P, zip_p=ZIP_P, vals=saved_bc)
    #         print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")
    #         print("保存しました")
    #         print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")
    #
    #     # self.flag_stop_block_build = False

    def __generate_block_with_tp(self):
        if DEBUG:
            print('Thread for generate_block_with_tp started!')

        try:
            if RAND_INTERVAL:
                CHECK_INTERVAL = randint(39, 60)
            else:
                CHECK_INTERVAL = INTERVAL
            print(
                "■■■■■■■■■■■■■■■■■■■ Current BC ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■"
            )
            print(self.bm.chain)

            # self.save_block_2_db()
            saved_bcs = self.bm.save_block_2_db()

            print("txs_hash len:", self.tp.get_txs_hash_len())
            print("txs_hash:", self.tp.get_txs_hash())

            # txs_hash = self.tp.get_txs_hash().values()
            # for t in txs_hash:
            #     print(f"addrs:{t} / len:{len(t)}")

            if saved_bcs:
                prev_ts = 0.0
                ts_list = []
                for saved_bc in saved_bcs:
                    # genesis_blockはトランザクションがハッシュ値なのでloadsできない
                    try:
                        self.tp.clear_my_hash_txs(
                            json.loads(saved_bc["transactions"]))
                    except json.decoder.JSONDecodeError:
                        pass

                    if prev_ts == 0.0:
                        prev_ts = saved_bc["timestamp"]
                    else:
                        ts_list.append(saved_bc["timestamp"] - prev_ts)
                        prev_ts = saved_bc["timestamp"]

                print("■■■■■■■■■■■■■■■■■■■")
                print("平均ブロック生成時間")
                print(sum(ts_list) / len(saved_bcs))
                print("■■■■■■■■■■■■■■■■■■■")

            print("txs_hash len:", self.tp.get_txs_hash_len())
            # print("txs_hash:", self.tp.get_txs_hash())

            # while self.flag_stop_block_build is not True:
            if self.flag_stop_block_build is not True:
                # new_tp = self.tp.get_stored_transactions2()
                # new_tp = deepcopy(self.tp.transactions)
                new_tp = self.tp.get_stored_transactions3()
                if DEBUG:
                    print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")
                    print("transactions", new_tp)
                    print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")

                # if not result:
                #     print('Transaction Pool is empty ...')
                #     new_block = self.bb.generate_new_block("", self.prev_block_hash)
                #     self.bm.set_new_block(new_block.to_dict())
                #     self.prev_block_hash = self.bm.get_hash(new_block.to_dict())
                #     # message_new_block = self.cm.get_message_text(MSG_NEW_BLOCK,
                #     #                                              json.dumps(new_block.to_dict(), sort_keys=True,
                #     #                                                         ensure_ascii=False))
                #     message_new_block = self.cm.get_message_text(MSG_NEW_BLOCK, json.dumps(new_block.to_dict()))
                #     self.cm.send_msg_to_all_peer(message_new_block)
                #     index = len(result)
                #     self.tp.clear_my_transactions(index)

                # new_tp = self.bm.remove_useless_transaction(result)
                # self.tp.renew_my_transactions(new_tp)

                # if len(new_tp) == 0:  # TODO TPが0のとき、終わるように。コメントアウトで切り替え
                #     break

                # TODO ここでiteration errorでる。値変わってるせい。
                txs_hash = self.tp.get_txs_hash()
                block_num = level_param.get_block_num(PARAM_P) + len(
                    self.bm.chain)
                new_block = self.bb.generate_new_block(new_tp,
                                                       self.prev_block_hash,
                                                       str(block_num), ADDRESS,
                                                       txs_hash, self)

                new_block_dic = new_block.to_dict()

                if not new_block_dic:
                    print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")
                    print("■■■■■■■■■■■■■■ 負け!w ■■■■■■■■■■■■■■■")
                    print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")
                    self.flag_stop_block_build = False
                    self.is_bb_running = False
                    self.bb_timer = threading.Timer(
                        CHECK_INTERVAL, self.__generate_block_with_tp)
                    self.bb_timer.start()
                    return
                elif int(new_block_dic["block_number"]) < int(
                        self.bm.chain[-1]["block_number"]):
                    print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")
                    print("■■■■■■■■■■■■■■ YOU LOSE ■■■■■■■■■■■■■■■")
                    print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")
                    self.flag_stop_block_build = False
                    self.is_bb_running = False
                    self.bb_timer = threading.Timer(
                        CHECK_INTERVAL, self.__generate_block_with_tp)
                    self.bb_timer.start()
                    return
                # elif (int(new_block_dic["block_number"]) == int(self.bm.chain[-1]["block_number"])) and (
                #         new_block_dic["total_majority"] <= self.bm.chain[-1]["total_majority"]):
                #     print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")
                #     print("■■■■■■■■■■■■■■ u r 少数派 ■■■■■■■■■■■■■■")
                #     print("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■")
                #     self.flag_stop_block_build = False
                #     self.is_bb_running = False
                #     self.bb_timer = threading.Timer(CHECK_INTERVAL, self.__generate_block_with_tp)
                #     self.bb_timer.start()
                #     return

                print("ブロック生成")
                print(new_block_dic)
                if len(self.bm.chain) >= 2:
                    print("ブロック生成時間")
                    print(
                        self.__calculate_gene_time(self.bm.chain[-2],
                                                   self.bm.chain[-1]))

                if self.bm.set_new_block(new_block.to_dict(),
                                         self.prev_block_hash):
                    self.prev_block_hash = self.bm.get_hash(
                        new_block.to_dict())

                    # self.save_block_2_db()

                    message_new_block = self.cm.get_message_text(
                        MSG_NEW_BLOCK, json.dumps(new_block.to_dict()))

                    self.cm.send_msg_to_all_peer(message_new_block)

                    # index = len(result)
                    # self.tp.clear_my_transactions(index)
                    # 排除対象になったtxを取り込み済みtxから除く
                    exclusion_txs = new_block.get_exclusion_tx()
                    for ex_tx in exclusion_txs:
                        try:
                            del new_tp[ex_tx]
                        except KeyError:
                            pass
                    self.tp.add_through_count(exclusion_txs)
                    self.tp.clear_my_transactions2(new_tp)

                    with open(f'logs/{ADDRESS}_generate_block.csv', 'a') as f:
                        writer = csv.writer(f)
                        writer.writerow([
                            datetime.now(),
                            new_block_dic["block_number"],
                            # new_block_dic["total_majority"],
                            new_block_dic["nTx"],
                            # new_block_dic["over_half"],
                        ])

                # break

            # print('Current prev_block_hash is ... ', self.prev_block_hash)
            self.flag_stop_block_build = False
            self.is_bb_running = False
            self.bb_timer = threading.Timer(CHECK_INTERVAL,
                                            self.__generate_block_with_tp)
            self.bb_timer.start()

        except:
            with open(f"logs/{ADDRESS}_error.log", "a") as f:
                print(traceback.print_exc(file=f))

    def __handle_message(self, msg, is_core, peer=None):

        if peer:
            if msg[2] == MSG_REQUEST_FULL_CHAIN:
                if DEBUG:
                    print('Send our latest blockchain for reply to : ', peer)
                mychain = self.bm.get_my_blockchain()
                if DEBUG:
                    print(mychain)
                chain_data = pickle.dumps(mychain, 0).decode()
                new_message = self.cm.get_message_text(RSP_FULL_CHAIN,
                                                       chain_data)
                self.cm.send_msg(peer, new_message)
        else:
            if msg[2] == MSG_NEW_TRANSACTION:
                # 新規transactionを登録する処理を呼び出す
                new_transaction = json.loads(msg[4])
                bload_tx = deepcopy(new_transaction)

                if DEBUG:
                    print("received new_transaction", new_transaction)
                # current_transactions = self.tp.get_stored_transactions()

                # if DEBUG:
                #     print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
                #     print("current_transactions:", current_transactions)
                #     print("current_transactions type:", type(current_transactions))
                #     if current_transactions:
                #         print("current_transactions [0]:", current_transactions[0])
                #         print("current_transactions [0] type:", type(current_transactions[0]))
                #     print("new_transaction:", new_transaction)
                #     print("new_transaction type:", type(new_transaction))
                #     if new_transaction:
                #         print("new_transaction [0]:", new_transaction[0])
                #         print("new_transaction [0]:", type(new_transaction[0]))
                #     print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")

                # if new_transaction in current_transactions:
                #     if DEBUG:
                #         print("this is already pooled transaction:", new_transaction)
                #     return

                # only_new_tx = self.tp.check_duplicates(new_transaction)
                # if not only_new_tx:
                #     return

                # if not self.tp.check_duplicates_and_set_tx(new_transaction):
                #     return
                self.tp.check_duplicates_and_set_tx(new_transaction)

                # self.tp.set_new_transaction(only_new_tx)

                if not is_core:
                    new_message = self.cm.get_message_text(
                        MSG_NEW_TRANSACTION, json.dumps(bload_tx))
                    self.cm.send_msg_to_all_peer(new_message)

            elif msg[2] == MSG_NEW_BLOCK:

                if not is_core:
                    print('block received from unknown')
                    return

                # 新規ブロックを検証し、正当なものであればブロックチェーンに追加する

                new_block = json.loads(msg[4])
                if DEBUG:
                    print('new_block: ', new_block)

                # if (int(self.bm.chain[-1]["block_number"]) > int(new_block["block_number"])) or (
                #         self.bm.chain[-1]["total_majority"] >= new_block["total_majority"] and (
                #         int(self.bm.chain[-1]["block_number"]) == int(new_block["block_number"]))):
                #     return
                if int(self.bm.chain[-1]["block_number"]) > int(
                        new_block["block_number"]):
                    return

                try:
                    if self.bm.is_valid_block(self.prev_block_hash, new_block):
                        # ブロック生成が行われていたら一旦停止してあげる(threadingなのでキレイに止まらない場合あり)
                        # if self.is_bb_running:
                        #     self.flag_stop_block_build = True

                        # self.prev_block_hash = self.bm.get_hash(new_block)
                        # self.bm.set_new_block(new_block)

                        if self.bm.set_new_block(new_block,
                                                 self.prev_block_hash):
                            self.prev_block_hash = self.bm.get_hash(new_block)
                            self.tp.clear_my_transactions2(
                                json.loads(new_block["addrs"]))
                            with open(f'logs/{ADDRESS}_most_longest.csv',
                                      'a') as f:
                                writer = csv.writer(f)
                                writer.writerow([
                                    datetime.now(),
                                    new_block["block_number"],
                                    # new_block["total_majority"],
                                    new_block["nTx"],
                                    # new_block["over_half"],
                                ])

                    # elif self.bm.is_valid_block_booby(new_block):
                    #     if (self.bm.chain[-1]["total_majority"] < new_block["total_majority"]) and (int(
                    #             self.bm.chain[-1]["block_number"]) == int(new_block["block_number"])):
                    #         deleted_block = self.bm.replace_latest_block(new_block)
                    #         if deleted_block:
                    #             self.prev_block_hash = self.bm.get_hash(new_block)
                    #             self.tp.increment_tx(deleted_block, new_block)
                    #             self.tp.clear_my_transactions2(json.loads(new_block["addrs"]))
                    #             with open(f'logs/{ADDRESS}_most_majority.csv', 'a') as f:
                    #                 writer = csv.writer(f)
                    #                 writer.writerow([
                    #                     datetime.now(),
                    #                     new_block["block_number"],
                    #                     new_block["total_majority"],
                    #                     new_block["nTx"],
                    #                     new_block["over_half"],
                    #                 ])

                    else:
                        # ブロックとして不正ではないがVerifyにコケる場合は自分がorphanブロックを生成している
                        # 可能性がある
                        # if self.is_bb_running:  # TODO 試しで追加
                        #     self.flag_stop_block_build = True

                        self.get_all_chains_for_resolve_conflict()
                except:
                    with open(f"logs/{ADDRESS}_error_1.log", "a") as f:
                        print(traceback.print_exc(file=f))

            elif msg[2] == RSP_FULL_CHAIN:
                try:
                    if not is_core:
                        if DEBUG:
                            print('blockchain received from unknown')
                        return
                    # ブロックチェーン送信要求に応じて返却されたブロックチェーンを検証し、有効なものか検証した上で
                    # 自分の持つチェインと比較し優位な方を今後のブロックチェーンとして有効化する
                    new_block_chain = pickle.loads(msg[4].encode('utf8'))

                    # if ((int(new_block_chain[-1]["block_number"]) > int(self.bm.chain[-1]["block_number"])) or (
                    #         (int(new_block_chain[-1]["block_number"]) == int(self.bm.chain[-1]["block_number"])) and (
                    #         new_block_chain[-1]["total_majority"] > self.bm.chain[-1]["total_majority"]))) and (
                    #         (int(new_block_chain[0]["block_number"]) == int(self.bm.chain[0]["block_number"])) or (
                    #         self.bm.chain[0]["block_number"] == "0") or (len(self.bm.chain) < SAVE_BORDER_HALF)):
                    if (int(new_block_chain[-1]["block_number"]) > int(
                            self.bm.chain[-1]["block_number"])) and (
                                (int(new_block_chain[0]["block_number"])
                                 == int(self.bm.chain[0]["block_number"])) or
                                (self.bm.chain[0]["block_number"] == "0") or
                                (len(self.bm.chain) < SAVE_BORDER_HALF)):
                        result, pool_4_orphan_blocks = self.bm.resolve_conflicts(
                            new_block_chain)

                        if result and self.cm.sync_flag:
                            try:
                                self.tp.justification_conflict(
                                    self.bm.chain[-6:])
                            except:
                                with open(f"logs/{ADDRESS}_error_2.log",
                                          "a") as f:
                                    print(traceback.print_exc(file=f))

                        if DEBUG:
                            print('blockchain received')
                        if result is not None:
                            self.prev_block_hash = result
                            # if len(pool_4_orphan_blocks) != 0:
                            #     # orphanブロック群の中にあった未処理扱いになるTransactionをTransactionPoolに戻す
                            #     new_transactions = self.bm.get_transactions_from_orphan_blocks(pool_4_orphan_blocks)
                            #     for t in new_transactions:
                            #         self.tp.set_new_transaction(t)
                        else:
                            if DEBUG:
                                print('Received blockchain is useless...')

                    # self.flag_stop_block_build = False
                except:
                    with open(f"logs/{ADDRESS}_error_3.log", "a") as f:
                        print(traceback.print_exc(file=f))

            elif msg[2] == MSG_ENHANCED:
                # P2P Network を単なるトランスポートして使っているアプリケーションが独自拡張したメッセージはここで処理する。SimpleBitcoin としてはこの種別は使わない
                self.mpmh.handle_message(msg[4])

    def __get_myip(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(('8.8.8.8', 80))
        return s.getsockname()[0]

    def __calculate_gene_time(self, prev_block: dict, new_block: dict):
        prev_ts = prev_block["timestamp"]
        # prev_ts = 1587105439.753553
        new_ts = new_block["timestamp"]
        # new_ts = 1587105451.5021372
        gene_time = new_ts - prev_ts
        return gene_time

    def format_bc(self):
        oldest_memory_block = self.bm.chain[0]
        self.bm.chain = self.bm.chain[:1]
        self.bm.set_reconnect_block(oldest_memory_block)
        self.prev_block_hash = self.bm.get_hash(oldest_memory_block)
Beispiel #12
0
class ServerCore:

  def __init__(self, my_port = 50082, core_node_host=None, core_node_port=None, pass_phrase=None):
    self.server_state = STATE_INIT
    print('Initializing server...')
    self.my_ip = self.__get_myip()
    print('Server IP address is set to ...', self.my_ip)
    self.my_port = my_port
    self.cm = ConnectinManager(self.my_ip, self.my_port, self.__handle_message)
    self.mpmh = MyProtocolMessageHandler()
    self.core_node_host = core_node_host
    self.core_node_port = core_node_port
    self.bb = BlockBuilder()
    my_genesis_block = self.bb.generate_genesis_block()
    self.bm = BlockchainManager(my_genesis_block.to_dict())
    self.prev_block_hash = self.bm.get_hash(my_genesis_block.to_dict())
    self.tp = TransactionPool()
    self.is_bb_running = False
    self.flag_stop_block_build = False
    self.mpm_store = MessageStore()
    self.km = KeyManager(None, pass_phrase)
    self.rsa_util = RSAUtil()
    self.um = UTXOManager(self.km.my_address())

  def start_block_building(self):
    self.bb_timer = threading.Timer(CHECK_INTERVAL, self.__generate_block_with_tp)
    self.bb_timer.start()

  def stop_block_building(self):
    self.bb_timer = threading.Timer(CHECK_INTERVAL, self.__generate_block_with_tp)
    self.bb_timer.start()

  def stop_block_building(self):
    print('Thread for __generate_block_with_tp is stopped now')
    self.bb_timer.cancel()

  def start(self):
    self.server_state = STATE_STANDBY
    self.cm.start()
    self.start_block_building()

  def join_network(self):
    if self.core_node_host != None:
      self.server_state = STATE_CONNECTED_TO_CENTRAL
      self.server_state = STATE_CONNECTION_TO_CENTRAL
      self.cm.join_network(self.core_node_host, self.core_node_port)
    else:
      print('This server si running as Genesis Core Node...')

  def shutdown(self):
    self.server_state = STATE_SHUTTING_DOWN
    self.flag_stop_block_build = True
    print('Shutdown server...')
    self.cm.connection_close()
    self.stop_block_building()

  def get_my_current_state(self):
    return self.server_state

  def send_req_full_chain_to_my_peer(self):
    print()
    new_message = self.cm.get_message_text(MSG_REQUEST_FULL_CHAIN)
    self.cm.send_msg((self.core_node_host, self.core_node_port),new_message)

  def get_all_chains_for_resolve_conflict(self):
    print('send_req_full_chain_to_my_central called')
    new_message = self.cm.get_message_text(MSG_REQUEST_FULL_CHAIN)
    self.cm.send_msg((self.core_node_host, self.core_port),new_message)

  def get_all_cahins_for_resolve_conflict(self):
    print('get_all_chains_for_resolve_conflict called')
    new_message = self.cm.get_message_text(MSG_REQUEST_FULL_CHAIN)
    self.cm.send_msg_to_all_peer(new_message)

  def __generate_block_with_tp(self):

    print('Thread for generate_block_with_tp started!')
    while not self.flag_stop_block_build:
      self.is_bb_running = True
      prev_hash = copy.copy(self.prev_block_hash)
      result = self.get_stored_transactions()
      if len(result) == 0:
        print('Transaction Pool is empty ...')
        result = self.tp.get_stored_transactions()
        if len(result) == 0:
          print('Transaction Pool is empty ...')
          break
        new_tp = self.bm.remove_useless_transaction(result)
        self.tp.renew_my_transactions(new_tp)
        if len(new_tp) == 0:
          break

        total_fee = self.tp_get_total_fee_from_tp()
        total_fee += 30
        my_coinbase = CoinbaseTransaction(self.km.my_address(), total_fee)
        transactions_4_block = copy.deepcopy(new_tp)
        transactions_4_block.insert(0, my_coinbase_t.to_dict())
        new_block = self.bb.generate_new_block(transactions_4_block, prev_hash)
        if new_block.to_dict()['previous_block'] == self.prev_block_hash:
          self.bm.set_new_block(new_block.to_dict())
          self.prev_block_hash = self.bm.get_hash(new_block.to_dict())
          msg_new_block = self.cm.get_message_text(MSG_NEW_BLOCK, json.dumps(new_block.to_dict()))
          self.cm.send_msg_to_all(msg_new_block)
          index = len(new_tp)
          self.tp.clear_my_my_transactions(index)
          break
        else:
          print('Bad Block. It seems someone already win the Pow.')
          beak

      print('Current Blockchain is ...', self.bm.chain)
      print('Current prev_block_hash is ... ', self.prev_block_hash)
      self.flag_stop_block_build = False
      self.is_bb_running = False
      self.bb_timer = threading.Timer(CHECK_INTERVAL, self.__generate_block_with_tp)
      self.bb_timer.start()

  def _check-availability_of_transaction(self, transaction):
    """
    """
    v_result, used_outputs = self.rsa_util.verify_sbc_transaction_sig(transaction)
    if v_result is not True:
      print('signature verification error on new transaction')
      return False
   
    for used_o in used_outputs:
      print('used_o', used_o)
      bm_v_result = self.bm.has_this_output_in_my_chain(used_o)
      tp_v_result = self.tp.has_this_output_in_my_tp(used_o)
      bm_v_result2 = self.bm.is_valid_output_in_my_chain(used_o)
      if bm_v_result:
        print('This TransactionOutput is already used', used_o)
        return False:
      if tp_v_result:
        print('This TransactionOutput is already stored in the TransactionPool', used_o)
        return False
      if bm_v_result2 is not True:
        print('This TransactionOutput is unknown', used_o)
        return False

    return True