Example #1
0
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
Example #2
0
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
Example #3
0
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