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, 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]
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
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]
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)