async def _get_block_bodies( self, peer: ETHPeer, headers: Tuple[BlockHeader, ...], ) -> Tuple[Tuple[BlockBodyBundle, ...], Tuple[BlockHeader, ...]]: """ Request and return block bodies, pairing them with the associated headers. Store the bodies for later use, during block import (or persist). Note the difference from _request_block_bodies, which only issues the request, and doesn't pair the results with the associated block headers that were successfully delivered. """ block_body_bundles = await self.wait( self._request_block_bodies(peer, headers)) if len(block_body_bundles) == 0: self.logger.debug( "Got block bodies for 0/%d headers from %s, from %r..%r", len(headers), peer, headers[0], headers[-1], ) return tuple(), tuple() bodies_by_root = { (transaction_root, uncles_hash): block_body for block_body, (transaction_root, _), uncles_hash in block_body_bundles } header_roots = { header: (header.transaction_root, header.uncles_hash) for header in headers } completed_header_roots = valfilter(lambda root: root in bodies_by_root, header_roots) completed_headers = tuple(completed_header_roots.keys()) # store bodies for later usage, during block import pending_bodies = { header: bodies_by_root[root] for header, root in completed_header_roots.items() } self._pending_bodies = merge(self._pending_bodies, pending_bodies) self.logger.debug( "Got block bodies for %d/%d headers from %s, from %r..%r", len(completed_header_roots), len(headers), peer, headers[0], headers[-1], ) return block_body_bundles, completed_headers
def _mk_attestations_for_epoch_by_count(number_of_committee_samples, epoch, block_producer, state, config): results = {} for _ in range(number_of_committee_samples): sample = _mk_attestation_inputs_in_epoch(epoch, block_producer, state, config) results = merge(results, sample) return results
def _mk_pre_index_from_attestations( self, state: BeaconState, attestations: Sequence[AttestationLike]) -> PreIndex: """ A 'pre-index' is a Dict[ValidatorIndex, Tuple[Slot, AttestationData]]. """ return merge( *mapcat(self._mk_pre_index_from_attestation(state), attestations))
def modifyTransaction( self, transaction_hash: _Hash32, **transaction_params: Any ) -> HexBytes: assert_valid_transaction_params(cast(TxParams, transaction_params)) current_transaction = get_required_transaction(self.web3, transaction_hash) current_transaction_params = extract_valid_transaction_params(current_transaction) new_transaction = merge(current_transaction_params, transaction_params) return replace_transaction(self.web3, current_transaction, new_transaction)
def modifyTransaction(self, transaction_hash, **transaction_params): assert_valid_transaction_params(transaction_params) current_transaction = get_required_transaction(self.web3, transaction_hash) current_transaction_params = extract_valid_transaction_params( current_transaction) new_transaction = merge(current_transaction_params, transaction_params) return replace_transaction(self.web3, current_transaction, new_transaction)
def get_subprocess_kwargs(self) -> SubprocessKwargs: # This is needed so that pytest can capture the subproc's output. Otherwise it will crash # with a "io.UnsupportedOperation: redirected stdin is pseudofile, has no fileno()" error. return merge( super().get_subprocess_kwargs(), { 'stdin': subprocess.PIPE, 'stdout': subprocess.PIPE, 'stderr': subprocess.PIPE, })
def validate_logging(logging_dict: Dict) -> Dict: """validate the logging dictionary We don't do much here, but instead rely on the main function to catch errors from logging.config.dictConfig """ if not isinstance(logging_dict, dict): raise ValueError("logging must be a dictionary") return merge({"version": 1, "incremental": True}, logging_dict)
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 formatter_middleware(make_request, w3): formatters = merge( { 'request_formatters': {}, 'result_formatters': {}, 'error_formatters': {}, }, web3_formatters_builder(w3), ) return apply_formatters(make_request=make_request, **formatters)
def generate_go_ethereum_fixture(destination_dir): with contextlib.ExitStack() as stack: datadir = stack.enter_context(tempdir()) keystore_dir = os.path.join(datadir, 'keystore') ensure_path_exists(keystore_dir) keyfile_path = os.path.join(keystore_dir, KEYFILE_FILENAME) with open(keyfile_path, 'w') as keyfile: keyfile.write(KEYFILE_DATA) genesis_file_path = os.path.join(datadir, 'genesis.json') with open(genesis_file_path, 'w') as genesis_file: genesis_file.write(json.dumps(GENESIS_DATA)) geth_ipc_path_dir = stack.enter_context(tempdir()) geth_ipc_path = os.path.join(geth_ipc_path_dir, 'geth.ipc') geth_port = get_open_port() geth_binary = get_geth_binary() with get_geth_process( geth_binary=geth_binary, datadir=datadir, genesis_file_path=genesis_file_path, geth_ipc_path=geth_ipc_path, geth_port=geth_port): wait_for_socket(geth_ipc_path) web3 = Web3(Web3.IPCProvider(geth_ipc_path)) chain_data = setup_chain_state(web3) # close geth by exiting context # must be closed before copying data dir verify_chain_state(web3, chain_data) # verify that chain state is still valid after closing # and re-opening geth with get_geth_process( geth_binary=geth_binary, datadir=datadir, genesis_file_path=genesis_file_path, geth_ipc_path=geth_ipc_path, geth_port=geth_port): wait_for_socket(geth_ipc_path) web3 = Web3(Web3.IPCProvider(geth_ipc_path)) verify_chain_state(web3, chain_data) static_data = { 'raw_txn_account': RAW_TXN_ACCOUNT, 'keyfile_pw': KEYFILE_PW, } config = merge(chain_data, static_data) pprint.pprint(config) write_config_json(config, datadir) shutil.make_archive(destination_dir, 'zip', datadir)
def formatter_middleware( make_request: Callable[[RPCEndpoint, Any], Any], w3: "Web3") -> Callable[[RPCEndpoint, Any], RPCResponse]: formatters = merge( { "request_formatters": {}, "result_formatters": {}, "error_formatters": {}, }, web3_formatters_builder(w3), ) return apply_formatters(make_request=make_request, **formatters)
def merge_genesis_overrides(defaults, overrides): allowed_fields = set(defaults.keys()) override_fields = set(overrides.keys()) unexpected_fields = tuple( sorted(override_fields.difference(allowed_fields))) if unexpected_fields: err = "The following invalid fields were supplied to override default genesis values: {0}." raise ValueError(err.format(unexpected_fields)) merged_params = merge(defaults, overrides) return merged_params
def load_config(path: str) -> Dict[str, Any]: if path is None: user_config = {} else: user_config = toml.load(path) environment_config = load_config_from_environment() config = merge(OPTIONAL_CONFIG_ENTRIES_WITH_DEFAULTS, user_config, environment_config) return validate_config(config)
def middleware(method: RPCEndpoint, params: Any) -> RPCResponse: formatters = merge( FORMATTER_DEFAULTS, web3_formatters_builder(w3, method), ) request_formatters = formatters.pop('request_formatters') if method in request_formatters: formatter = request_formatters[method] params = formatter(params) response = make_request(method, params) return _apply_response_formatters(method=method, response=response, **formatters)
def commit_changeset(self, changeset_id: uuid.UUID) -> Dict[bytes, bytes]: """ Collapses all changes for the given changeset into the previous changesets if it exists. """ changeset_data = self.pop_changeset(changeset_id) if not self.is_empty(): # we only have to merge the changes into the latest changeset if # there is one. self.latest = merge( self.latest, changeset_data, ) return changeset_data
def create_test_block(parent=None, **kwargs): defaults = { "slot": SERENITY_CONFIG.GENESIS_SLOT, "previous_block_root": ZERO_HASH32, "state_root": ZERO_HASH32, # note: not the actual genesis state root "signature": EMPTY_SIGNATURE, "body": BeaconBlockBody.create_empty_body() } if parent is not None: kwargs["previous_block_root"] = parent.signing_root kwargs["slot"] = parent.slot + 1 return BeaconBlock(**merge(defaults, kwargs))
def normalize_unsigned_transaction(transaction: TransactionDict, indexes: Dict[str, Any]) -> TransactionDict: normalized = normalize_transaction_group(transaction) return merge(normalized, { # Dynamic key access not yet allowed with TypedDict # https://github.com/python/mypy/issues/5359 transaction_key: normalized[transaction_key][indexes[index_key]] # type: ignore for transaction_key, index_key in [ ("gasLimit", "gas"), ("value", "value"), ("data", "data"), ] if index_key in indexes })
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 fill_transaction_defaults(web3, transaction): """ if web3 is None, fill as much as possible while offline """ defaults = {} for key, default_getter in TRANSACTION_DEFAULTS.items(): if key not in transaction: if callable(default_getter): if web3 is not None: default_val = default_getter(web3, transaction) else: raise ValueError("You must specify %s in the transaction" % key) else: default_val = default_getter defaults[key] = default_val return merge(defaults, transaction)
def create_test_block(parent=None, **kwargs): defaults = { "slot": 0, "parent_root": ZERO_HASH32, "state_root": ZERO_HASH32, # note: not the actual genesis state root "randao_reveal": ZERO_HASH32, "candidate_pow_receipt_root": ZERO_HASH32, "signature": (0, 0), "body": empty_body() } if parent is not None: kwargs["parent_root"] = parent.root kwargs["slot"] = parent.slot + 1 return BeaconBlock(**merge(defaults, kwargs))
def create_test_block(parent=None, **kwargs): defaults = { "slot": 0, "parent_root": ZERO_HASH32, "state_root": ZERO_HASH32, # note: not the actual genesis state root "randao_reveal": EMPTY_SIGNATURE, "eth1_data": Eth1Data.create_empty_data(), "signature": EMPTY_SIGNATURE, "body": BeaconBlockBody.create_empty_body() } if parent is not None: kwargs["parent_root"] = parent.root kwargs["slot"] = parent.slot + 1 return BeaconBlock(**merge(defaults, kwargs))
def create_test_block(parent=None, **kwargs): defaults = { "slot": 0, "randao_reveal": ZERO_HASH32, "candidate_pow_receipt_root": ZERO_HASH32, "ancestor_hashes": [ZERO_HASH32] * 32, "state_root": ZERO_HASH32, # note: not the actual genesis state root "attestations": [], "specials": [], "proposer_signature": None, } if parent is not None: kwargs["ancestor_hashes"] = [parent.hash] + [ZERO_HASH32] * 31 kwargs["slot"] = parent.slot + 1 return BaseBeaconBlock(**merge(defaults, kwargs))
def buildBuyTicketTx(transaction, defaultChainId): defaults = {} alreadygot = {} for key, default_val in BUYTICKET_DEFAULTS.items(): if key not in transaction: defaults[key] = default_val for key, val in transaction.items(): if key in VALID_BUYTICKET_PARAMS: alreadygot[key] = transaction[key] transaction_merged = merge(defaults, alreadygot) transaction_merged['chainId'] = defaultChainId transaction_new = unsigned_buyticket_formatter(transaction_merged) assert_check_buyticket_params(transaction_new) return transaction_new
def buildTakeSwapTx(transaction, defaultChainId): defaults = {} alreadygot = {} for key, default_val in TAKESWAP_DEFAULTS.items(): if key not in transaction: defaults[key] = default_val for key, val in transaction.items(): if key in VALID_TAKESWAP_PARAMS: alreadygot[key] = transaction[key] transaction_merged = merge(defaults, alreadygot) transaction_merged['chainId'] = defaultChainId transaction_new = unsigned_takeswap_formatter(transaction_merged) assert_check_takeswap_params(transaction_new) return transaction_new
def buildGenAssetTx(transaction, defaultChainId): defaults = {} alreadygot = {} for key, default_val in GENASSET_DEFAULTS.items(): if key not in transaction: defaults[key] = default_val for key, val in transaction.items(): if key in VALID_GENASSETTX_PARAMS: alreadygot[key] = transaction[key] transaction_merged = merge(defaults, alreadygot) transaction_merged['chainId'] = defaultChainId transaction_new = unsigned_assetcreate_formatter(transaction_merged) assert_check_gen_asset_params(transaction_new) return transaction_new
def buildTimeLockToAssetTx(transaction, defaultChainId): defaults = {} alreadygot = {} for key, default_val in TLTOASSET_DEFAULTS.items(): if key not in transaction: defaults[key] = default_val for key, val in transaction.items(): if key in VALID_TLTOASSET_PARAMS: alreadygot[key] = transaction[key] transaction_merged = merge(defaults, alreadygot) transaction_merged['chainId'] = defaultChainId transaction_new = unsigned_tltoasset_formatter(transaction_merged) assert_check_tltoasset_params(transaction_new) return transaction_new
def buildSendToTimeLockTx(transaction, defaultChainId): defaults = {} alreadygot = {} for key, default_val in SENDTOTL_DEFAULTS.items(): if key not in transaction: defaults[key] = default_val for key, val in transaction.items(): if key in VALID_SENDTOTL_PARAMS: alreadygot[key] = transaction[key] transaction_merged = merge(defaults, alreadygot) transaction_merged['chainId'] = defaultChainId transaction_new = unsigned_sendtotl_formatter(transaction_merged) assert_check_sendtotl_params(transaction_new) return transaction_new
def test_signed_transaction(w3, fund_account, transaction, expected, key_object, from_): w3.middleware_onion.add(construct_sign_and_send_raw_middleware(key_object)) # Drop any falsy addresses to_from = valfilter(bool, {'to': w3.eth.accounts[0], 'from': from_}) _transaction = merge(transaction, to_from) if isinstance(expected, type) and issubclass(expected, Exception): with pytest.raises(expected): w3.eth.send_transaction(_transaction) else: start_balance = w3.eth.get_balance( _transaction.get('from', w3.eth.accounts[0])) w3.eth.send_transaction(_transaction) assert w3.eth.get_balance( _transaction.get('from')) <= start_balance + expected
def set_text( self, name: str, key: str, value: str, transact: "TxParams" = None ) -> HexBytes: """ Set the value of a text record of an ENS name. :param str name: ENS name :param str key: Name of the attribute to set :param str value: Value to set the attribute to :param dict transact: The transaction configuration, like in :meth:`~web3.eth.Eth.send_transaction` :return: Transaction hash :rtype: HexBytes :raises UnsupportedFunction: If the resolver does not support the "0x59d1d43c" interface id :raises ResolverNotFound: If no resolver is found for the provided name """ if not transact: transact = {} owner = self.owner(name) node = raw_name_to_hash(name) normal_name = normalize_name(name) transaction_dict = merge({'from': owner}, transact) r = self.resolver(normal_name) if r: if _resolver_supports_interface(r, GET_TEXT_INTERFACE_ID): return r.functions.setText(node, key, value).transact(transaction_dict) else: raise UnsupportedFunction( f"Resolver for name `{name}` does not support `text` function" ) else: raise ResolverNotFound( f"No resolver found for name `{name}`. It is likely the name contains an " "unsupported top level domain (tld)." )
def __init__( self, private_key: keys.PrivateKey, enr_db: ENRDatabaseAPI, kv_pairs: Optional[Mapping[bytes, bytes]] = None, identity_scheme_registry: IdentitySchemeRegistryAPI = default_identity_scheme_registry, # noqa: E501 ) -> None: self._identity_scheme_registry = identity_scheme_registry self._private_key = private_key self._enr_db = enr_db if kv_pairs is None: kv_pairs = {} if b"id" in kv_pairs: identity_kv_pairs = {} else: identity_kv_pairs = { b"id": b"v4", b"secp256k1": self._private_key.public_key.to_compressed_bytes(), } minimal_enr = UnsignedENR( sequence_number=1, kv_pairs=merge(identity_kv_pairs, kv_pairs), identity_scheme_registry=self._identity_scheme_registry, ).to_signed_enr(self._private_key.to_bytes()) self._node_id = minimal_enr.node_id try: base_enr = self._enr_db.get_enr(minimal_enr.node_id) except KeyError: self.logger.info( "ENR created: seq=%d enr=%r", minimal_enr.sequence_number, minimal_enr, ) self._enr = minimal_enr self._enr_db.set_enr(self._enr) else: self._enr = base_enr self.update(*tuple(kv_pairs.items()))