Esempio n. 1
0
def test_equality(identity_scheme_registry):
    base_kwargs = {
        "sequence_number": 0,
        "kv_pairs": {
            b"id": b"mock",
            b"key1": b"value1",
            b"key2": b"value2",
        },
        "signature": b"signature",
        "identity_scheme_registry": identity_scheme_registry,
    }

    base_enr = ENR(**base_kwargs)
    equal_enr = ENR(**base_kwargs)
    enr_different_sequence_number = ENR(
        **assoc(base_kwargs, "sequence_number", 1))
    enr_different_kv_pairs = ENR(
        **assoc_in(base_kwargs, ("kv_pairs", b"key1"), b"value2"), )
    enr_different_signature = ENR(
        **assoc(base_kwargs, "signature", b"different-signature"))

    assert base_enr == base_enr
    assert equal_enr == base_enr
    assert enr_different_sequence_number != base_enr
    assert enr_different_kv_pairs != base_enr
    assert enr_different_signature != base_enr
Esempio n. 2
0
def check_manifest_version(manifest: Manifest,
                           warnings: Dict[str, str]) -> Dict[str, str]:
    if "manifest" not in manifest or not manifest["manifest"]:
        return assoc(warnings, "manifest", WARNINGS["manifest_missing"])
    if manifest["manifest"] != "ethpm/3":
        return assoc(warnings, "manifest", WARNINGS["manifest_invalid"])
    return warnings
Esempio n. 3
0
def apply_formatters(
    method: RPCEndpoint,
    params: Any,
    make_request: Callable[[RPCEndpoint, Any], RPCResponse],
    request_formatters: Formatters,
    result_formatters: Formatters,
    error_formatters: Formatters,
) -> RPCResponse:
    if method in request_formatters:
        formatter = request_formatters[method]
        formatted_params = formatter(params)
        response = make_request(method, formatted_params)
    else:
        response = make_request(method, params)

    if "result" in response and method in result_formatters:
        formatter = result_formatters[method]
        formatted_response = assoc(
            response,
            "result",
            formatter(response["result"]),
        )
        return formatted_response
    elif "error" in response and method in error_formatters:
        formatter = error_formatters[method]
        formatted_response = assoc(
            response,
            "error",
            formatter(response["error"]),
        )
        return formatted_response
    else:
        return response
Esempio n. 4
0
def prepare_replacement_transaction(web3: "Web3", current_transaction: TxData,
                                    new_transaction: TxParams) -> TxParams:
    if current_transaction['blockHash'] is not None:
        raise ValueError(
            'Supplied transaction with hash {} has already been mined'.format(
                current_transaction['hash']))
    if 'nonce' in new_transaction and new_transaction[
            'nonce'] != current_transaction['nonce']:
        raise ValueError(
            'Supplied nonce in new_transaction must match the pending transaction'
        )

    if 'nonce' not in new_transaction:
        new_transaction = assoc(new_transaction, 'nonce',
                                current_transaction['nonce'])

    if 'gasPrice' in new_transaction:
        if new_transaction['gasPrice'] <= current_transaction['gasPrice']:
            raise ValueError(
                'Supplied gas price must exceed existing transaction gas price'
            )
    else:
        generated_gas_price = web3.eth.generateGasPrice(new_transaction)
        minimum_gas_price = int(
            math.ceil(current_transaction['gasPrice'] * 1.1))
        if generated_gas_price and generated_gas_price > minimum_gas_price:
            new_transaction = assoc(new_transaction, 'gasPrice',
                                    generated_gas_price)
        else:
            new_transaction = assoc(new_transaction, 'gasPrice',
                                    minimum_gas_price)

    return new_transaction
Esempio n. 5
0
def check_package_name(manifest: Manifest,
                       warnings: Dict[str, str]) -> Dict[str, str]:
    if "name" not in manifest or not manifest["name"]:
        return assoc(warnings, "name", WARNINGS["name_missing"])
    if not bool(re.match(PACKAGE_NAME_REGEX, manifest["name"])):
        return assoc(warnings, "name", WARNINGS["name_invalid"])
    return warnings
