示例#1
0
文件: contract.py 项目: kmn/bc4py
def contract_fill(c: Contract, best_block=None, best_chain=None, stop_txhash=None):
    # database
    c_iter = builder.db.read_contract_iter(c_address=c.c_address, start_idx=c.db_index)
    for index, start_hash, finish_hash, (c_method, c_args, c_storage) in c_iter:
        if start_hash == stop_txhash or finish_hash == stop_txhash:
            return
        c.update(db_index=index, start_hash=start_hash, finish_hash=finish_hash,
                 c_method=c_method, c_args=c_args, c_storage=c_storage)
    # memory
    if best_chain:
        _best_chain = None
    elif best_block and best_block == builder.best_block:
        _best_chain = builder.best_chain
    else:
        dummy, _best_chain = builder.get_best_chain(best_block=best_block)
    for block in reversed(best_chain or _best_chain):
        for tx in block.txs:
            if tx.hash == stop_txhash:
                return
            if tx.type != C.TX_CONCLUDE_CONTRACT:
                continue
            c_address, start_hash, c_storage = decode(tx.message)
            if c_address != c.c_address:
                continue
            if start_hash == stop_txhash:
                return
            start_tx = tx_builder.get_tx(txhash=start_hash)
            dummy, c_method, redeem_address, c_args = decode(start_tx.message)
            index = start_tx2index(start_tx=start_tx)
            c.update(db_index=index, start_hash=start_hash, finish_hash=tx.hash,
                     c_method=c_method, c_args=c_args, c_storage=c_storage)
    # unconfirmed (check validator condition satisfied)
    if best_block is None:
        unconfirmed = list()
        for conclude_tx in tuple(tx_builder.unconfirmed.values()):
            if conclude_tx.hash == stop_txhash:
                break
            if conclude_tx.type != C.TX_CONCLUDE_CONTRACT:
                continue
            c_address, start_hash, c_storage = decode(conclude_tx.message)
            if c_address != c.c_address:
                continue
            if start_hash == stop_txhash:
                break
            start_tx = tx_builder.get_tx(txhash=start_hash)
            if start_tx.height is None:
                continue
            sort_key = start_tx2index(start_tx=start_tx)
            unconfirmed.append((c_address, start_tx, conclude_tx, c_storage, sort_key))

        v = get_validator_object(c_address=c.c_address, best_block=best_block,
                                 best_chain=best_chain, stop_txhash=stop_txhash)
        for c_address, start_tx, conclude_tx, c_storage, sort_key in sorted(unconfirmed, key=lambda x: x[4]):
            if len(conclude_tx.signature) < v.require:
                continue  # ignore unsatisfied ConcludeTXs
            dummy, c_method, redeem_address, c_args = decode(start_tx.message)
            c.update(db_index=sort_key, start_hash=start_tx.hash, finish_hash=conclude_tx.hash,
                     c_method=c_method, c_args=c_args, c_storage=c_storage)
示例#2
0
def contract_fill(c: Contract,
                  best_block=None,
                  best_chain=None,
                  stop_txhash=None):
    assert c.index == -1, 'Already updated'
    # database
    c_iter = builder.db.read_contract_iter(c_address=c.c_address)
    for index, start_hash, finish_hash, (c_method, c_args,
                                         c_storage) in c_iter:
        if finish_hash == stop_txhash:
            return
        c.update(start_hash=start_hash,
                 finish_hash=finish_hash,
                 c_method=c_method,
                 c_args=c_args,
                 c_storage=c_storage)
    # memory
    if best_chain:
        _best_chain = None
    elif best_block and best_block == builder.best_block:
        _best_chain = builder.best_chain
    else:
        dummy, _best_chain = builder.get_best_chain(best_block=best_block)
    for block in reversed(best_chain or _best_chain):
        for tx in block.txs:
            if tx.hash == stop_txhash:
                return
            if tx.type != C.TX_CONCLUDE_CONTRACT:
                continue
            c_address, start_hash, c_storage = decode(tx.message)
            if c_address != c.c_address:
                continue
            start_tx = tx_builder.get_tx(txhash=start_hash)
            dummy, c_method, c_args = decode(start_tx.message)
            c.update(start_hash=start_hash,
                     finish_hash=tx.hash,
                     c_method=c_method,
                     c_args=c_args,
                     c_storage=c_storage)
    # unconfirmed
    if best_block is None:
        for tx in sorted(tx_builder.unconfirmed.values(),
                         key=lambda x: x.time):
            if tx.hash == stop_txhash:
                return
            if tx.type != C.TX_CONCLUDE_CONTRACT:
                continue
            c_address, start_hash, c_storage = decode(tx.message)
            if c_address != c.c_address:
                continue
            start_tx = tx_builder.get_tx(txhash=start_hash)
            dummy, c_method, c_args = decode(start_tx.message)
            c.update(start_hash=start_hash,
                     finish_hash=tx.hash,
                     c_method=c_method,
                     c_args=c_args,
                     c_storage=c_storage)
