|
6 | 6 | import contextlib |
7 | 7 | import functools |
8 | 8 | import logging |
9 | | -from typing import ( # noqa: F401 |
10 | | - List, |
| 9 | +from typing import ( |
11 | 10 | Type, |
12 | 11 | ) |
13 | 12 |
|
|
36 | 35 | from eth.exceptions import ( |
37 | 36 | HeaderNotFound, |
38 | 37 | ) |
39 | | -from eth.rlp.blocks import ( # noqa: F401 |
| 38 | +from eth.rlp.blocks import ( |
40 | 39 | BaseBlock, |
41 | 40 | ) |
42 | 41 | from eth.rlp.headers import ( |
43 | 42 | BlockHeader, |
44 | 43 | ) |
45 | | -from eth.rlp.receipts import Receipt # noqa: F401 |
| 44 | +from eth.rlp.receipts import Receipt |
| 45 | +from eth.rlp.sedes import ( |
| 46 | + int32, |
| 47 | +) |
46 | 48 | from eth.utils.datatypes import ( |
47 | 49 | Configurable, |
48 | 50 | ) |
@@ -189,7 +191,7 @@ def generate_block_from_parent_header_and_coinbase(cls, parent_header, coinbase) |
189 | 191 |
|
190 | 192 | @classmethod |
191 | 193 | @abstractmethod |
192 | | - def get_block_class(cls) -> Type['BaseBlock']: |
| 194 | + def get_block_class(cls) -> Type[BaseBlock]: |
193 | 195 | raise NotImplementedError("VM classes must implement this method") |
194 | 196 |
|
195 | 197 | @staticmethod |
@@ -251,6 +253,11 @@ def get_transaction_class(cls): |
251 | 253 | # |
252 | 254 | # Validate |
253 | 255 | # |
| 256 | + @classmethod |
| 257 | + @abstractmethod |
| 258 | + def validate_receipt(self, receipt: Receipt) -> None: |
| 259 | + raise NotImplementedError("VM classes must implement this method") |
| 260 | + |
254 | 261 | @abstractmethod |
255 | 262 | def validate_block(self, block): |
256 | 263 | raise NotImplementedError("VM classes must implement this method") |
@@ -348,6 +355,7 @@ def apply_transaction(self, header, transaction): |
348 | 355 | self.validate_transaction_against_header(header, transaction) |
349 | 356 | state_root, computation = self.state.apply_transaction(transaction) |
350 | 357 | receipt = self.make_receipt(header, transaction, computation, self.state) |
| 358 | + self.validate_receipt(receipt) |
351 | 359 |
|
352 | 360 | new_header = header.copy( |
353 | 361 | bloom=int(BloomFilter(header.bloom) | receipt.bloom), |
@@ -606,7 +614,7 @@ def generate_block_from_parent_header_and_coinbase(cls, parent_header, coinbase) |
606 | 614 | return block |
607 | 615 |
|
608 | 616 | @classmethod |
609 | | - def get_block_class(cls) -> Type['BaseBlock']: |
| 617 | + def get_block_class(cls) -> Type[BaseBlock]: |
610 | 618 | """ |
611 | 619 | Return the :class:`~eth.rlp.blocks.Block` class that this VM uses for blocks. |
612 | 620 | """ |
@@ -664,6 +672,22 @@ def get_transaction_class(cls): |
664 | 672 | # |
665 | 673 | # Validate |
666 | 674 | # |
| 675 | + @classmethod |
| 676 | + def validate_receipt(cls, receipt: Receipt) -> None: |
| 677 | + for log_idx, log in enumerate(receipt.logs): |
| 678 | + if log.address not in receipt.bloom_filter: |
| 679 | + raise ValidationError( |
| 680 | + "The address from the log entry at position {0} is not " |
| 681 | + "present in the provided bloom filter.".format(log_idx) |
| 682 | + ) |
| 683 | + for topic_idx, topic in enumerate(log.topics): |
| 684 | + if int32.serialize(topic) not in receipt.bloom_filter: |
| 685 | + raise ValidationError( |
| 686 | + "The topic at position {0} from the log entry at " |
| 687 | + "position {1} is not present in the provided bloom " |
| 688 | + "filter.".format(topic_idx, log_idx) |
| 689 | + ) |
| 690 | + |
667 | 691 | def validate_block(self, block): |
668 | 692 | """ |
669 | 693 | Validate the the given block. |
|
0 commit comments