Esempio n. 6
0
def validate_transaction_params(transaction: TxParams, latest_block: BlockData,
                                strategy_based_gas_price: Wei) -> TxParams:
    # gas price strategy explicitly set:
    if (strategy_based_gas_price is not None and 'gasPrice' not in transaction
            and none_in_dict(DYNAMIC_FEE_TXN_PARAMS, transaction)):
        transaction = assoc(transaction, 'gasPrice',
                            hex(strategy_based_gas_price))

    # legacy and dynamic fee tx variables used:
    if "gasPrice" in transaction and any_in_dict(DYNAMIC_FEE_TXN_PARAMS,
                                                 transaction):
        raise TransactionTypeMismatch()
    # dynamic fee transaction - canonical case:
    elif all_in_dict(DYNAMIC_FEE_TXN_PARAMS, transaction):
        if int(str(transaction["maxFeePerGas"]), 16) < int(
                str(transaction["maxPriorityFeePerGas"]), 16):
            raise InvalidTransaction(
                "maxFeePerGas must be >= maxPriorityFeePerGas")
    # dynamic fee txn - no max fee:
    elif 'maxFeePerGas' not in transaction and 'maxPriorityFeePerGas' in transaction:
        base_fee = latest_block['baseFeePerGas']
        priority_fee = int(str(transaction['maxPriorityFeePerGas']), 16)
        max_fee_per_gas = priority_fee + 2 * base_fee
        transaction = assoc(transaction, 'maxFeePerGas', hex(max_fee_per_gas))
    # dynamic fee transaction - no priority fee:
    elif 'maxFeePerGas' in transaction and 'maxPriorityFeePerGas' not in transaction:
        raise InvalidTransaction(
            "maxPriorityFeePerGas must be defined in a 1559 transaction.")

    # should be a fully formed (legacy or dynamic fee) tx or no fee values were specified
    return transaction
def apply_formatters(method, params, make_request, request_formatters,
                     result_formatters, error_formatters):
    if method in request_formatters:
        formatter = request_formatters[method]
        formatted_params = formatter(params)
        response = make_request(method, formatted_params)
    else:
        response = make_request(method, params)

    if 'result' in response and method in result_formatters:
        formatter = result_formatters[method]
        formatted_response = assoc(
            response,
            'result',
            formatter(response['result']),
        )
        return formatted_response
    elif 'error' in response and method in error_formatters:
        formatter = error_formatters[method]
        formatted_response = assoc(
            response,
            'error',
            formatter(response['error']),
        )
        return formatted_response
    else:
        return response
Esempio n. 8
0
def test_builder_with_alias_and_select_contract_types(owned_package_devdoc):
    _, _, compiler_output = owned_package_devdoc

    manifest = build(
        BASE_MANIFEST,
        contract_type(
            "Owned",
            compiler_output,
            alias="OwnedAlias",
            abi=True,
            natspec=True,
            deployment_bytecode=True,
            runtime_bytecode=True,
            compiler=True,
        ),
        validate(),
    )

    contract_type_data = normalize_contract_type(
        compiler_output["Owned.sol"]["Owned"])
    expected = assoc(
        BASE_MANIFEST,
        "contract_types",
        {"OwnedAlias": assoc(contract_type_data, "contract_type", "Owned")},
    )
    assert manifest == expected
Esempio n. 9
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: 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)
Esempio n. 10
0
    def send_transaction_munger(self, transaction: TxParams) -> Tuple[TxParams]:
        # TODO: move to middleware
        if 'from' not in transaction and is_checksum_address(self.default_account):
            transaction = assoc(transaction, 'from', self.default_account)

        # TODO: move gas estimation in middleware
        if 'gas' not in transaction:
            transaction = assoc(
                transaction,
                'gas',
                get_buffered_gas_estimate(self.web3, transaction),
            )
        return (transaction,)
Esempio n. 11
0
def test_builder_with_default_contract_types(owned_package):
    _, _, compiler_output = owned_package

    manifest = build(BASE_MANIFEST, contract_type("Owned", compiler_output),
                     validate())

    contract_type_data = normalize_contract_type(
        compiler_output["Owned.sol"]["Owned"], "Owned.sol")
    compilers_data = contract_type_data.pop('compiler')
    compilers_data["contractTypes"] = ["Owned"]
    expected_with_contract_type = assoc(BASE_MANIFEST, "contractTypes",
                                        {"Owned": contract_type_data})
    expected = assoc(expected_with_contract_type, "compilers",
                     [compilers_data])
    assert manifest == expected
Esempio n. 12
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,
    }})