示例#3
0
文件: validator.py 项目: kmn/bc4py
def validator_fill(v: Validator,
                   best_block=None,
                   best_chain=None,
                   stop_txhash=None):
    # database
    v_iter = builder.db.read_validator_iter(c_address=v.c_address,
                                            start_idx=v.db_index)
    for index, address, flag, txhash, sig_diff in v_iter:
        if txhash == stop_txhash:
            return
        v.update(db_index=index,
                 flag=flag,
                 address=address,
                 sig_diff=sig_diff,
                 txhash=txhash)
    # memory
    if best_chain:
        _best_chain = None
    elif best_block and best_block == builder.best_block:
        _best_chain = builder.best_chain
    else:
        dummy, _best_chain = builder.get_best_chain(best_block=best_block)
    for block in reversed(best_chain or _best_chain):
        for tx in block.txs:
            if tx.hash == stop_txhash:
                return
            if tx.type != C.TX_VALIDATOR_EDIT:
                continue
            c_address, address, flag, sig_diff = decode(tx.message)
            if c_address != v.c_address:
                continue
            index = validator_tx2index(tx=tx)
            v.update(db_index=index,
                     flag=flag,
                     address=address,
                     sig_diff=sig_diff,
                     txhash=tx.hash)
    # unconfirmed
    if best_block is None:
        for tx in sorted(tx_builder.unconfirmed.values(),
                         key=lambda x: x.time):
            if tx.hash == stop_txhash:
                return
            if tx.type != C.TX_VALIDATOR_EDIT:
                continue
            c_address, address, flag, sig_diff = decode(tx.message)
            if c_address != v.c_address:
                continue
            if len(tx.signature) < v.require:
                continue
            index = validator_tx2index(tx=tx)
            v.update(db_index=index,
                     flag=flag,
                     address=address,
                     sig_diff=sig_diff,
                     txhash=tx.hash)
示例#4
0
def _get_best_chain_all(best_block):
    global best_block_cashe, best_chain_cashe
    # MemoryにおけるBestBlockまでのChainを返す
    if best_block is None:
        best_block_cashe = best_chain_cashe = None
        return builder.best_chain
    elif best_block_cashe and best_block == best_block_cashe:
        return best_chain_cashe
    else:
        dummy, best_chain = builder.get_best_chain(best_block)
        # best_chain = [<height=n>, <height=n-1>,.. <height=n-m>]
        if len(best_chain) == 0:
            raise BlockChainError('Ignore, New block inserted on "_get_best_chain_all".')
        best_block_cashe = best_block
        best_chain_cashe = best_chain
        return best_chain
