def check_new_tx(tx: TX): if tx.height is not None: raise CheckWatchError('is not unconfirmed? {}'.format(tx)) elif tx.message_type != C.MSG_BYTE: return elif tx.type == C.TX_CONCLUDE_CONTRACT: # 十分な署名が集まったら消す c_address, start_hash, c_storage = bjson.loads(tx.message) v = get_validator_object(c_address=c_address, stop_txhash=tx.hash) related_list = check_related_address(v.validators) if related_list: data = (time(), tx, related_list, c_address, start_hash, c_storage) watching_tx[tx.hash] = data NewInfo.put((C_Conclude, False, data)) elif tx.type == C.TX_VALIDATOR_EDIT: # 十分な署名が集まったら消す c_address, new_address, flag, sig_diff = bjson.loads(tx.message) v = get_validator_object(c_address=c_address, stop_txhash=tx.hash) related_list = check_related_address(v.validators) if related_list: data = (time(), tx, related_list, c_address, new_address, flag, sig_diff) watching_tx[tx.hash] = data NewInfo.put((C_Validator, False, data)) else: pass
def put_unconfirmed(self, tx, outer_cur=None): assert tx.height is None, 'Not unconfirmed tx {}'.format(tx) if tx.type in (C.TX_POW_REWARD, C.TX_POS_REWARD): return # It is Reword tx elif tx.hash in self.unconfirmed: logging.debug('Already unconfirmed tx. {}'.format(tx)) return self.unconfirmed[tx.hash] = tx if tx.hash in self.chained_tx: logging.debug('Already chained tx. {}'.format(tx)) return user_account.affect_new_tx(tx, outer_cur) NewInfo.put(obj=tx)
def run(): global f_running f_running = True logging.info("Start emulators debug={}".format(f_debug)) while f_running: try: data = NewInfo.get(channel='emulator', timeout=1) if not isinstance(data, tuple) or len(data) != 3: continue cmd, is_public, data_list = data if cmd == C_RequestConclude: # c_transfer tx is confirmed, create conclude tx _time, start_tx, related_list, c_address, c_method, c_args = data_list for e in emulators: if e.c_address != c_address: continue # elif c_method == M_INIT: # pass # elif c_method == M_UPDATE: # pass else: e.emulate(start_tx=start_tx, c_method=c_method, c_args=c_args, f_debug=f_debug) # elif cmd == C_Conclude: # # sign already created conclude tx # _time, tx, related_list, c_address, start_hash, c_storage = data_list else: pass except NewInfo.empty: pass except Exception: logging.error("Emulator", exc_info=True)
def new_insert_block(block, time_check=False): t = time.time() with global_lock: fixed_delay = time.time() - t try: # Check if time_check: check_block_time(block, fixed_delay) check_block(block) batch_sign_cashe(block.txs) for tx in block.txs: check_tx(tx=tx, include_block=block) if time_check: check_tx_time(tx) # Recode builder.new_block(block) for tx in block.txs: user_account.affect_new_tx(tx) # Delete from sign-cashe delete_txhash_set = set() batched_blocks = builder.batch_apply() for del_block in batched_blocks: delete_txhash_set.update({tx.hash for tx in del_block.txs}) delete_signed_cashe(delete_txhash_set) NewInfo.put(obj=block) logging.info("New block accepted {}Sec {}.".format( round(time.time() - t, 3), block)) return True except BlockChainError as e: logging.warning("Reject new block by \"{}\"".format(e)) delay = time.time( ) - builder.best_block.time - V.BLOCK_GENESIS_TIME if delay > 10800: # 3hours logging.warning( "{}Min before block inserted, too old on DB!".format( delay // 60)) P.F_NOW_BOOTING = True return False except BaseException as e: message = "New insert block error, \"{}\"".format(e) logging.warning(message, exc_info=True) add_failed_mark() return False
def check_new_block(block: Block): for tx in block.txs: if tx.height is None: raise CheckWatchError('is unconfirmed? {}'.format(tx)) elif tx.message_type != C.MSG_BYTE: continue elif tx.type == C.TX_TRANSFER: # ConcludeTXを作成するべきフォーマットのTXを見つける c_address, c_method, redeem_address, c_args = bjson.loads( tx.message) v = get_validator_object(c_address=c_address) related_list = check_related_address(v.validators) if related_list: data = (time(), tx, related_list, c_address, c_method, redeem_address, c_args) watching_tx[tx.hash] = data NewInfo.put((C_RequestConclude, False, data)) elif tx.type == C.TX_CONCLUDE_CONTRACT: if tx.hash in watching_tx: # try to delete c_transfer_tx and conclude_tx _time, _tx, _related_list, _c_address, start_hash, c_storage = watching_tx[ tx.hash] if start_hash in watching_tx: del watching_tx[start_hash] del watching_tx[tx.hash] data = (time(), tx) NewInfo.put((C_FinishConclude, False, data)) elif tx.type == C.TX_VALIDATOR_EDIT: if tx.hash in watching_tx: del watching_tx[tx.hash] data = (time(), tx) NewInfo.put((C_FinishValidator, False, data)) else: pass
def loop(): logging.info("Watching contract start.") while not P.F_STOP and P.F_WATCH_CONTRACT: try: obj = NewInfo.get(channel='watch contract', timeout=2) if isinstance(obj, TX): check_new_tx(tx=obj) elif isinstance(obj, Block): check_new_block(block=obj) else: pass except NewInfo.empty: pass except CheckWatchError as e: logging.error(e) except Exception as e: logging.error(e, exc_info=True) logging.info("Close watching contract.")
def _loop(): logging.info("start websocket loop.") while not P.F_STOP: try: data = NewInfo.get(channel='websocket', timeout=1) if isinstance(data, Block): send_websocket_data(cmd=CMD_NEW_BLOCK, data=data.getinfo(), is_public_data=True) elif isinstance(data, TX): send_websocket_data(cmd=CMD_NEW_TX, data=data.getinfo(), is_public_data=True) elif isinstance(data, tuple): cmd, is_public, data_list = data if cmd == C_Conclude: _time, tx, related_list, c_address, start_hash, c_storage = data_list send_data = OrderedDict() send_data['c_address'] = c_address send_data['hash'] = hexlify(tx.hash).decode() send_data['time'] = _time send_data['tx'] = tx.getinfo() send_data['related'] = related_list send_data['start_hash'] = hexlify(start_hash).decode() send_data['c_storage'] = decode(c_storage) elif cmd == C_Validator: _time, tx, related_list, c_address, new_address, flag, sig_diff = data_list send_data = OrderedDict() send_data['c_address'] = c_address send_data['hash'] = hexlify(tx.hash).decode() send_data['time'] = _time send_data['tx'] = tx.getinfo() send_data['related'] = related_list send_data['new_address'] = new_address send_data['flag'] = flag send_data['sig_diff'] = sig_diff elif cmd == C_RequestConclude: _time, tx, related_list, c_address, c_method, c_args = data_list send_data = OrderedDict() send_data['c_address'] = c_address send_data['hash'] = hexlify(tx.hash).decode() send_data['time'] = _time send_data['tx'] = tx.getinfo() send_data['related'] = related_list send_data['c_method'] = c_method send_data['c_args'] = decode(c_args) elif cmd == C_FinishConclude or cmd == C_FinishValidator: _time, tx = data_list send_data = OrderedDict() send_data['hash'] = hexlify(tx.hash).decode() send_data['time'] = _time send_data['tx'] = tx.getinfo() else: logging.warning("Not found cmd {}".format(cmd)) continue send_websocket_data(cmd=cmd, data=send_data, is_public_data=is_public) except NewInfo.empty: pass logging.info("close websocket loop.")
def run(): global f_running with lock: f_running = True # wait for booting_mode finish while P.F_NOW_BOOTING: sleep(1) logging.info("Start emulators, check unconfirmed.") unconfirmed_data = list() for tx in sorted(tx_builder.unconfirmed.values(), key=lambda x: x.time): if tx.type != C.TX_CONCLUDE_CONTRACT: continue try: c_address, start_hash, c_storage = bjson.loads(tx.message) for em in emulators: if c_address == em.c_address: break else: continue start_tx = tx_builder.get_tx(txhash=start_hash) c_address2, c_method, redeem_address, c_args = bjson.loads(start_tx.message) if c_address != c_address2: continue is_public = False data_list = (time(), start_tx, 'dummy', c_address, c_method, redeem_address, c_args) data = (C_RequestConclude, is_public, data_list) unconfirmed_data.append(data) except Exception: logging.debug("Failed check unconfirmed ConcludeTX,", exc_info=True) logging.info("Start listening NewInfo, need to emulate {} txs.".format(len(unconfirmed_data))) while f_running: try: if len(unconfirmed_data) > 0: data = unconfirmed_data.pop(0) else: data = NewInfo.get(channel='emulator', timeout=1) if not isinstance(data, tuple) or len(data) != 3: continue cmd, is_public, data_list = data if cmd == C_RequestConclude: # c_transfer tx is confirmed, create conclude tx _time, start_tx, related_list, c_address, c_method, redeem_address, c_args = data_list for e in emulators: if e.c_address != c_address: continue elif c_method == M_INIT: logging.warning("No work on init.") # elif c_method == M_UPDATE: # pass else: if e.f_claim_gas: gas_limit = 0 for address, coin_id, amount in start_tx.outputs: if address == c_address and coin_id == 0: gas_limit += amount else: gas_limit = None # No limit on gas consumption, turing-complete result, emulate_gas = execute( c_address=c_address, genesis_block=genesis_block, start_tx=start_tx, c_method=c_method, redeem_address=redeem_address, c_args=c_args, gas_limit=gas_limit, f_show_log=True) claim_emulate_gas = emulate_gas if e.f_claim_gas else 0 broadcast(c_address=c_address, start_tx=start_tx, redeem_address=redeem_address, emulate_gas=claim_emulate_gas, result=result, f_debug=f_debug) # elif cmd == C_Conclude: # # sign already created conclude tx # _time, tx, related_list, c_address, start_hash, c_storage = data_list else: pass except NewInfo.empty: pass except BlockChainError: logging.warning("Emulator", exc_info=True) except Exception: logging.error("Emulator", exc_info=True)