Esempio n. 13
0
def test_builder_simple_with_multi_meta_field():
    manifest = build(
        BASE_MANIFEST,
        authors("some", "guy"),
        license("MIT"),
        description("description"),
        keywords("awesome", "package"),
        links(website="www", repository="github"),
        validate(),
    )
    expected = assoc(
        BASE_MANIFEST,
        "meta",
        {
            "license": "MIT",
            "authors": ["some", "guy"],
            "description": "description",
            "keywords": ["awesome", "package"],
            "links": {
                "website": "www",
                "repository": "github"
            },
        },
    )
    assert manifest == expected
Esempio n. 14
0
def fill_default(field: str, guess_func: Callable[..., Any], web3: "Web3",
                 transaction: TxParams) -> TxParams:
    if field in transaction and transaction[field] is not None:
        return transaction
    else:
        guess_val = guess_func(web3, transaction)
        return assoc(transaction, field, guess_val)
Esempio n. 15
0
    def test_manual_mine_pending_transactions(self, eth_tester, test_transaction):
        accounts = eth_tester.get_accounts()
        assert accounts, "No accounts available for transaction sending"

        complete_transaction = assoc(test_transaction, 'from', accounts[0])

        self.skip_if_no_evm_execution()
        eth_tester.mine_blocks()
        eth_tester.disable_auto_mine_transactions()

        txn_hash = eth_tester.send_transaction(complete_transaction)

        with pytest.raises(TransactionNotFound):
            eth_tester.get_transaction_receipt(txn_hash)

        pending_transaction = eth_tester.get_transaction_by_hash(txn_hash)
        self._check_transactions(complete_transaction, pending_transaction)

        eth_tester.mine_block()

        receipt = eth_tester.get_transaction_receipt(txn_hash)
        assert receipt['transaction_hash'] == txn_hash
        assert receipt['block_number']

        mined_transaction = eth_tester.get_transaction_by_hash(txn_hash)
        self._check_transactions(complete_transaction, mined_transaction)
Esempio n. 16
0
def _corrupt_validator_indices(params):
    corrupt_validator_indices = (
        params["validator_indices"][1],
        params["validator_indices"][0],
    ) + tuple(params["validator_indices"][2:])

    return assoc(params, "validator_indices", corrupt_validator_indices)
Esempio n. 17
0
def extract_valid_transaction_params(transaction_params: TxData) -> TxParams:
    extracted_params = cast(
        TxParams, {
            key: transaction_params[key]
            for key in VALID_TRANSACTION_PARAMS if key in transaction_params
        })
    # There is always a gasPrice now on eth_getTransaction call for pending transactions, including
    # dynamic fee transactions. For dynamic fee transactions, we need to pull the gasPrice value
    # back out of the extracted params if it is equal to the expected value (maxFeePerGas). If
    # we don't, the modified transaction will include a gasPrice as well as dynamic fee values in
    # the eth_sendTransaction call and cause a conflict.
    if all_in_dict(DYNAMIC_FEE_TXN_PARAMS, extracted_params):
        if extracted_params['gasPrice'] == extracted_params['maxFeePerGas']:
            extracted_params.pop('gasPrice')

    if extracted_params.get('data') is not None:
        if transaction_params.get('input') is not None:
            if extracted_params['data'] != transaction_params['input']:
                msg = 'failure to handle this transaction due to both "input: {}" and'
                msg += ' "data: {}" are populated. You need to resolve this conflict.'
                err_vals = (transaction_params['input'],
                            extracted_params['data'])
                raise AttributeError(msg.format(*err_vals))
            else:
                return extracted_params
        else:
            return extracted_params
    elif extracted_params.get('data') is None:
        if transaction_params.get('input') is not None:
            return assoc(extracted_params, 'data', transaction_params['input'])
        else:
            return extracted_params
    else:
        raise Exception(
            "Unreachable path: transaction's 'data' is either set or not set")
Esempio n. 18
0
def serialize_block(block, transaction_serializer, is_pending):
    serialized_transactions = tuple(
        transaction_serializer(transaction, block, transaction_index, is_pending=is_pending)
        for transaction_index, transaction
        in enumerate(block['transactions'])
    )
    return assoc(block, 'transactions', serialized_transactions)
Esempio n. 19
0
    def _normalize_pending_transaction(pending_transaction):
        """
        Add the transaction type and, if a dynamic fee transaction, add gas_price =
        max_fee_per_gas as highlighted in the execution-specs link below.
        """
        _type = extract_transaction_type(pending_transaction)
        pending_transaction = assoc(pending_transaction, 'type', _type)

        # TODO: Sometime in 2022 the inclusion of gas_price may be removed from dynamic fee
        #  transactions and we can get rid of this behavior.
        #  https://github.com/ethereum/execution-specs/pull/251
        # add gas_price = max_fee_per_gas to pending dynamic fee transactions
        if _type == '0x2':
            pending_transaction = assoc(pending_transaction, 'gas_price',
                                        pending_transaction['max_fee_per_gas'])
        return pending_transaction
