Example #1
0
 def new_block(data):
     try:
         new_block = fill_newblock_info(data)
     except BlockChainError as e:
         warning = 'Do not accept block "{}"'.format(e)
         log.warning(warning)
         return False
     except Exception:
         error = "error on accept new block"
         log.error(error, exc_info=True)
         return False
     try:
         if new_insert_block(new_block):
             update_info_for_generate()
             log.info("Accept new block {}".format(new_block))
             return True
         else:
             return False
     except BlockChainError as e:
         error = 'Failed accept new block "{}"'.format(e)
         log.error(error, exc_info=True)
         return False
     except Exception:
         error = "error on accept new block"
         log.error(error, exc_info=True)
         return False
Example #2
0
def mined_newblock(que):
    """new thread, broadcast mined block to network"""
    assert V.P2P_OBJ, "PeerClient is None"
    while not P.F_STOP:
        try:
            new_block = que.get(timeout=1)
            new_block.create_time = int(time())
            if P.F_NOW_BOOTING:
                log.debug("self reject, mined but now booting")
                continue
            elif new_block.height != chain_builder.best_block.height + 1:
                log.debug("self reject, mined but its old block")
                continue
            else:
                log.debug("Mined block check success")
                if new_insert_block(new_block):
                    log.info("Mined new block {}".format(new_block.getinfo()))
                else:
                    log.debug("self reject, cannot new insert")
                    update_info_for_generate()
                    continue
            proof_tx = new_block.txs[0]
            txs_hash_list = [tx.hash for tx in new_block.txs]
            data = {
                'cmd': BroadcastCmd.NEW_BLOCK,
                'data': {
                    'binary': new_block.b,
                    'height': new_block.height,
                    'txs': txs_hash_list,
                    'proof': proof_tx,
                    'block_flag': new_block.flag,
                }
            }
            try:
                V.P2P_OBJ.send_command(cmd=Peer2PeerCmd.BROADCAST, data=data)
                log.info("Success broadcast new block {}".format(new_block))
                update_info_for_generate()
            except TimeoutError:
                log.warning(
                    "Failed broadcast new block, other nodes don\'t accept {}".
                    format(new_block.getinfo()))
        except queue.Empty:
            if V.P2P_OBJ.f_stop:
                log.debug("Mined new block closed")
                break
        except BlockChainError as e:
            log.error('Failed mined new block "{}"'.format(e))
        except Exception as e:
            log.error("mined_newblock()", exc_info=True)
Example #3
0
 def new_tx(data):
     try:
         new_tx: TX = data['tx']
         check_tx_time(new_tx)
         fill_verified_addr_tx(new_tx)
         check_tx(tx=new_tx, include_block=None)
         if new_tx.type in (C.TX_VALIDATOR_EDIT, C.TX_CONCLUDE_CONTRACT):
             tx_builder.marge_signature(tx=new_tx)
         else:
             tx_builder.put_unconfirmed(tx=new_tx)
         log.info("Accept new tx {}".format(new_tx))
         update_info_for_generate(u_block=False,
                                  u_unspent=False,
                                  u_unconfirmed=True)
         return True
     except BlockChainError as e:
         error = 'Failed accept new tx "{}"'.format(e)
         log.error(error, exc_info=True)
         return False
     except Exception:
         error = "Failed accept new tx"
         log.error(error, exc_info=True)
         return False
Example #4
0
def send_newtx(new_tx, outer_cur=None, exc_info=True):
    assert V.P2P_OBJ, "PeerClient is None"
    try:
        check_tx_time(new_tx)
        check_tx(new_tx, include_block=None)
        data = {'cmd': BroadcastCmd.NEW_TX, 'data': {'tx': new_tx}}
        V.P2P_OBJ.send_command(cmd=Peer2PeerCmd.BROADCAST, data=data)
        if new_tx.type in (C.TX_VALIDATOR_EDIT, C.TX_CONCLUDE_CONTRACT):
            tx_builder.marge_signature(tx=new_tx)
        else:
            tx_builder.put_unconfirmed(tx=new_tx)
        log.info("Success broadcast new tx {}".format(new_tx))
        update_info_for_generate(u_block=False,
                                 u_unspent=True,
                                 u_unconfirmed=True)
        return True
    except Exception as e:
        log.warning(
            "Failed broadcast new tx, other nodes don\'t accept {}".format(
                new_tx.getinfo()))
        log.warning("Reason is \"{}\"".format(e))
        log.debug("traceback,", exc_info=exc_info)
        return False
Example #5
0
def _main_loop():
    while not P.F_STOP:
        sleep(1)
        if P.F_NOW_BOOTING is False:
            continue
        if chain_builder.best_block is None:
            continue
        if not back_sync_thread.is_alive():
            raise Exception('BackSync is dead!')
        # start fast sync
        my_best_block: Block = chain_builder.best_block
        start_height = my_best_block.height
        start_time = time()
        # first of all
        back_que.put(my_best_block.height + 1)
        while True:
            new_block: Block = get_block_from_stack(my_best_block.height + 1)
            # check blockchain continuity
            if new_block is None:
                log.debug(
                    "request height is higher than network height! sync will not need?"
                )
                stack_dict.clear()
                break
            if chain_builder.root_block is not None\
                    and chain_builder.root_block.height is not None\
                    and new_block.height <= chain_builder.root_block.height:
                log.error("cannot rollback block depth height={}".format(
                    new_block.height))
                P.F_STOP = True
                return
            if new_block.hash in chain_builder.chain:
                log.debug("new block is already known {}".format(new_block))
                my_best_block = chain_builder.get_block(
                    blockhash=new_block.hash)
                continue
            if my_best_block.hash != new_block.previous_hash:
                log.debug(
                    "not chained my_best_block with new_block, rollback to {}".
                    format(my_best_block.height - 1))
                my_best_block = chain_builder.get_block(
                    blockhash=my_best_block.previous_hash)
                back_que.put(my_best_block.height + 1)
                continue
            if len(new_block.txs) <= 0:
                log.debug("something wrong?, rollback to {}".format(
                    my_best_block.height - 1))
                my_best_block = chain_builder.get_block(
                    blockhash=my_best_block.previous_hash)
                back_que.put(my_best_block.height + 1)
                continue
            # insert
            if not new_insert_block(
                    block=new_block, f_time=False, f_sign=False):
                log.debug("failed to insert new block, rollback to {}".format(
                    my_best_block.height - 1))
                my_best_block = chain_builder.get_block(
                    blockhash=my_best_block.previous_hash)
                back_que.put(my_best_block.height + 1)
                continue
            # request next chunk
            if len(stack_dict) < STACK_CHUNK_SIZE:
                if 0 < len(stack_dict):
                    back_que.put(max(stack_dict) + 1)
                else:
                    back_que.put(new_block.height + 1)
            # check reached top height
            best_height_on_network, best_hash_on_network = get_best_conn_info()
            if new_block.height < best_height_on_network:
                my_best_block = new_block
                continue
            else:
                log.info("reached max height of network height={}".format(
                    best_height_on_network))
                stack_dict.clear()
                break
        # get unconfirmed txs
        log.info("next get unconfirmed txs")
        unconfirmed_txhash_set = set()
        for data in ask_all_nodes(cmd=DirectCmd.UNCONFIRMED_TX):
            unconfirmed_txhash_set.update(data['txs'])
        unconfirmed_txs = list()
        for txhash in unconfirmed_txhash_set:
            if txhash in tx_builder.unconfirmed:
                continue
            try:
                tx: TX = seek_nodes(cmd=DirectCmd.TX_BY_HASH,
                                    data={'txhash': txhash})
                tx.height = None
                fill_verified_addr_tx(tx)
                unconfirmed_txs.append(tx)
            except BlockChainError as e:
                log.debug("1: Failed get unconfirmed {} '{}'".format(
                    txhash.hex(), e))
        with create_db(V.DB_ACCOUNT_PATH) as db:
            cur = db.cursor()
            for tx in sorted(unconfirmed_txs, key=lambda x: x.time):
                try:
                    check_tx_time(tx)
                    check_tx(tx, include_block=None)
                    tx_builder.put_unconfirmed(tx=tx, outer_cur=cur)
                except BlockChainError as e:
                    log.debug("2: Failed get unconfirmed '{}'".format(e))
        # fast sync finish
        log.info("fast sync finished start={} finish={} {}m".format(
            start_height, chain_builder.best_block.height,
            int((time() - start_time) / 60)))
        P.F_NOW_BOOTING = False
        update_info_for_generate()
    log.info("close by F_STOP flag")