Example #1
0
def _expect(post_state: Dict[str, Any], networks: Any,
            transaction: TransactionDict, filler: Dict[str,
                                                       Any]) -> Dict[str, Any]:

    test_name = get_test_name(filler)
    test = filler[test_name]
    test_update = {test_name: {}}  # type: Dict[str, Dict[Any, Any]]

    pre_state = test.get("pre", {})
    post_state = normalize_state(post_state or {})
    defaults = {
        address: {
            "balance": 0,
            "nonce": 0,
            "code": b"",
            "storage": {},
        }
        for address in post_state
    }
    result = deep_merge(defaults, pre_state, normalize_state(post_state))
    new_expect = {"result": result}

    if transaction is not None:
        transaction = normalize_transaction(
            merge(get_default_transaction(networks), transaction))
        if "transaction" not in test:
            transaction_group = apply_formatters_to_dict(
                {
                    "data": wrap_in_list,
                    "gasLimit": wrap_in_list,
                    "value": wrap_in_list,
                }, transaction)
            indexes = {
                index_key: 0
                for transaction_key, index_key in [
                    ("gasLimit", "gas"),
                    ("value", "value"),
                    ("data", "data"),
                ] if transaction_key in transaction_group
            }
        else:
            transaction_group, indexes = add_transaction_to_group(
                test["transaction"], transaction)
        new_expect = assoc(new_expect, "indexes", indexes)
        test_update = assoc_in(test_update, [test_name, "transaction"],
                               transaction_group)

    if networks is not None:
        networks = normalize_networks(networks)
        new_expect = assoc(new_expect, "networks", networks)

    existing_expects = test.get("expect", [])
    expect = existing_expects + [new_expect]
    test_update = assoc_in(test_update, [test_name, "expect"], expect)

    return deep_merge(filler, test_update)
Example #2
0
def fill_state_test(filler: Dict[str, Any]) -> Dict[str, Dict[str, Any]]:
    """
    Filler function for filling state tests.
    """
    test_name = get_test_name(filler)
    test = filler[test_name]

    environment = normalize_environment(test["env"])
    pre_state = normalize_state(test["pre"])
    transaction_group = normalize_transaction_group(test["transaction"])

    post = defaultdict(list)  # type: Dict[int, List[Dict[str, str]]]
    for expect in test["expect"]:
        indexes = expect["indexes"]
        networks = normalize_networks(expect["networks"])
        result = normalize_state(expect["result"])
        post_state = deep_merge(pre_state, result)
        for network in networks:
            state_class = STATE_CLASSES[network]
            post_state_root = calc_state_root(post_state, state_class)
            post[network].append({
                "hash": encode_hex(post_state_root),
                "indexes": indexes,
            })

    return {
        test_name: {
            "env": environment,
            "pre": pre_state,
            "transaction": transaction_group,
            "post": post
        }
    }
Example #3
0
def execution(execution, filler):
    execution = normalize_execution(execution or {})

    # user caller as origin if not explicitly given
    if "caller" in execution and "origin" not in execution:
        execution = assoc(execution, "origin", execution["caller"])

    if "vyperLLLCode" in execution:
        code = compile_vyper_lll(execution["vyperLLLCode"])
        if "code" in execution:
            if code != execution["code"]:
                raise ValueError("Compiled Vyper LLL code does not match")
        execution = assoc(execution, "code", code)

    execution = merge(DEFAULT_EXECUTION, execution)

    test_name = get_test_name(filler)
    return deep_merge(
        filler,
        {
            test_name: {
                "exec": execution,
            }
        }
    )
Example #4
0
def _fill_and_normalize_state(simple_state):
    base_state = normalize_state(simple_state)
    defaults = {address: {
        "balance": 0,
        "nonce": 0,
        "code": b"",
        "storage": {},
    } for address in base_state.keys()}
    state = deep_merge(defaults, base_state)
    return state