示例#5
0
def validator_fill(v: Validator,
                   best_block=None,
                   best_chain=None,
                   stop_txhash=None):
    assert v.index == -1, 'Already updated'
    # database
    for index, address, flag, txhash, sig_diff in builder.db.read_validator_iter(
            c_address=v.c_address):
        if txhash == stop_txhash:
            return
        v.update(flag=flag, address=address, sig_diff=sig_diff, txhash=txhash)
    # memory
    if best_chain:
        _best_chain = None
    elif best_block and best_block == builder.best_block:
        _best_chain = builder.best_chain
    else:
        dummy, _best_chain = builder.get_best_chain(best_block=best_block)
    for block in reversed(best_chain or _best_chain):
        for tx in block.txs:
            if tx.hash == stop_txhash:
                return
            if tx.type != C.TX_VALIDATOR_EDIT:
                continue
            c_address, address, flag, sig_diff = decode(tx.message)
            if c_address != v.c_address:
                continue
            v.update(flag=flag,
                     address=address,
                     sig_diff=sig_diff,
                     txhash=tx.hash)
    # unconfirmed
    if best_block is None:
        for tx in sorted(tx_builder.unconfirmed.values(),
                         key=lambda x: x.time):
            if tx.hash == stop_txhash:
                return
            if tx.type != C.TX_VALIDATOR_EDIT:
                continue
            c_address, address, flag, sig_diff = decode(tx.message)
            if c_address != v.c_address:
                continue
            v.update(flag=flag,
                     address=address,
                     sig_diff=sig_diff,
                     txhash=tx.hash)
示例#6
0
def get_conclude_hash_by_start_hash(c_address,
                                    start_hash,
                                    best_block=None,
                                    best_chain=None,
                                    stop_txhash=None):
    # database
    c_iter = builder.db.read_contract_iter(c_address=c_address)
    for index, _start_hash, finish_hash, (c_method, c_args,
                                          c_storage) in c_iter:
        if finish_hash == stop_txhash:
            return None
        if _start_hash == start_hash:
            return finish_hash
    # memory
    if best_chain:
        _best_chain = None
    elif best_block and best_block == builder.best_block:
        _best_chain = builder.best_chain
    else:
        dummy, _best_chain = builder.get_best_chain(best_block=best_block)
    for block in reversed(best_chain or _best_chain):
        for tx in block.txs:
            if tx.hash == stop_txhash:
                return None
            if tx.type != C.TX_CONCLUDE_CONTRACT:
                continue
            _c_address, _start_hash, c_storage = decode(tx.message)
            if _c_address != c_address:
                continue
            if _start_hash == start_hash:
                return tx.hash
    # unconfirmed
    if best_block is None:
        for tx in sorted(tx_builder.unconfirmed.values(),
                         key=lambda x: x.time):
            if tx.hash == stop_txhash:
                return None
            if tx.type != C.TX_CONCLUDE_CONTRACT:
                continue
            _c_address, _start_hash, c_storage = decode(tx.message)
            if _c_address != c_address:
                continue
            if _start_hash == start_hash:
                return tx.hash
    return None
示例#7
0
def fill_mintcoin_status(m,
                         best_block=None,
                         best_chain=None,
                         stop_txhash=None):
    assert m.version == -1, 'Already updated'
    # database
    for index, txhash, params, setting in builder.db.read_coins_iter(
            coin_id=m.coin_id):
        if txhash == stop_txhash:
            return
        m.update(params=params, setting=setting, txhash=txhash)
    # memory
    if best_chain:
        _best_chain = None
    elif best_block and best_block == builder.best_block:
        _best_chain = builder.best_chain
    else:
        dummy, _best_chain = builder.get_best_chain(best_block=best_block)
    for block in reversed(best_chain or _best_chain):
        for tx in block.txs:
            if tx.hash == stop_txhash:
                return
            if tx.type != C.TX_MINT_COIN:
                continue
            coin_id, params, setting = decode(tx.message)
            if coin_id != m.coin_id:
                continue
            m.update(params=params, setting=setting, txhash=tx.hash)
    # unconfirmed
    if best_block is None:
        for tx in sorted(tx_builder.unconfirmed.values(),
                         key=lambda x: x.time):
            if tx.hash == stop_txhash:
                return
            if tx.type != C.TX_MINT_COIN:
                continue
            coin_id, params, setting = decode(tx.message)
            if coin_id != m.coin_id:
                continue
            m.update(params=params, setting=setting, txhash=tx.hash)
