def get_name_puzzle_conditions_rust(generator: BlockGenerator, max_cost: int,
                                    *, cost_per_byte: int,
                                    safe_mode: bool) -> NPCResult:
    block_program, block_program_args = setup_generator_args(generator)
    max_cost -= len(bytes(generator.program)) * cost_per_byte
    if max_cost < 0:
        return NPCResult(uint16(Err.INVALID_BLOCK_COST.value), [], uint64(0))

    flags = STRICT_MODE if safe_mode else 0
    err, result, clvm_cost = GENERATOR_MOD.run_as_generator(
        max_cost, flags, block_program, block_program_args)
    if err is not None:
        return NPCResult(uint16(err), [], uint64(0))
    else:
        npc_list = []
        for r in result:
            conditions = []
            for c in r.conditions:
                cwa = []
                for cond_list in c[1]:
                    cwa.append(
                        ConditionWithArgs(
                            ConditionOpcode(bytes([cond_list.opcode])),
                            cond_list.vars))
                conditions.append((ConditionOpcode(bytes([c[0]])), cwa))
            npc_list.append(NPC(r.coin_name, r.puzzle_hash, conditions))
        return NPCResult(None, npc_list, uint64(clvm_cost))
示例#2
0
def get_name_puzzle_conditions(
    generator: BlockGenerator, max_cost: int, *, cost_per_byte: int, mempool_mode: bool
) -> NPCResult:
    block_program, block_program_args = setup_generator_args(generator)
    max_cost -= len(bytes(generator.program)) * cost_per_byte
    if max_cost < 0:
        return NPCResult(uint16(Err.INVALID_BLOCK_COST.value), [], uint64(0))

    flags = MEMPOOL_MODE if mempool_mode else 0
    try:
        err, result, clvm_cost = GENERATOR_MOD.run_as_generator(max_cost, flags, block_program, block_program_args)
        if err is not None:
            return NPCResult(uint16(err), [], uint64(0))
        else:
            npc_list = []
            for r in result:
                conditions = []
                for c in r.conditions:
                    cwa = []
                    for cond_list in c[1]:
                        cwa.append(ConditionWithArgs(ConditionOpcode(bytes([cond_list.opcode])), cond_list.vars))
                    conditions.append((ConditionOpcode(bytes([c[0]])), cwa))
                npc_list.append(NPC(r.coin_name, r.puzzle_hash, conditions))
            return NPCResult(None, npc_list, uint64(clvm_cost))
    except BaseException as e:
        log.debug(f"get_name_puzzle_condition failed: {e}")
        return NPCResult(uint16(Err.GENERATOR_RUNTIME_ERROR.value), [], uint64(0))
def get_name_puzzle_conditions(generator: BlockGenerator, max_cost: int,
                               safe_mode: bool) -> NPCResult:
    try:
        block_program, block_program_args = setup_generator_args(generator)
        if safe_mode:
            cost, result = GENERATOR_MOD.run_safe_with_cost(
                max_cost, block_program, block_program_args)
        else:
            cost, result = GENERATOR_MOD.run_with_cost(max_cost, block_program,
                                                       block_program_args)
        npc_list: List[NPC] = []
        opcodes: Set[bytes] = set(item.value for item in ConditionOpcode)

        for res in result.as_iter():
            conditions_list: List[ConditionWithArgs] = []

            spent_coin_parent_id: bytes32 = res.first().first().as_atom()
            spent_coin_puzzle_hash: bytes32 = res.first().rest().first(
            ).as_atom()
            spent_coin_amount: uint64 = uint64(
                res.first().rest().rest().first().as_int())
            spent_coin: Coin = Coin(spent_coin_parent_id,
                                    spent_coin_puzzle_hash, spent_coin_amount)

            for cond in res.rest().first().as_iter():
                if cond.first().as_atom() in opcodes:
                    opcode: ConditionOpcode = ConditionOpcode(
                        cond.first().as_atom())
                elif not safe_mode:
                    opcode = ConditionOpcode.UNKNOWN
                else:
                    return NPCResult(uint16(Err.GENERATOR_RUNTIME_ERROR.value),
                                     [], uint64(0))
                cvl = ConditionWithArgs(opcode, cond.rest().as_atom_list())
                conditions_list.append(cvl)
            conditions_dict = conditions_by_opcode(conditions_list)
            if conditions_dict is None:
                conditions_dict = {}
            npc_list.append(
                NPC(spent_coin.name(), spent_coin.puzzle_hash,
                    [(a, b) for a, b in conditions_dict.items()]))
        return NPCResult(None, npc_list, uint64(cost))
    except Exception:
        return NPCResult(uint16(Err.GENERATOR_RUNTIME_ERROR.value), [],
                         uint64(0))
