|
9 | 9 | from ethereum_test_base_types.base_types import Bytes |
10 | 10 | from ethereum_test_forks import Fork |
11 | 11 | from ethereum_test_rpc import BlobAndProofV1, BlobAndProofV2, EngineRPC, EthRPC |
12 | | -from ethereum_test_types import NetworkWrappedTransaction, Transaction, TransactionTestMetadata |
| 12 | +from ethereum_test_rpc.types import GetBlobsResponse |
| 13 | +from ethereum_test_types import NetworkWrappedTransaction, Transaction |
| 14 | +from ethereum_test_types.transaction_types import TransactionTestMetadata |
| 15 | +from pytest_plugins.logging import get_logger |
13 | 16 |
|
14 | 17 | from .base import BaseExecute |
15 | 18 |
|
| 19 | +logger = get_logger(__name__) |
| 20 | + |
16 | 21 |
|
17 | 22 | def versioned_hashes_with_blobs_and_proofs( |
18 | 23 | tx: NetworkWrappedTransaction, |
@@ -54,6 +59,7 @@ class BlobTransaction(BaseExecute): |
54 | 59 | requires_engine_rpc: ClassVar[bool] = True |
55 | 60 |
|
56 | 61 | txs: List[NetworkWrappedTransaction | Transaction] |
| 62 | + nonexisting_blob_hashes: List[Hash] | None = None |
57 | 63 |
|
58 | 64 | def execute( |
59 | 65 | self, fork: Fork, eth_rpc: EthRPC, engine_rpc: EngineRPC | None, request: FixtureRequest |
@@ -87,15 +93,39 @@ def execute( |
87 | 93 | ) |
88 | 94 | version = fork.engine_get_blobs_version() |
89 | 95 | assert version is not None, "Engine get blobs version is not supported by the fork." |
90 | | - blob_response = engine_rpc.get_blobs(list(versioned_hashes.keys()), version=version) |
| 96 | + |
| 97 | + # ensure that clients respond 'null' when they have no access to at least one blob |
| 98 | + list_versioned_hashes = list(versioned_hashes.keys()) |
| 99 | + if self.nonexisting_blob_hashes is not None: |
| 100 | + list_versioned_hashes.extend(self.nonexisting_blob_hashes) |
| 101 | + |
| 102 | + blob_response: GetBlobsResponse | None = engine_rpc.get_blobs( |
| 103 | + list_versioned_hashes, version=version |
| 104 | + ) # noqa: E501 |
| 105 | + |
| 106 | + # if non-existing blob hashes were request then the response must be 'null' |
| 107 | + if self.nonexisting_blob_hashes is not None: |
| 108 | + if blob_response is not None: |
| 109 | + raise ValueError( |
| 110 | + f"Non-existing blob hashes were requested and " |
| 111 | + "the client was expected to respond with 'null', but instead it replied: " |
| 112 | + f"{blob_response.root}" |
| 113 | + ) |
| 114 | + else: |
| 115 | + logger.info( |
| 116 | + "Test was passed (partial responses are not allowed and the client " |
| 117 | + "correctly returned 'null')" |
| 118 | + ) |
| 119 | + eth_rpc.wait_for_transactions(sent_txs) |
| 120 | + return |
| 121 | + |
| 122 | + assert blob_response is not None |
91 | 123 | local_blobs_and_proofs = list(versioned_hashes.values()) |
92 | | - if len(blob_response) != len(local_blobs_and_proofs): |
93 | | - raise ValueError( |
94 | | - f"Expected {len(local_blobs_and_proofs)} blobs and proofs, " |
95 | | - f"got {len(blob_response)}." |
96 | | - ) |
| 124 | + assert len(blob_response) == len(local_blobs_and_proofs), "Expected " |
| 125 | + f"{len(local_blobs_and_proofs)} blobs and proofs, got {len(blob_response)}." |
| 126 | + |
97 | 127 | for expected_blob, received_blob in zip( |
98 | | - local_blobs_and_proofs, blob_response.root, strict=False |
| 128 | + local_blobs_and_proofs, blob_response.root, strict=True |
99 | 129 | ): |
100 | 130 | if received_blob is None: |
101 | 131 | raise ValueError("Received blob is empty.") |
|
0 commit comments