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 # 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.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: 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