|
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