|  | 
| 1 | 1 | """JSON-RPC methods and helper functions for EEST consume based hive simulators.""" | 
| 2 | 2 | 
 | 
| 3 |  | -import json | 
| 4 |  | -import logging | 
| 5 | 3 | import time | 
| 6 | 4 | from itertools import count | 
| 7 |  | -from pathlib import Path | 
| 8 | 5 | from pprint import pprint | 
| 9 | 6 | from typing import Any, ClassVar, Dict, List, Literal, Union | 
| 10 | 7 | 
 | 
|  | 
| 14 | 11 | 
 | 
| 15 | 12 | from ethereum_test_base_types import Address, Bytes, Hash, to_json | 
| 16 | 13 | from ethereum_test_types import Transaction | 
| 17 |  | -from pytest_plugins.logging import get_logger | 
| 18 | 14 | 
 | 
| 19 | 15 | from .types import ( | 
| 20 | 16 |     ForkchoiceState, | 
|  | 
| 28 | 24 | ) | 
| 29 | 25 | 
 | 
| 30 | 26 | BlockNumberType = Union[int, Literal["latest", "earliest", "pending"]] | 
| 31 |  | -logger = get_logger(__name__) | 
| 32 | 27 | 
 | 
| 33 | 28 | 
 | 
| 34 | 29 | class SendTransactionExceptionError(Exception): | 
| 35 | 30 |     """Represent an exception that is raised when a transaction fails to be sent.""" | 
| 36 | 31 | 
 | 
| 37 | 32 |     tx: Transaction | None = None | 
| 38 | 33 |     tx_rlp: Bytes | None = None | 
| 39 |  | -    shorten_errors: bool = False | 
| 40 |  | -    log_rlp_data: bool = False | 
| 41 | 34 | 
 | 
| 42 |  | -    def __init__( | 
| 43 |  | -        self, | 
| 44 |  | -        *args, | 
| 45 |  | -        tx: Transaction | None = None, | 
| 46 |  | -        tx_rlp: Bytes | None = None, | 
| 47 |  | -        shorten_errors: bool = False, | 
| 48 |  | -        log_rlp_data: bool = False, | 
| 49 |  | -    ): | 
|  | 35 | +    def __init__(self, *args, tx: Transaction | None = None, tx_rlp: Bytes | None = None): | 
| 50 | 36 |         """Initialize SendTransactionExceptionError class with the given transaction.""" | 
| 51 | 37 |         super().__init__(*args) | 
| 52 | 38 |         self.tx = tx | 
| 53 | 39 |         self.tx_rlp = tx_rlp | 
| 54 |  | -        self.shorten_errors = shorten_errors | 
| 55 |  | -        self.log_rlp_data = log_rlp_data | 
| 56 | 40 | 
 | 
| 57 | 41 |     def __str__(self): | 
| 58 | 42 |         """Return string representation of the exception.""" | 
| 59 |  | -        # create ./logs/rlp folder for detailed rlp logging | 
| 60 |  | -        rlp_logs_folder = Path(".") / "logs" / "rlp" | 
| 61 |  | -        rlp_logs_folder.mkdir(parents=True, exist_ok=True) | 
| 62 |  | - | 
| 63 | 43 |         if self.tx is not None: | 
| 64 | 44 |             f"{super().__str__()} Transaction={self.tx.model_dump_json()}" | 
| 65 | 45 |         elif self.tx_rlp is not None: | 
| 66 |  | -            tx_rlp_hex = self.tx_rlp.hex() | 
| 67 |  | - | 
| 68 |  | -            # log rpc call data to file (each rlp object gets dumped in its own file) | 
| 69 |  | -            if self.log_rlp_data: | 
| 70 |  | -                #   create and config a temporary logger (unique filename via timestamp) | 
| 71 |  | -                timestamp = time.time_ns() | 
| 72 |  | -                file_name = rlp_logs_folder / f"{timestamp}_rlp_data.log" | 
| 73 |  | -                temp_logger = logging.getLogger(f"rlp_{timestamp}") | 
| 74 |  | -                temp_logger.setLevel(logging.ERROR) | 
| 75 |  | -                temp_logger.propagate = False | 
| 76 |  | -                file_handler = logging.FileHandler(file_name) | 
| 77 |  | -                temp_logger.addHandler(file_handler) | 
| 78 |  | -                #   log rlp to file | 
| 79 |  | -                temp_logger.error(tx_rlp_hex) | 
| 80 |  | -                #   cleanup | 
| 81 |  | -                temp_logger.removeHandler(file_handler) | 
| 82 |  | -                file_handler.close() | 
| 83 |  | - | 
| 84 |  | -            if self.shorten_errors: | 
| 85 |  | -                tx_rlp_hex = tx_rlp_hex[:50]  # just print first few chars | 
| 86 |  | -            return f"{super().__str__()} Transaction RLP={tx_rlp_hex}" | 
| 87 |  | - | 
|  | 46 | +            return f"{super().__str__()} Transaction RLP={self.tx_rlp.hex()}" | 
| 88 | 47 |         return super().__str__() | 
| 89 | 48 | 
 | 
