Skip to content

Commit

Permalink
Typing; Revert some of the changes from commit ba05e4e for now:
Browse files Browse the repository at this point in the history
- The state of transaction typing is quite messy. This will have to
  be addressed separately since this is a significant enough PR already.
  For now, de-DRY some of the changes made earlier and type: ignore some
  of the Cancun transaction fields until we fix the typing situation.
  • Loading branch information
fselmo committed Mar 12, 2024
1 parent 3a1753c commit 2941163
Show file tree
Hide file tree
Showing 25 changed files with 286 additions and 155 deletions.
3 changes: 1 addition & 2 deletions eth/_utils/transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
from eth.abc import (
SignedTransactionAPI,
UnsignedTransactionAPI,
UnsignedTypedTransactionAPI,
)
from eth.constants import (
CREATE_CONTRACT_ADDRESS,
Expand Down Expand Up @@ -118,7 +117,7 @@ class IntrinsicGasSchedule(NamedTuple):

def calculate_intrinsic_gas(
gas_schedule: IntrinsicGasSchedule,
transaction: Union[SignedTransactionAPI, UnsignedTypedTransactionAPI],
transaction: Union[SignedTransactionAPI, UnsignedTransactionAPI],
) -> int:
num_zero_bytes = transaction.data.count(b"\x00")
num_non_zero_bytes = len(transaction.data) - num_zero_bytes
Expand Down
37 changes: 20 additions & 17 deletions eth/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
abstractmethod,
)
from typing import (
TYPE_CHECKING,
Any,
Callable,
ClassVar,
Expand Down Expand Up @@ -53,6 +54,11 @@
VMConfiguration,
)

if TYPE_CHECKING:
from eth.vm.forks.cancun.transactions import (
BlobTransaction,
)

T = TypeVar("T")

# A decoded RLP object of unknown interpretation, with a maximum "depth" of 1.
Expand Down Expand Up @@ -480,6 +486,16 @@ def hash(self) -> Hash32:
def chain_id(self) -> Optional[int]:
...

@property
@abstractmethod
def max_fee_per_blob_gas(self) -> int:
...

@property
@abstractmethod
def blob_versioned_hashes(self) -> Sequence[Hash32]:
...


class LegacyTransactionFieldsAPI(TransactionFieldsAPI):
@property
Expand Down Expand Up @@ -510,28 +526,15 @@ class UnsignedTransactionAPI(BaseTransactionAPI):
# API that must be implemented by all Transaction subclasses.
#
@abstractmethod
def as_signed_transaction(self, private_key: PrivateKey) -> "SignedTransactionAPI":
def as_signed_transaction(
self, private_key: PrivateKey, chain_id: int = None
) -> "SignedTransactionAPI":
"""
Return a version of this transaction which has been signed using the
provided `private_key`
"""
...

# the chain_id must be defined similarly to `TransactionFieldsAPI` as @property
@property
def chain_id(self) -> Optional[int]:
return None


class UnsignedTypedTransactionAPI(UnsignedTransactionAPI, BaseTransactionAPI):
@abstractmethod
def get_message_for_signing(self) -> bytes:
"""
Return the bytestring that should be signed in order to create a signed
transaction.
"""
...


class TransactionDecoderAPI(ABC):
"""
Expand Down Expand Up @@ -2837,7 +2840,7 @@ def finalize_computation(
# -- post-cancun -- #

@abstractmethod
def calc_data_fee(self, transaction: TransactionFieldsAPI) -> int:
def calc_data_fee(self, transaction: "BlobTransaction") -> int:
"""
For Cancun and later, calculate the data fee for a transaction.
"""
Expand Down
8 changes: 3 additions & 5 deletions eth/consensus/clique/encoding.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,9 @@ def decode_vote(vote: bytes) -> Vote:
signer=signer,
block_number=block_number,
subject=subject,
action=(
VoteAction.NOMINATE
if action == VoteAction.NOMINATE.value
else VoteAction.KICK
),
action=VoteAction.NOMINATE
if action == VoteAction.NOMINATE.value
else VoteAction.KICK,
)


Expand Down
1 change: 0 additions & 1 deletion eth/consensus/ethash.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
This file was heavily inspired by and borrowed from the ethereum.org page on Ethash,
as well as the ``ethereum/execution-specs`` repository implementation of Ethash.
"""

