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
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: Dict[int, List[Dict[str, str]]] = defaultdict(list) 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 } }
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: Dict[str, Dict[Any, Any]] = {test_name: {}} 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)
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, }})
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)
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, Tuple[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, } }