Example #5
0
def execution(execution: Dict[str, Any], filler: Dict[str, Any]) -> Dict[str, Any]:
    """
    For VM tests, specify the code that is being run as well as the current state of
    the EVM. State tests don't support this object. The parameter is a dictionary specifying some
    or all of the following keys:

    +--------------------+------------------------------------------------------------+
    |  key               | description                                                |
    +====================+============================================================+
    | ``"address"``      | the address of the account executing the code              |
    +--------------------+------------------------------------------------------------+
    | ``"caller"``       | the caller address                                         |
    +--------------------+------------------------------------------------------------+
    | ``"origin"``       | the origin address (defaulting to the caller address)      |
    +--------------------+------------------------------------------------------------+
    | ``"value"``        | the value of the call                                      |
    +--------------------+------------------------------------------------------------+
    | ``"data"``         | the data passed with the call                              |
    +--------------------+------------------------------------------------------------+
    | ``"gasPrice"``     | the gas price of the call                                  |
    +--------------------+------------------------------------------------------------+
    | ``"gas"``          | the amount of gas allocated for the call                   |
    +--------------------+------------------------------------------------------------+
    | ``"code"``         | the bytecode to execute                                    |
    +--------------------+------------------------------------------------------------+
    | ``"vyperLLLCode"`` | the code in Vyper LLL (compiled to bytecode automatically) |
    +--------------------+------------------------------------------------------------+
    """
    execution = normalize_execution(execution or {})

    # user caller as origin if not explicitly given
    if "caller" in execution and "origin" not in execution:
        execution = assoc(execution, "origin", execution["caller"])

    if "vyperLLLCode" in execution:
        code = compile_vyper_lll(execution["vyperLLLCode"])
        if "code" in execution:
            if code != execution["code"]:
                raise ValueError("Compiled Vyper LLL code does not match")
        execution = assoc(execution, "code", code)

    execution = merge(DEFAULT_EXECUTION, execution)

    test_name = get_test_name(filler)
    return deep_merge(
        filler,
        {
            test_name: {
                "exec": execution,
            }
        }
    )
Example #6
0
    def _pre_state(filler: Dict[str, Any]) -> Dict[str, Any]:
        test_name = get_test_name(filler)

        old_pre_state = filler[test_name].get("pre_state", {})
        pre_state = normalize_state(raw_state)
        defaults = {address: {
            "balance": 0,
            "nonce": 0,
            "code": b"",
            "storage": {},
        } for address in pre_state}
        new_pre_state = deep_merge(defaults, old_pre_state, pre_state)

        return assoc_in(filler, [test_name, "pre"], new_pre_state)
Example #7
0
def state_definition_to_dict(state_definition: GeneralState) -> AccountState:
    """Convert a state definition to the canonical dict form.

    State can either be defined in the canonical form, or as a list of sub states that are then
    merged to one. Sub states can either be given as dictionaries themselves, or as tuples where
    the last element is the value and all others the keys for this value in the nested state
    dictionary. Example:

    ```
        [
            ("0xaabb", "balance", 3),
            ("0xaabb", "storage", {
                4: 5,
            }),
            "0xbbcc", {
                "balance": 6,
                "nonce": 7
            }
        ]
    ```
    """
    if isinstance(state_definition, Mapping):
        state_dict = state_definition
    elif isinstance(state_definition, Iterable):
        state_dicts = [
            assoc_in(
                {},
                state_item[:-1],
                state_item[-1]
            ) if not isinstance(state_item, Mapping) else state_item
            for state_item
            in state_definition
        ]
        if not is_cleanly_mergable(*state_dicts):
            raise ValidationError("Some state item is defined multiple times")
        state_dict = deep_merge(*state_dicts)
    else:
        assert TypeError("State definition must either be a mapping or a sequence")

    seen_keys = set(concat(d.keys() for d in state_dict.values()))
    bad_keys = seen_keys - set(["balance", "nonce", "storage", "code"])
    if bad_keys:
        raise ValidationError(
            "State definition contains the following invalid account fields: {}".format(
                ", ".join(bad_keys)
            )
        )

    return state_dict
Example #8
0
def fill_vm_test(
        filler: Dict[str, Any],
        *,
        call_creates: Any=None,
        gas_price: Union[int, str]=None,
        gas_remaining: Union[int, str]=0,
        logs: Iterable[Tuple[bytes, List[int], bytes]]=None,
        output: bytes=b"") -> Dict[str, Dict[str, Any]]:

    test_name = get_test_name(filler)
    test = filler[test_name]

    environment = normalize_environment(test["env"])
    pre_state = normalize_state(test["pre"])
    execution = normalize_execution(test["exec"])

    assert len(test["expect"]) == 1
    expect = test["expect"][0]
    assert "network" not in test
    assert "indexes" not in test

    result = normalize_state(expect["result"])
    post_state = deep_merge(pre_state, result)

    call_creates = normalize_call_creates(call_creates or [])
    gas_remaining = normalize_int(gas_remaining)
    output = normalize_bytes(output)

    logs = normalize_logs(logs or [])
    log_hash = hash_log_entries(logs)

    return {
        test_name: {
            "env": environment,
            "pre": pre_state,
            "exec": execution,
            "post": post_state,
            "callcreates": call_creates,
            "gas": gas_remaining,
            "output": output,
            "logs": log_hash,
        }
    }