示例#8
0
def _update_unconfirmed_info():
    with unconfirmed_lock:
        s = time()
        # sort unconfirmed txs
        unconfirmed_txs = sorted(tx_builder.unconfirmed.values(),
                                 key=lambda x: (x.gas_price, -1 * x.time),
                                 reverse=True)

        # reject tx (input tx is unconfirmed)
        limit_height = builder.best_block.height - C.MATURE_HEIGHT
        best_block, best_chain = builder.get_best_chain()
        used_pairs = set()
        for tx in unconfirmed_txs.copy():
            if tx.height is not None:
                if tx.hash in tx_builder.unconfirmed:
                    del tx_builder.unconfirmed[tx.hash]
                unconfirmed_txs.remove(tx)
                continue
            if Debug.F_STICKY_TX_REJECTION and tx.hash in sticky_failed_txhash:
                unconfirmed_txs.remove(tx)
                continue
            # inputs check
            for txhash, txindex in tx.inputs:
                input_tx = tx_builder.get_tx(txhash)
                if input_tx is None:
                    unconfirmed_txs.remove(tx)
                    break
                elif input_tx.height is None:
                    unconfirmed_txs.remove(tx)
                    break
                elif input_tx.type in (C.TX_POS_REWARD, C.TX_POW_REWARD) and \
                        input_tx.height > limit_height:
                    unconfirmed_txs.remove(tx)
                    break
                elif is_usedindex(txhash, txindex, tx.hash, best_block,
                                  best_chain):
                    unconfirmed_txs.remove(tx)
                    break
                # check inputs used same unconfirmed_txs
                input_pair = (txhash, txindex)
                if input_pair in used_pairs:
                    unconfirmed_txs.remove(tx)
                    break
                used_pairs.add(input_pair)

        # contract tx
        need_resort_txs = defaultdict(list)
        for tx in unconfirmed_txs.copy():
            if tx.type == C.TX_CONCLUDE_CONTRACT:
                try:
                    c_address, start_hash, c_storage = bjson.loads(tx.message)
                except Exception:
                    unconfirmed_txs.remove(tx)  # failed decode bjson
                    continue
                start_tx = tx_builder.get_tx(txhash=start_hash)
                if start_tx is None or start_tx.height is None:
                    unconfirmed_txs.remove(tx)  # start tx is confirmed
                    continue
                v = get_validator_object(c_address=c_address,
                                         best_block=best_block,
                                         best_chain=best_chain)
                signed_cks = get_signed_cks(tx)
                accept_cks = signed_cks & set(v.validators)
                if v.require > len(accept_cks):
                    unconfirmed_txs.remove(tx)
                    continue
                # decide to include the ConcludeTx
                index = start_tx2index(start_tx=start_tx)
                need_resort_txs[c_address].append((index, tx))
            elif tx.type == C.TX_VALIDATOR_EDIT:
                try:
                    c_address, address, flag, sig_diff = bjson.loads(
                        tx.message)
                except Exception:
                    unconfirmed_txs.remove(tx)  # failed decode bjson
                    continue
                v = get_validator_object(c_address=c_address,
                                         best_block=best_block,
                                         best_chain=best_chain)
                signed_cks = get_signed_cks(tx)
                accept_cks = signed_cks & set(v.validators)
                if v.require > len(accept_cks):
                    unconfirmed_txs.remove(tx)
                    continue
            else:
                pass

        # affect resort txs (for contract)
        if len(need_resort_txs) > 0:
            append_txs = list()
            for c_address, data_list in need_resort_txs.items():
                if len(data_list) < 2:
                    continue
                for index, tx in sorted(data_list, key=lambda x: x[0]):
                    unconfirmed_txs.remove(tx)
                    append_txs.append(tx)
            else:
                unconfirmed_txs.extend(append_txs)

        # limit per tx's in block
        if Debug.F_LIMIT_INCLUDE_TX_IN_BLOCK:
            unconfirmed_txs = unconfirmed_txs[:Debug.
                                              F_LIMIT_INCLUDE_TX_IN_BLOCK]

        update_unconfirmed_txs(unconfirmed_txs)
        logging.debug("Update unconfirmed={}/{} {}Sec".format(
            len(unconfirmed_txs), len(tx_builder.unconfirmed),
            round(time() - s, 3)))
示例#9
0
文件: update.py 项目: yoosofan/bc4py
def _update_unconfirmed_info():
    with unconfirmed_lock:
        s = time()
        # sort unconfirmed txs
        unconfirmed_txs = sorted(tx_builder.unconfirmed.values(),
                                 key=lambda x: x.gas_price,
                                 reverse=True)
        # reject tx (input tx is unconfirmed)
        limit_height = builder.best_block.height - C.MATURE_HEIGHT
        best_block, best_chain = builder.get_best_chain()
        used_pairs = set()
        for tx in unconfirmed_txs.copy():
            if tx.height is not None:
                if tx.hash in tx_builder.unconfirmed:
                    del tx_builder.unconfirmed[tx.hash]
                unconfirmed_txs.remove(tx)
                continue
            if Debug.F_STICKY_TX_REJECTION and tx.hash in sticky_failed_txhash:
                unconfirmed_txs.remove(tx)
                continue
            for txhash, txindex in tx.inputs:
                input_tx = tx_builder.get_tx(txhash)
                if input_tx is None:
                    unconfirmed_txs.remove(tx)
                    break
                elif input_tx.height is None:
                    unconfirmed_txs.remove(tx)
                    break
                elif input_tx.type in (C.TX_POS_REWARD, C.TX_POW_REWARD) and \
                        input_tx.height > limit_height:
                    unconfirmed_txs.remove(tx)
                    break
                elif is_usedindex(txhash, txindex, tx.hash, best_block,
                                  best_chain):
                    unconfirmed_txs.remove(tx)
                    break
                # check inputs used same unconfirmed_txs
                input_pair = (txhash, txindex)
                if input_pair in used_pairs:
                    unconfirmed_txs.remove(tx)
                    break
                used_pairs.add(input_pair)

        # limit per tx's in block
        if Debug.F_LIMIT_INCLUDE_TX_IN_BLOCK:
            unconfirmed_txs = unconfirmed_txs[:Debug.
                                              F_LIMIT_INCLUDE_TX_IN_BLOCK]
        unconfirmed_txs = sorted(unconfirmed_txs, key=lambda x: x.time)

        # ContractTXのみ取り出す
        contract_txs = dict()
        for tx in unconfirmed_txs.copy():
            if tx.type == C.TX_START_CONTRACT:
                unconfirmed_txs.remove(tx)
                if tx not in contract_txs:
                    contract_txs[tx] = list()
            elif tx.type == C.TX_FINISH_CONTRACT:
                unconfirmed_txs.remove(tx)
                dummy0, start_hash, dummy1 = bjson.loads(tx.message)
                if start_hash not in tx_builder.unconfirmed:
                    continue
                start_tx = tx_builder.unconfirmed[start_hash]
                if start_tx in contract_txs:
                    contract_txs[start_tx].append(tx)
                if start_tx in unconfirmed_txs:
                    contract_txs[start_tx] = [tx]

        # StartTX=>FinishTXを一対一関係で繋げる
        if len(contract_txs) > 0:
            _, required_num = get_validator_info()
            for start_tx, finish_txs in contract_txs.items():
                if len(finish_txs) == 0:
                    continue
                for tx in finish_txs:
                    if len(tx.signature) < required_num:
                        continue
                    # OK!
                    unconfirmed_txs.extend((start_tx, tx))
                    break

        update_unconfirmed_txs(unconfirmed_txs)
        logging.debug("Update unconfirmed={}/{} {}Sec".format(
            len(unconfirmed_txs), len(tx_builder.unconfirmed),
            round(time() - s, 3)))