Skip to content
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

block: Set hardforkbyblocknumber true on rlp block constructor #2081

Merged
merged 3 commits into from
Jul 29, 2022

Conversation

acolytec3
Copy link
Contributor

We encountered a scenario where instantiating a block header using Blockheader.fromRLPSerializedHeader was producing incorrect block hashes for block RLPs pulled from mainnet prior to London if the blockOpt.hardforkByBlockNumber is not set to true because the default hardfork is now London and if no baseFee is provided in the header data and london is active, the blockheader constructor adds a default basefee field which causes the block hash to be calculated with the additional field included in the hash. Defaulting hardforkByBlockNumber to true in cases where it is not provided and we are using RLP serialized header data seems like a reasonable default setting to avoid strange scenarios where a user expects the constructor to produce the correct block but it has a basefee field attached that wasn't in the RLP data.

@codecov
Copy link

codecov bot commented Jul 29, 2022

Codecov Report

Merging #2081 (e7a22ac) into master (a5273af) will decrease coverage by 0.01%.
The diff coverage is 100.00%.

Impacted file tree graph

Flag Coverage Δ
block 83.81% <100.00%> (+0.06%) ⬆️
blockchain 80.10% <ø> (ø)
client 78.29% <ø> (ø)
common 95.00% <ø> (ø)
devp2p 82.54% <ø> (-0.13%) ⬇️
ethash 90.81% <ø> (ø)
evm 40.89% <ø> (ø)
statemanager 84.55% <ø> (ø)
trie 81.35% <ø> (ø)
tx 92.18% <ø> (ø)
util 87.22% <ø> (ø)
vm 78.54% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

g11tech
g11tech previously approved these changes Jul 29, 2022
Copy link
Contributor

@g11tech g11tech left a comment

Choose a reason for hiding this comment

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

LGTM

@acolytec3 acolytec3 changed the title Set hardforkbyblocknumber true on rlp block constructor block: Set hardforkbyblocknumber true on rlp block constructor Jul 29, 2022
Copy link
Contributor

@g11tech g11tech left a comment

Choose a reason for hiding this comment

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

LGTM

// is provided that predates London result in a default base fee being added to the block
// (resulting in an erroneous block hash since the default `common` hardfork is London and the blockheader constructor
// adds a default basefee if EIP-1559 is active and no basefee is provided in the `headerData`)
if (opts.hardforkByTTD === undefined) {
Copy link
Member

Choose a reason for hiding this comment

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

hardforkByTTD doesn't exist, this should be hardforkByTD.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

🤦 Ack. Will add it to the fixes list.

Copy link
Member

Choose a reason for hiding this comment

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

Wait, I have another comment... 😋

Copy link
Member

Choose a reason for hiding this comment

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

I will soon write a more general comment on this solution itself, but if we would take the solution here, wouldn't we need to also check that Common is not provided? otherwise we'll overwrite in many cases (which is likely not intended by the user)? 🤔

@holgerd77
Copy link
Member

holgerd77 commented Aug 2, 2022

I am generally not so sure if I like this solution so much, since this will often lead to false results in unknown chain scenarios where no common is provided (this leads on the side line also to the Common question I just posted), since this will always falsely assume mainnet block numbers, also for blocks from custom chains or unknown sources (and then mostly set to a wrong HF).

Would the following mechanims an alternative?

if (noCommonProvided && values.length === 15) { // old block format without base fee
  Initialize with a Common with a pre-London HF (likely: Berlin?)
}

On a first round I would think this has substantially less side effects.

@acolytec3
Copy link
Contributor Author

Hmm, that makes sense and I'd be open to that route. One other edge case to consider (my original issue) is that if we have an RLP serialized block in the pre-london format and someone passes in common with london or later hardfork set, should we throw or just let the user proceed? In this instance, the user is giving a completely packaged up RLP encoded block (which we assume they retrieved from some RPC endpoint or something similar rather than encoding by hand) so if there is incomplete data in the block (i.e. no basefee) and they've set the hardfork as london, should we throw or let the constructor provide the default base fee? I'm mainly thinking about the exact edge case I encountered in Ultralight where I wasn't thinking about setting the hardfork and assumed the fromRLPSerializedHeader constructor would handle all of that for me since I'm retrieving serialized blocks from the network and just trying to deserialize them and verify the hashes match for purposes of putting into the header accumulator.

@holgerd77
Copy link
Member

Ok, nice! 🙂

One other edge case to consider (my original issue) is that if we have an RLP serialized block in the pre-london format and someone passes in common with london or later hardfork set

I had a first thinking of generalize here and doing these kind of things in the main header constructor, but then draw back for various reasons (our current base fee default behavior e.g. which is also convenient I guess and also makes sense in various use case scenarios).

So, yes, I guess it makes sense to directly throw in these cases in the RLP static constructor, so both for:

  1. Pre-London Common, base fee provided
  2. Post-London Common, no base fee provided

Does this make sense and is an accurate task description?

@acolytec3
Copy link
Contributor Author

Yep!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants