Пример #1
0
async def chain_info(request):
    best_height = builder.best_block.height
    best_block = builder.best_block
    old_block_height = builder.best_chain[0].height - 1
    old_block_hash = hexlify(builder.get_block_hash(old_block_height)).decode()
    data = {'best': best_block.getinfo()}
    difficulty = dict()
    for consensus, ratio in V.BLOCK_CONSENSUSES.items():
        name = C.consensus2name[consensus]
        target = get_bits_by_hash(previous_hash=best_block.hash, consensus=consensus)[1]
        block_time = round(V.BLOCK_TIME_SPAN / ratio * 100)
        diff = (MAX_256_INT // target) / 100000000
        bias = get_bias_by_hash(previous_hash=best_block.previous_hash, consensus=consensus)
        difficulty[name] = {
            'number': consensus,
            'diff': round(diff / 100000000, 8),
            'bias': round(bias, 8),
            'fixed_diff': round(diff / bias, 8),
            'hashrate(kh/s)': round((MAX_256_INT//target)/block_time/1000, 3),
            'is_base': V.BLOCK_BASE_CONSENSUS == consensus,
        }
    data['mining'] = difficulty
    data['size'] = best_block.getsize()
    data['checkpoint'] = {'height': old_block_height, 'blockhash': old_block_hash}
    data['money_supply'] = GompertzCurve.calc_total_supply(best_height)
    data['total_supply'] = GompertzCurve.k
    return web_base.json_res(data)
Пример #2
0
def start_tx2index(start_hash=None, start_tx=None):
    if start_hash:
        start_tx = tx_builder.get_tx(txhash=start_hash)
    block = builder.get_block(blockhash=builder.get_block_hash(height=start_tx.height))
    if block is None:
        raise BlockChainError('Not found block of start_tx included? {}'.format(start_tx))
    if start_tx not in block.txs:
        raise BlockChainError('Not found start_tx in block? {}'.format(block))
    return start_tx.height * 0xffffffff + block.txs.index(start_tx)
Пример #3
0
async def get_block_by_height(request):
    height = int(request.query.get('height', 0))
    blockhash = builder.get_block_hash(height)
    if blockhash is None:
        return web.Response(text="Not found height.", status=400)
    block = builder.get_block(blockhash)
    data = block.getinfo()
    data['size'] = block.getsize()
    data['hex'] = hexlify(block.b).decode()
    return web_base.json_res(data)
Пример #4
0
def _big_blocks(height):
    data = list()
    for i in range(20):
        blockhash = builder.get_block_hash(height + i)
        if blockhash is None:
            break
        block = builder.get_block(blockhash)
        if block is None:
            break
        txs = [(tx.b, tx.signature) for tx in block.txs]
        data.append((block.b, block.height, block.flag, txs))
    # TODO:一度に送信できるBytesにチェック
    return data
Пример #5
0
async def get_block_by_height(request):
    f_pickled = request.query.get('pickle', False)
    height = int(request.query['height'])
    blockhash = builder.get_block_hash(height)
    if blockhash is None:
        return web.Response(text="Not found height.", status=400)
    block = builder.get_block(blockhash)
    if f_pickled:
        block = pickle.dumps(block)
        return web_base.json_res(b64encode(block).decode())
    data = block.getinfo()
    data['size'] = block.getsize()
    data['hex'] = hexlify(block.b).decode()
    return web_base.json_res(data)
Пример #6
0
def try_emulate(start_tx, gas_limit=None, out=None):
    start_time = time.time()
    cxt = get_context('spawn')
    que = cxt.Queue()
    # out = out or io.StringIO()
    c_address, c_method, c_args, c_redeem = bjson.loads(start_tx.message)
    c_bin = get_contract_binary(c_address)
    assert c_bin, 'Not found c_bin of {}'.format(c_address)
    params = {
        'sub_dir': V.SUB_DIR, 'genesis_block': builder.get_block(builder.get_block_hash(0)),
        'c_bin': c_bin, 'c_address': c_address, 'c_method': c_method, 'args': c_args}
    p = cxt.Process(target=_work, args=(params, start_tx, que))
    p.start()
    que_cmd, port = que.get(timeout=10)
    if que_cmd != CMD_PORT:
        raise TypeError('Not correct command="{}" data="{}"'.format(que_cmd, port))
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect(("127.0.0.1", port))
    sock.settimeout(10)
    # Start emulation
    line = fee = 0
    cmd = EMU_STEP
    error = None
    logging.debug("Start contract emulate port={}".format(port))
    while True:
        try:
            msg_list = sock.recv(8192).decode(errors='ignore').replace("\r", "").split("\n")
            if len(msg_list) <= 1:
                sock.close()
                break
            elif len(msg_list) < 3:
                pass
            elif gas_limit and fee > gas_limit:
                error = 'reached gas limit. [{}>{}]'.format(fee, gas_limit)
                break
            elif cmd in (EMU_STEP, EMU_NEXT, EMU_UNTIL, EMU_RETURN):
                msg_list, path, words = msg_list[:-3], msg_list[-3][2:], msg_list[-2][3:]
                file = os.path.split(path)[1]
                print(file, words, path)
                if file.startswith('exe.py') and file.endswith('work_field()'):
                    cmd = EMU_STEP  # Start!
                    print("start contract {}", file=out)
                elif file.startswith('contract('):
                    line += 1
                    fee += 1
                    cmd = EMU_STEP
                else:
                    cmd = EMU_NEXT
                # Add fee
                for func, gas in __price__.items():
                    if func in words and words.startswith('def ' + func + '('):
                        fee += gas
                print("{}:read [{}] {} >> {}".format(line, fee, cmd, words), file=out)
            else:
                msg = ', '.join(msg_list)
                print("msg [{}] >>".format(cmd), msg, file=out)
            # response to work field
            sock.send((cmd + "\n").encode())
        except ConnectionResetError:
            break
        except BaseException:
            error = str(traceback.format_exc())
            break
    logging.debug("Finish contract {}Sec error:{}".format(round(time.time() - start_time, 3), error))
    # Close emulation
    try:
        que_cmd, result = que.get_nowait()
        print(result)
        try: que.close()
        except: pass
        try: p.terminate()
        except: pass
        if que_cmd == CMD_ERROR:
            return False, result, fee, line
        elif que_cmd == CMD_SUCCESS:
            return True, result, fee, line
    except BaseException:
        return False, error, fee, line
Пример #7
0
def _block_by_height(height):
    blockhash = builder.get_block_hash(height)
    if blockhash:
        return {'blockhash': blockhash}
    else:
        return 'Not found block height {}.'.format(height)
Пример #8
0
def fast_sync_chain():
    assert V.PC_OBJ is not None, "Need PeerClient start before."
    global f_changed_status, back_thread
    # wait for back_thread is closed status
    count = 0
    while back_thread and back_thread.is_alive():
        block_stack.clear()
        sleep(1)
        count += 1
        if count % 30 == 0:
            logging.warning(
                "Waiting for back_thread closed... {}Sec".format(count))
    back_thread = Thread(target=background_process,
                         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 fast 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 new={} before={}".format(
                new_block, before_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:
            failed_num += 1
            for height in tuple(block_stack.keys()):
                if height >= index_height:
                    del block_stack[height]
            next_index_block = index_height - 1
            editable_height = builder.root_block.height + 1
            if next_index_block <= editable_height:
                logging.error("Try to rollback to editable height {}".format(
                    editable_height))
                f_changed_status = False
                return False
            elif next_index_block not in block_stack:
                # back 20 height, no blocks to recombine in block_stack
                index_height = max(3, editable_height, index_height - 20)
                index_block = builder.get_block(
                    blockhash=builder.get_block_hash(index_height))
                before_block = builder.get_block(
                    blockhash=index_block.previous_hash)
                with write_protect_lock:
                    block_stack.clear()
                    block_stack[index_height] = index_block
            else:
                # back 1 height
                before_block = builder.get_block(before_block.previous_hash)
                index_height = before_block.height + 1
            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.")
    unconfirmed_txhash_set = set()
    for data in ask_all_nodes(cmd=DirectCmd.UNCONFIRMED_TX):
        unconfirmed_txhash_set.update(data['txs'])
    for txhash in unconfirmed_txhash_set:
        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 [best={}, now={}]".
            format(round(time() - start, 1), best_height_on_network,
                   my_best_height))
        return True
    else:
        logging.debug("Continue update chain, best={}, now={}".format(
            best_height_on_network, my_best_height))
        return False