from typing import (
Callable,
Dict,
Expand Down
8 changes: 3 additions & 5 deletions eth/tools/_utils/normalization.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,9 @@ def state_definition_to_dict(state_definition: GeneralState) -> AccountState:
state_dict = state_definition
elif isinstance(state_definition, Iterable):
state_dicts = [
(
assoc_in({}, state_item[:-1], state_item[-1])
if not isinstance(state_item, Mapping)
else state_item
)
assoc_in({}, state_item[:-1], state_item[-1])
if not isinstance(state_item, Mapping)
else state_item
for state_item in state_definition
]
if not is_cleanly_mergable(*state_dicts):
Expand Down
2 changes: 1 addition & 1 deletion eth/tools/factories/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def new_transaction(
data=data,
)
if private_key:
return tx.as_signed_transaction(private_key)
return tx.as_signed_transaction(private_key, chain_id=chain_id)
else:
return SpoofTransaction(tx, from_=from_)

Expand Down
6 changes: 2 additions & 4 deletions eth/vm/forks/arrow_glacier/transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,9 @@ class ArrowGlacierLegacyTransaction(LondonLegacyTransaction, ABC):

class ArrowGlacierUnsignedLegacyTransaction(LondonUnsignedLegacyTransaction):
def as_signed_transaction(
self, private_key: PrivateKey
self, private_key: PrivateKey, chain_id: int = None
) -> ArrowGlacierLegacyTransaction:
v, r, s = create_transaction_signature(
self, private_key, chain_id=self.chain_id
)
v, r, s = create_transaction_signature(self, private_key, chain_id=chain_id)
return ArrowGlacierLegacyTransaction(
nonce=self.nonce,
gas_price=self.gas_price,
Expand Down
62 changes: 36 additions & 26 deletions eth/vm/forks/berlin/transactions.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
from abc import (
ABC,
)
from typing import (
Any,
Dict,
Expand Down Expand Up @@ -52,7 +49,6 @@
TransactionBuilderAPI,
TransactionDecoderAPI,
UnsignedTransactionAPI,
UnsignedTypedTransactionAPI,
)
from eth.constants import (
CREATE_CONTRACT_ADDRESS,
Expand Down Expand Up @@ -103,10 +99,10 @@ class BerlinLegacyTransaction(MuirGlacierTransaction):


class BerlinUnsignedLegacyTransaction(MuirGlacierUnsignedTransaction):
def as_signed_transaction(self, private_key: PrivateKey) -> BerlinLegacyTransaction:
v, r, s = create_transaction_signature(
self, private_key, chain_id=self.chain_id
)
def as_signed_transaction(
self, private_key: PrivateKey, chain_id: int = None
) -> BerlinLegacyTransaction:
v, r, s = create_transaction_signature(self, private_key, chain_id=chain_id)
return BerlinLegacyTransaction(
nonce=self.nonce,
gas_price=self.gas_price,
Expand All @@ -127,8 +123,11 @@ class AccountAccesses(rlp.Serializable):
]


class UnsignedAccessListTransaction(rlp.Serializable, UnsignedTypedTransactionAPI, ABC):
class UnsignedAccessListTransaction(rlp.Serializable, UnsignedTransactionAPI):
_type_id = ACCESS_LIST_TRANSACTION_TYPE

chain_id: int

fields = [
("chain_id", big_endian_int),
("nonce", big_endian_int),
Expand All @@ -148,7 +147,9 @@ def get_message_for_signing(self) -> bytes:
payload = rlp.encode(self)
return self._type_byte + payload

def as_signed_transaction(self, private_key: PrivateKey) -> "TypedTransaction":
def as_signed_transaction(
self, private_key: PrivateKey, chain_id: int = None
) -> "TypedTransaction":
message = self.get_message_for_signing()
signature = private_key.sign_msg(message)
y_parity, r, s = signature.vrs
Expand Down Expand Up @@ -180,10 +181,10 @@ def validate(self) -> None:
validate_is_transaction_access_list(self.access_list)

def gas_used_by(self, computation: ComputationAPI) -> int:
return _get_txn_intrinsic_gas(self) + computation.get_gas_used()
return self.intrinsic_gas + computation.get_gas_used()

def get_intrinsic_gas(self) -> int:
return _get_txn_intrinsic_gas(self)
return _calculate_txn_intrinsic_gas_berlin(self)

@property
def intrinsic_gas(self) -> int:
Expand All @@ -200,7 +201,7 @@ def max_fee_per_gas(self) -> int:


class AccessListTransaction(
rlp.Serializable, SignedTransactionMethods, SignedTransactionAPI, ABC
rlp.Serializable, SignedTransactionMethods, SignedTransactionAPI
):
_type_id = ACCESS_LIST_TRANSACTION_TYPE
fields = [
Expand Down Expand Up @@ -246,7 +247,7 @@ def hash(self) -> Hash32:
raise NotImplementedError("Call hash() on the TypedTransaction instead")

def get_intrinsic_gas(self) -> int:
return _get_txn_intrinsic_gas(self)
return _calculate_txn_intrinsic_gas_berlin(self)

def encode(self) -> bytes:
return rlp.encode(self)
Expand Down Expand Up @@ -274,6 +275,18 @@ def max_priority_fee_per_gas(self) -> int:
def max_fee_per_gas(self) -> int:
return self.gas_price

@property
def max_fee_per_blob_gas(self) -> int:
raise NotImplementedError(
"max_fee_per_blob_gas is not implemented until Cancun."
)

@property
def blob_versioned_hashes(self) -> Hash32:
raise NotImplementedError(
"blob_versioned_hashes is not implemented until Cancun."
)


class AccessListPayloadDecoder(TransactionDecoderAPI):
@classmethod
Expand All @@ -292,14 +305,7 @@ class TypedTransaction(
}
receipt_builder = BerlinReceiptBuilder

def __init__(
self,
type_id: int,
proxy_target: SignedTransactionAPI,
*args: Any,
**kwargs: Any,
) -> None:
super().__init__(*args, **kwargs)
def __init__(self, type_id: int, proxy_target: SignedTransactionAPI) -> None:
self.type_id = type_id
self._inner = proxy_target

Expand Down Expand Up @@ -365,11 +371,15 @@ def max_fee_per_gas(self) -> int:

@property
def max_fee_per_blob_gas(self) -> int:
return self._inner.max_fee_per_blob_gas
raise NotImplementedError(
"max_fee_per_blob_gas is not implemented until Cancun."
)

@property
def blob_versioned_hashes(self) -> Hash32:
return self._inner.blob_versioned_hashes
raise NotImplementedError(
"blob_versioned_hashes is not implemented until Cancun."
)

@property
def gas(self) -> int:
Expand Down Expand Up @@ -565,8 +575,8 @@ def new_access_list_transaction(
return cls.typed_transaction(ACCESS_LIST_TRANSACTION_TYPE, transaction)


def _get_txn_intrinsic_gas(
klass: Union[UnsignedTypedTransactionAPI, SignedTransactionAPI]
def _calculate_txn_intrinsic_gas_berlin(
klass: Union[SignedTransactionAPI, UnsignedTransactionAPI]
) -> int:
core_gas = calculate_intrinsic_gas(ISTANBUL_TX_GAS_SCHEDULE, klass)

Expand Down
8 changes: 4 additions & 4 deletions eth/vm/forks/byzantium/transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ def create_unsigned_transaction(


class ByzantiumUnsignedTransaction(SpuriousDragonUnsignedTransaction):
def as_signed_transaction(self, private_key: PrivateKey) -> ByzantiumTransaction:
v, r, s = create_transaction_signature(
self, private_key, chain_id=self.chain_id
)
def as_signed_transaction(
self, private_key: PrivateKey, chain_id: int = None
) -> ByzantiumTransaction:
v, r, s = create_transaction_signature(self, private_key, chain_id=chain_id)
return ByzantiumTransaction(
nonce=self.nonce,
gas_price=self.gas_price,
Expand Down
9 changes: 4 additions & 5 deletions eth/vm/forks/cancun/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,10 @@ class CancunVM(ShanghaiVM):

@staticmethod
def _get_total_blob_gas(transaction: TransactionFieldsAPI) -> int:
return (
GAS_PER_BLOB * len(transaction.blob_versioned_hashes)
if hasattr(transaction, "blob_versioned_hashes")
else 0
)
try:
return GAS_PER_BLOB * len(transaction.blob_versioned_hashes) # type: ignore
except (AttributeError, NotImplementedError):
return 0

def increment_blob_gas_used(
self, old_header: BlockHeaderAPI, transaction: TransactionFieldsAPI
Expand Down
2 changes: 1 addition & 1 deletion eth/vm/forks/cancun/headers.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
)


def calc_excess_blob_gas(parent_header):
def calc_excess_blob_gas(parent_header: BlockHeaderAPI) -> int:
if (
parent_header.excess_blob_gas + parent_header.blob_gas_used
< TARGET_BLOB_GAS_PER_BLOCK
Expand Down

0 comments on commit 2941163

Please sign in to comment.