Exemple #1
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
        }
    }
Exemple #2
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,
            }
        }
    )
Exemple #3
0
def fill_test(filler: Dict[str, Any],
              info: Dict[str, Any] = None,
              apply_formatter: bool = True,
              **kwargs: Any) -> Dict[str, Any]:

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

    if "transaction" in test:
        filled = fill_state_test(filler)
        formatter = filled_state_test_formatter
    elif "exec" in test:
        filled = fill_vm_test(filler, **kwargs)
        formatter = filled_vm_test_formatter
    else:
        raise ValueError(
            "Given filler does not appear to be for VM or state test")

    info = merge(
        {
            "filledwith":
            FILLED_WITH_TEMPLATE.format(version=get_version_from_git())
        }, info if info else {})
    filled = assoc_in(filled, [test_name, "_info"], info)

    if apply_formatter:
        return formatter(filled)
    else:
        return filled
Exemple #4
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)
Exemple #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,
            }
        }
    )
Exemple #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)
Exemple #7
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,
        }
    }
Exemple #8
0
PARENT_DIR = os.path.dirname(os.path.abspath(__file__))
OUTPUT_DIR = os.path.join(PARENT_DIR, "json")
FILLER_PARENT_DIR = os.path.join(OUTPUT_DIR, "fillers")
TEST_PARENT_DIR = os.path.join(OUTPUT_DIR, "tests")


DIR_STRUCTURE = {

}


if __name__ == "__main__":
    for (filler_dir, test_dir), test_groups in DIR_STRUCTURE.items():
        for test_group, tests in test_groups.items():
            for filler, filler_kwargs in tests:
                test_name = get_test_name(filler)
                filename = test_name + ".json"

                filler_src_path = os.path.join(filler_dir, test_group, filename)
                filler_path = os.path.join(FILLER_PARENT_DIR, filler_src_path)
                test_path = os.path.join(TEST_PARENT_DIR, test_dir, test_group, filename)

                for path in [filler_path, test_path]:
                    os.makedirs(os.path.dirname(path), exist_ok=True)

                formatted_filler = filler_formatter(filler)
                filler_string = json.dumps(formatted_filler, indent=4, sort_keys=True)
                with open(filler_path, "w") as filler_file:
                    filler_file.write(filler_string)

                filler_hash = keccak(filler_string.encode("ascii"))