Skip to content

[WIP] add support for EIP-1559 #2005

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 10 commits into from
Closed

Conversation

ftruzzi
Copy link
Contributor

@ftruzzi ftruzzi commented May 3, 2021

Hi!

I tried to add new block headers and transactions, and a bit of header validation. Please take a look at those -- do they make sense? Should those changes to blocks/transactions be applied somewhere else? Should I keep going?

Thanks :)

@pipermerriam
Copy link
Member

I think yes, you can keep going. I only gave this a shallow review but the direction and structure looks good. I didn't dig into the actual method implementations yet.

My main recommendation would be to extract the "stub" for London from this PR to reduce the size of the diff. See #1969 for how this was done for Berlin.

@@ -74,6 +74,8 @@ class MiningHeaderAPI(ABC):
gas_used: int
timestamp: int
extra_data: bytes
gas_target: int # EIP-1559
base_fee_per_gas: int # EIP-1559
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels... unfortunate, but it might be necessary. Ideally, it would be nice if these fields didn't leak into all the previous VM APIs.... but doing so might introduce even more unfortunate complexity into our type definitions which might be worse...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree and will take a deeper look -- for now I can say a similar problem applies to transactions. Base transaction.validate methods all type-check gas_price which is no longer a thing in London transactions so they need to be duplicated almost entirely. We could keep gas_price as an (internal, not exposed) alias for either max_fee_per_gas or max_priority_fee_per_gas so that we could extend and call basic validation methods via super(), but it sounds confusing :(

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After dealing with typed transactions, my general take on it was: the latest VM should have the cleanest implementation. If a kludge is called for, it should be on the old VMs (like v vs y-parity in the signature, where we started to prefer y-parity as the default/native field). At first glance, this change seems to follow that approach, so I'm 👌🏻 to keep it. I'll comment if I stumble on a better option while reading the rest.


def normalize_transaction(
transaction: SignedTransactionAPI
) -> SignedTransactionAPI:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function modifies the transaction object rather than creating an instance of a possible new LondonTypedTransaction class so that both new (London-specific) and existing validation code can work on all transactions. However this means that max_priority_fee_per_gas and max_fee_per_gas cannot be read-only properties, and I'm wondering how should we handle users trying to access the new properties in pre-London transactions?

return rlp.decode(header_rlp, sedes=BlockHeader)
except ObjectDeserializationError:
# could be a new >=London block header
return rlp.decode(header_rlp, sedes=LondonBlockHeader)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this look good, or should we find some way to check the header type first?

@property
def gas_price(self) -> None:
# maybe add a warning, or raise an exception instead?
return None
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How should we handle this? gas_price is no longer a transaction attribute. It could still be interpreted as "effective gas price", but that requires knowing the base gas fee of the block so it would not a be "transaction-only" attribute anymore

@ftruzzi
Copy link
Contributor Author

ftruzzi commented May 20, 2021

@pipermerriam would you take another look? Sorry it took me a while. Two main things I'd like to get some feedback on:

  • New transaction and block attributes: do they look good? How should we handle London-only attributes in the API? Users might be trying to access them in legacy transactions/VMs and vice-versa.
  • The way transaction execution works is by passing the effective gas price to the transaction context creator, and by adding the base gas fee to the execution context. After some trial and error it was the best way I found to keep as much existing code as possible, but I'm wondering if you have any other ideas.

Things that still have to be done are here + linting and style -- please let me know if this is too large/hard to read and you'd like me to better separate commits before taking a look. Thanks

@ftruzzi ftruzzi requested a review from pipermerriam May 24, 2021 12:57
Copy link
Contributor

@carver carver left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm just getting started looking around, will pick it up again tomorrow.

@@ -74,6 +74,8 @@ class MiningHeaderAPI(ABC):
gas_used: int
timestamp: int
extra_data: bytes
gas_target: int # EIP-1559
base_fee_per_gas: int # EIP-1559
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After dealing with typed transactions, my general take on it was: the latest VM should have the cleanest implementation. If a kludge is called for, it should be on the old VMs (like v vs y-parity in the signature, where we started to prefer y-parity as the default/native field). At first glance, this change seems to follow that approach, so I'm 👌🏻 to keep it. I'll comment if I stumble on a better option while reading the rest.

@abstractmethod
def get_transaction_context_class(cls) -> Type[TransactionContextAPI]:
def get_transaction_context_class(self) -> Type[TransactionContextAPI]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this one could stay a classmethod

Comment on lines +178 to +187
if isinstance(transaction, LondonTypedTransaction): # TODO probably do this somewhere else
priority_fee_per_gas = min(
transaction.max_priority_fee_per_gas,
transaction.max_fee_per_gas - self.execution_context.base_gas_fee
)
else:
priority_fee_per_gas = min(
transaction.gas_price,
transaction.gas_price - self.execution_context.base_gas_fee
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, my instinct is to put this in the transaction class, just have everything implement a priority_fee_per_gas attribute. Then we get to skip the instance check.

@abstractmethod
def get_transaction_context(cls,
def get_transaction_context(self,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, bummer that this can't be a class method anymore. I can maybe imagine doing something where the transaction context no longer gives access to the active gas price without explicit access to the execution-context (like as a parameter to a new get_gas_price(execution_context) method). Or something along those lines. I am okay with this solution though. 👍🏻

@carver
Copy link
Contributor

carver commented Aug 19, 2021

Thanks for getting this started! The commits from this PR are integrated to #2013

@carver carver closed this Aug 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants