def new_insert_block(block, f_time=True, f_sign=True): t = time() with new_block_lock: fixed_delay = time() - t try: # Check if f_time: check_block_time(block, fixed_delay) check_block(block) if f_sign: fill_verified_addr_single(block) for tx in block.txs: check_tx(tx=tx, include_block=block) if f_time: check_tx_time(tx) # Recode chain_builder.new_block(block) for tx in block.txs: user_account.affect_new_tx(tx) # insert database chain_builder.batch_apply() # inner streaming if not stream.is_disposed: stream.on_next(block) log.info("check success {}Sec {}".format(round(time() - t, 3), block)) return True except BlockChainError as e: log.warning("Reject new block by \"{}\"".format(e), exc_info=True) log.debug("Reject block => {}".format(block.getinfo())) return False except Exception as e: message = "New insert block error, \"{}\"".format(e) log.warning(message, exc_info=True) return False
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) # WebSocket apiに通知 if P.NEW_CHAIN_INFO_QUE: P.NEW_CHAIN_INFO_QUE.put_nowait(('block', block.getinfo())) 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 fast_sync_chain(): assert V.PC_OBJ is not None, "Need PeerClient start before." global f_changed_status back_thread = Thread(target=background_sync_chain, name='BackSync', daemon=True) back_thread.start() start = time() # 外部Nodeに次のBlockを逐一尋ねる failed_num = 0 before_block = builder.best_block index_height = before_block.height + 1 logging.debug("Start sync by {}".format(before_block)) while failed_num < 5: if index_height in block_stack: new_block = block_stack[index_height] with write_protect_lock: del block_stack[index_height] elif backend_processing_lock.locked(): sleep(0.1) continue else: with backend_processing_lock: logging.debug( "Stack blocks on front form {}".format(index_height)) r = ask_node(cmd=DirectCmd.BIG_BLOCKS, data={'height': index_height}) if isinstance(r, str): logging.debug("NewBLockGetError:{}".format(r)) before_block = builder.get_block( before_block.previous_hash) index_height = before_block.height + 1 failed_num += 1 continue elif isinstance(r, list): waiter = Waiter(0) waiter.set() waiter = put_to_block_stack(r, waiter) if waiter is None or len(block_stack) == 0: break else: waiter.wait() continue else: failed_num += 1 logging.debug("Not correct format BIG_BLOCKS.") continue # Base check base_check_failed_msg = None if before_block.hash != new_block.previous_hash: base_check_failed_msg = "Not correct previous hash {}".format( new_block) # proof of work check if not new_block.pow_check(): base_check_failed_msg = "Not correct work hash {}".format( new_block) # rollback if base_check_failed_msg is not None: before_block = builder.get_block(before_block.previous_hash) index_height = before_block.height + 1 failed_num += 1 for height in tuple(block_stack.keys()): if height >= index_height: del block_stack[height] logging.debug(base_check_failed_msg) continue # TX check if len(new_block.txs) > 1: with closing(create_db(V.DB_ACCOUNT_PATH)) as db: cur = db.cursor() for tx in new_block.txs: if tx.type in (C.TX_POS_REWARD, C.TX_POW_REWARD): continue check_tx(tx=tx, include_block=None) tx_builder.put_unconfirmed(tx=tx, outer_cur=cur) db.commit() # Block check check_block(new_block) for tx in new_block.txs: tx.height = new_block.height check_tx(tx=tx, include_block=new_block) # Chainに挿入 builder.new_block(new_block) for tx in new_block.txs: user_account.affect_new_tx(tx) builder.batch_apply() f_changed_status = True # 次のBlock failed_num = 0 before_block = new_block index_height = before_block.height + 1 # ロギング if index_height % 100 == 0: logging.debug("Update block {} now...".format(index_height + 1)) # Unconfirmed txを取得 logging.info("Finish get block, next get unconfirmed.") r = None while not isinstance(r, dict): r = ask_node(cmd=DirectCmd.UNCONFIRMED_TX, f_continue_asking=True) for txhash in r['txs']: if txhash in tx_builder.unconfirmed: continue try: r = ask_node(cmd=DirectCmd.TX_BY_HASH, data={'txhash': txhash}, f_continue_asking=True) tx = TX(binary=r['tx']) tx.signature = r['sign'] check_tx_time(tx) check_tx(tx, include_block=None) tx_builder.put_unconfirmed(tx) except BlockChainError: logging.debug("Failed get unconfirmed {}".format( hexlify(txhash).decode())) # 最終判断 reset_good_node() set_good_node() my_best_height = builder.best_block.height best_height_on_network, best_hash_on_network = get_best_conn_info() if best_height_on_network <= my_best_height: logging.info( "Finish update chain data by network. {}Sec [{}<={}]".format( round(time() - start, 1), best_height_on_network, my_best_height)) return True else: logging.debug("Continue update chain, {}<={}".format( best_height_on_network, my_best_height)) return False