def get_name_puzzle_conditions_python(generator: BlockGenerator, max_cost: int,
                                      *, cost_per_byte: int,
                                      safe_mode: bool) -> NPCResult:
    """
    This executes the generator program and returns the coins and their
    conditions. If the cost of the program (size, CLVM execution and conditions)
    exceed max_cost, the function fails. In order to accurately take the size
    of the program into account when calculating cost, cost_per_byte must be
    specified.
    safe_mode determines whether the clvm program and conditions are executed in
    strict mode or not. When in safe/strict mode, unknow operations or conditions
    are considered failures. This is the mode when accepting transactions into
    the mempool.
    """
    block_program, block_program_args = setup_generator_args(generator)
    max_cost -= len(bytes(generator.program)) * cost_per_byte
    if max_cost < 0:
        return NPCResult(uint16(Err.INVALID_BLOCK_COST.value), [], uint64(0))
    if safe_mode:
        clvm_cost, result = GENERATOR_MOD.run_safe_with_cost(
            max_cost, block_program, block_program_args)
    else:
        clvm_cost, result = GENERATOR_MOD.run_with_cost(
            max_cost, block_program, block_program_args)

    max_cost -= clvm_cost
    if max_cost < 0:
        return NPCResult(uint16(Err.INVALID_BLOCK_COST.value), [], uint64(0))
    npc_list: List[NPC] = []

    for res in result.first().as_iter():
        conditions_list: List[ConditionWithArgs] = []

        if len(res.first().atom) != 32:
            raise ValidationError(Err.INVALID_CONDITION)
        spent_coin_parent_id: bytes32 = res.first().as_atom()
        res = res.rest()
        if len(res.first().atom) != 32:
            raise ValidationError(Err.INVALID_CONDITION)
        spent_coin_puzzle_hash: bytes32 = res.first().as_atom()
        res = res.rest()
        spent_coin_amount: uint64 = uint64(sanitize_int(
            res.first(), safe_mode))
        res = res.rest()
        spent_coin: Coin = Coin(spent_coin_parent_id, spent_coin_puzzle_hash,
                                spent_coin_amount)

        for cond in res.first().as_iter():
            cost, cvl = parse_condition(cond, safe_mode)
            max_cost -= cost
            if max_cost < 0:
                return NPCResult(uint16(Err.INVALID_BLOCK_COST.value), [],
                                 uint64(0))
            if cvl is not None:
                conditions_list.append(cvl)

        conditions_dict = conditions_by_opcode(conditions_list)
        if conditions_dict is None:
            conditions_dict = {}
        npc_list.append(
            NPC(spent_coin.name(), spent_coin.puzzle_hash,
                [(a, b) for a, b in conditions_dict.items()]))
    return NPCResult(None, npc_list, uint64(clvm_cost))
def get_name_puzzle_conditions(generator: BlockGenerator,
                               max_cost: int,
                               *,
                               cost_per_byte: int,
                               mempool_mode: bool,
                               height: Optional[uint32] = None) -> NPCResult:
    block_program, block_program_args = setup_generator_args(generator)
    size_cost = len(bytes(generator.program)) * cost_per_byte
    max_cost -= size_cost
    if max_cost < 0:
        return NPCResult(uint16(Err.INVALID_BLOCK_COST.value), [], uint64(0))

    # in mempool mode, the height doesn't matter, because it's always strict.
    # But otherwise, height must be specified to know which rules to apply
    assert mempool_mode or height is not None

    # mempool mode also has these rules apply
    assert (MEMPOOL_MODE & COND_CANON_INTS) != 0
    assert (MEMPOOL_MODE & NO_NEG_DIV) != 0

    if mempool_mode:
        flags = MEMPOOL_MODE
    elif unwrap(height) >= DEFAULT_CONSTANTS.SOFT_FORK_HEIGHT:
        # conditions must use integers in canonical encoding (i.e. no redundant
        # leading zeros)
        # the division operator may not be used with negative operands
        flags = COND_CANON_INTS | NO_NEG_DIV
    else:
        flags = 0

    try:
        err, result = GENERATOR_MOD.run_as_generator(max_cost, flags,
                                                     block_program,
                                                     block_program_args)

        if err is not None:
            assert err != 0
            return NPCResult(uint16(err), [], uint64(0))

        first = True
        npc_list = []
        for r in result.spends:
            conditions: Dict[ConditionOpcode, List[ConditionWithArgs]] = {}
            if r.height_relative is not None:
                add_int_cond(conditions,
                             ConditionOpcode.ASSERT_HEIGHT_RELATIVE,
                             r.height_relative)
            if r.seconds_relative > 0:
                add_int_cond(conditions,
                             ConditionOpcode.ASSERT_SECONDS_RELATIVE,
                             r.seconds_relative)
            for cc in r.create_coin:
                if cc[2] == b"":
                    add_cond(conditions, ConditionOpcode.CREATE_COIN,
                             [cc[0], int_to_bytes(cc[1])])
                else:
                    add_cond(conditions, ConditionOpcode.CREATE_COIN,
                             [cc[0], int_to_bytes(cc[1]), cc[2]])
            for sig in r.agg_sig_me:
                add_cond(conditions, ConditionOpcode.AGG_SIG_ME,
                         [sig[0], sig[1]])

            # all conditions that aren't tied to a specific spent coin, we roll into the first one
            if first:
                first = False
                if result.reserve_fee > 0:
                    add_int_cond(conditions, ConditionOpcode.RESERVE_FEE,
                                 result.reserve_fee)
                if result.height_absolute > 0:
                    add_int_cond(conditions,
                                 ConditionOpcode.ASSERT_HEIGHT_ABSOLUTE,
                                 result.height_absolute)
                if result.seconds_absolute > 0:
                    add_int_cond(conditions,
                                 ConditionOpcode.ASSERT_SECONDS_ABSOLUTE,
                                 result.seconds_absolute)
                for sig in result.agg_sig_unsafe:
                    add_cond(conditions, ConditionOpcode.AGG_SIG_UNSAFE,
                             [sig[0], sig[1]])

            npc_list.append(
                NPC(r.coin_id, r.puzzle_hash,
                    [(op, cond) for op, cond in conditions.items()]))

        return NPCResult(None, npc_list, uint64(result.cost + size_cost))

    except BaseException as e:
        log.debug(f"get_name_puzzle_condition failed: {e}")
        return NPCResult(uint16(Err.GENERATOR_RUNTIME_ERROR.value), [],
                         uint64(0))