Esempio n. 20
0
def genesis_fields_from_fixture(fixture: Dict[str, Any]) -> Dict[str, Any]:
    """
    Convert all genesis fields in a fixture to a dictionary of header fields and values.
    """

    header_fields = fixture['genesisBlockHeader']
    base_fields = {
        'parent_hash': header_fields['parentHash'],
        'uncles_hash': header_fields['uncleHash'],
        'coinbase': header_fields['coinbase'],
        'state_root': header_fields['stateRoot'],
        'transaction_root': header_fields['transactionsTrie'],
        'receipt_root': header_fields['receiptTrie'],
        'bloom': header_fields['bloom'],
        'difficulty': header_fields['difficulty'],
        'block_number': header_fields['number'],
        'gas_limit': header_fields['gasLimit'],
        'gas_used': header_fields['gasUsed'],
        'timestamp': header_fields['timestamp'],
        'extra_data': header_fields['extraData'],
        'mix_hash': header_fields['mixHash'],
        'nonce': header_fields['nonce'],
    }
    if 'baseFeePerGas' in header_fields:
        return assoc(base_fields, 'base_fee_per_gas',
                     header_fields['baseFeePerGas'])
    else:
        return base_fields
Esempio n. 21
0
def generate_config_by_dict(dict_config: Dict[str, Any]) -> Eth2Config:
    filtered_keys = (
        "DOMAIN_",
        "ETH1_FOLLOW_DISTANCE",
        "TARGET_AGGREGATORS_PER_COMMITTEE",
        "RANDOM_SUBNETS_PER_VALIDATOR",
        "EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION",
        # Phase 1
        "MAX_EPOCHS_PER_CROSSLINK",
        "EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS",
        "EPOCHS_PER_CUSTODY_PERIOD",
        "CUSTODY_PERIOD_TO_RANDAO_PADDING",
        "SHARD_SLOTS_PER_BEACON_SLOT",
        "EPOCHS_PER_SHARD_PERIOD",
        "PHASE_1_FORK_EPOCH",
        "PHASE_1_FORK_SLOT",
    )

    return Eth2Config(**assoc(
        keyfilter(lambda name: all(key not in name for key in filtered_keys),
                  dict_config),
        "GENESIS_EPOCH",
        compute_epoch_at_slot(dict_config["GENESIS_SLOT"],
                              dict_config["SLOTS_PER_EPOCH"]),
    ))
Esempio n. 22
0
    def from_genesis(cls,
                     base_db: AtomicDatabaseAPI,
                     genesis_params: Dict[str, HeaderParams],
                     genesis_state: AccountState=None) -> 'BaseChain':
        genesis_vm_class = cls.get_vm_class_for_block_number(BlockNumber(0))

        pre_genesis_header = BlockHeader(difficulty=0, block_number=-1, gas_limit=0)
        chain_context = ChainContext(cls.chain_id)
        state = genesis_vm_class.build_state(base_db, pre_genesis_header, chain_context)

        if genesis_state is None:
            genesis_state = {}

        # mutation
        apply_state_dict(state, genesis_state)
        state.persist()

        if 'state_root' not in genesis_params:
            # If the genesis state_root was not specified, use the value
            # computed from the initialized state database.
            genesis_params = assoc(genesis_params, 'state_root', state.state_root)
        elif genesis_params['state_root'] != state.state_root:
            # If the genesis state_root was specified, validate that it matches
            # the computed state from the initialized state database.
            raise ValidationError(
                "The provided genesis state root does not match the computed "
                f"genesis state root.  Got {state.state_root!r}.  "
                f"Expected {genesis_params['state_root']!r}"
            )

        genesis_header = BlockHeader(**genesis_params)
        return cls.from_genesis_header(base_db, genesis_header)
Esempio n. 23
0
    def send_transaction_munger(self,
                                transaction: TxParams) -> Tuple[TxParams]:
        if 'from' not in transaction and is_checksum_address(
                self.default_account):
            transaction = assoc(transaction, 'from', self.default_account)

        return (transaction, )
Esempio n. 24
0
    def estimate_gas(self, transaction):
        evm_transaction = self._get_normalized_and_unsigned_evm_transaction(
            assoc(transaction, 'gas', 21000))
        spoofed_transaction = EVMSpoofTransaction(evm_transaction,
                                                  from_=transaction['from'])

        return self.chain.estimate_gas(spoofed_transaction)
Esempio n. 25
0
def _contract_type(
    name: str,
    compiler_output: Dict[str, Any],
    alias: Optional[str],
    selected_fields: Optional[List[str]],
    manifest: Manifest,
) -> Manifest:
    contracts_by_name = normalize_compiler_output(compiler_output)
    try:
        all_type_data = contracts_by_name[name]
    except KeyError:
        raise ManifestBuildingError(
            f"Contract name: {name} not found in the provided compiler output."
        )
    if selected_fields:
        contract_type_data = {
            k: v
            for k, v in all_type_data.items() if k in selected_fields
        }
    else:
        contract_type_data = all_type_data

    if alias:
        return assoc_in(
            manifest,
            ["contract_types", alias],
            assoc(contract_type_data, "contract_type", name),
        )
    return assoc_in(manifest, ["contract_types", name], contract_type_data)
Esempio n. 26
0
def _corrupt_attesting_indices(params):
    corrupt_attesting_indices = (
        params["attesting_indices"][1],
        params["attesting_indices"][0],
    ) + tuple(params["attesting_indices"][2:])

    return assoc(params, "attesting_indices", corrupt_attesting_indices)
Esempio n. 27
0
def serialize_full_transaction(transaction, block, transaction_index,
                               is_pending):
    if is_pending:
        block_number = None
        block_hash = None
        transaction_index = None
    else:
        block_number = block['number']
        block_hash = block['hash']

    serialized_transaction = pipe(
        transaction, partial(assoc, key='block_number', value=block_number),
        partial(assoc, key='block_hash', value=block_hash),
        partial(assoc, key='transaction_index', value=transaction_index),
        partial(assoc, key='type',
                value=extract_transaction_type(transaction)))

    if 'gas_price' in transaction:
        return serialized_transaction
    else:
        # TODO: Sometime in 2022 the inclusion of gas_price may be removed from dynamic fee
        #  transactions and we can get rid of this behavior.
        #  https://github.com/ethereum/execution-specs/pull/251
        gas_price = (transaction['max_fee_per_gas'] if is_pending else
                     calculate_effective_gas_price(transaction, block))
        return assoc(serialized_transaction, 'gas_price', gas_price)
Esempio n. 28
0
def extract_valid_transaction_params(transaction_params: TxData) -> TxParams:
    extracted_params = cast(
        TxParams, {
            key: transaction_params[key]
            for key in VALID_TRANSACTION_PARAMS if key in transaction_params
        })

    if extracted_params.get('data') is not None:
        if transaction_params.get('input') is not None:
            if extracted_params['data'] != transaction_params['input']:
                msg = 'failure to handle this transaction due to both "input: {}" and'
                msg += ' "data: {}" are populated. You need to resolve this conflict.'
                err_vals = (transaction_params['input'],
                            extracted_params['data'])
                raise AttributeError(msg.format(*err_vals))
            else:
                return extracted_params
        else:
            return extracted_params
    elif extracted_params.get('data') is None:
        if transaction_params.get('input') is not None:
            return assoc(extracted_params, 'data', transaction_params['input'])
        else:
            return extracted_params
    else:
        raise Exception(
            "Unreachable path: transaction's 'data' is either set or not set")
Esempio n. 29
0
    def sendTransaction(self, transaction: TxParams) -> HexBytes:
        # TODO: move to middleware
        if 'from' not in transaction and is_checksum_address(self.defaultAccount):
            transaction = assoc(transaction, 'from', self.defaultAccount)

        # TODO: move gas estimation in middleware
        if 'gas' not in transaction:
            transaction = assoc(
                transaction,
                'gas',
                get_buffered_gas_estimate(self.web3, transaction),
            )

        return self.web3.manager.request_blocking(
            RPC.eth_sendTransaction,
            [transaction],
        )
Esempio n. 30
0
 def decode(self, data: bytes) -> _DecodedMsgType:
     try:
         raw_decoded = cast(Dict[str, int], super().decode(data))
     except rlp.exceptions.ListDeserializationError:
         self.logger.warning("Malformed Disconnect message: %s", data)
         raise MalformedMessage(f"Malformed Disconnect message: {data}")
     return assoc(raw_decoded, 'reason_name',
                  self.get_reason_name(raw_decoded['reason']))