| 90 | 49 | 
 | 
| @@ -132,15 +91,6 @@ def post_request(self, method: str, *params: Any, extra_headers: Dict | None = N | 
| 132 | 91 |         } | 
| 133 | 92 |         headers = base_header | self.extra_headers | extra_headers | 
| 134 | 93 | 
 | 
| 135 |  | -        # debugging, estimate payload size | 
| 136 |  | -        payload_json = json.dumps(payload)  # pydantic.json | 
| 137 |  | -        payload_size_bytes = len(payload_json.encode("utf-8")) | 
| 138 |  | -        payload_size_mb = payload_size_bytes / (1024 * 1024) | 
| 139 |  | -        logger.debug( | 
| 140 |  | -            f"POST request of approximated size: {payload_size_mb:.2f} MB " | 
| 141 |  | -            f"({payload_size_bytes} bytes)" | 
| 142 |  | -        ) | 
| 143 |  | - | 
| 144 | 94 |         response = requests.post(self.url, json=payload, headers=headers) | 
| 145 | 95 |         response.raise_for_status() | 
| 146 | 96 |         response_json = response.json() | 
| @@ -228,40 +178,23 @@ def gas_price(self) -> int: | 
| 228 | 178 |     def send_raw_transaction(self, transaction_rlp: Bytes) -> Hash: | 
| 229 | 179 |         """`eth_sendRawTransaction`: Send a transaction to the client.""" | 
| 230 | 180 |         try: | 
| 231 |  | -            tx_rlp_hex = transaction_rlp.hex() | 
| 232 |  | -            result_hash = Hash(self.post_request("sendRawTransaction", f"{tx_rlp_hex}")) | 
| 233 |  | -            assert result_hash is not None, "result_hash seems to be None, critical error!" | 
| 234 |  | - | 
| 235 |  | -            # if you wrap SendTransactionExceptionError in print() it will get logged to file | 
| 236 |  | -            SendTransactionExceptionError( | 
| 237 |  | -                str("no error"), tx_rlp=transaction_rlp, shorten_errors=True, log_rlp_data=False | 
| 238 |  | -            ) | 
| 239 |  | - | 
|  | 181 | +            result_hash = Hash(self.post_request("sendRawTransaction", f"{transaction_rlp.hex()}")) | 
|  | 182 | +            assert result_hash is not None | 
| 240 | 183 |             return result_hash | 
| 241 | 184 |         except Exception as e: | 
| 242 |  | -            raise SendTransactionExceptionError( | 
| 243 |  | -                str(e), tx_rlp=transaction_rlp, shorten_errors=True, log_rlp_data=True | 
| 244 |  | -            ) from e | 
|  | 185 | +            raise SendTransactionExceptionError(str(e), tx_rlp=transaction_rlp) from e | 
| 245 | 186 | 
 | 
| 246 | 187 |     def send_transaction(self, transaction: Transaction) -> Hash: | 
| 247 | 188 |         """`eth_sendRawTransaction`: Send a transaction to the client.""" | 
| 248 | 189 |         try: | 
| 249 |  | -            transaction_rlp = transaction.rlp() | 
| 250 |  | -            tx_rlp_hex = transaction_rlp.hex() | 
| 251 |  | -            result_hash = Hash(self.post_request("sendRawTransaction", f"{tx_rlp_hex}")) | 
|  | 190 | +            result_hash = Hash( | 
|  | 191 | +                self.post_request("sendRawTransaction", f"{transaction.rlp().hex()}") | 
|  | 192 | +            ) | 
| 252 | 193 |             assert result_hash == transaction.hash | 
| 253 | 194 |             assert result_hash is not None | 
| 254 |  | - | 
| 255 |  | -            # if you wrap SendTransactionExceptionError in print() it will get logged to file | 
| 256 |  | -            SendTransactionExceptionError( | 
| 257 |  | -                str("no error"), tx_rlp=transaction_rlp, shorten_errors=True, log_rlp_data=False | 
| 258 |  | -            ) | 
| 259 |  | - | 
| 260 | 195 |             return transaction.hash | 
| 261 | 196 |         except Exception as e: | 
| 262 |  | -            raise SendTransactionExceptionError( | 
| 263 |  | -                str(e), tx=transaction, shorten_errors=True, log_rlp_data=True | 
| 264 |  | -            ) from e | 
|  | 197 | +            raise SendTransactionExceptionError(str(e), tx=transaction) from e | 
| 265 | 198 | 
 | 
| 266 | 199 |     def send_transactions(self, transactions: List[Transaction]) -> List[Hash]: | 
| 267 | 200 |         """Use `eth_sendRawTransaction` to send a list of transactions to the client.""" | 
|  | 
0 commit comments