-
Notifications
You must be signed in to change notification settings - Fork 20.5k
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
cmd, consensus, core, eth, tests: return memorized state error #26671
Conversation
6073161
to
a63b92c
Compare
I need to look a bit more to grokk everything, but one thing we need to be careful about is that
|
@@ -231,7 +233,6 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, | |||
|
|||
txIndex++ | |||
} | |||
statedb.IntermediateRoot(chainConfig.IsEIP158(vmContext.BlockNumber)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you drop this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because we will do a commit afterwards, https://github.com/ethereum/go-ethereum/pull/26671/files/a63b92c933e707f1f87b9040da3a32bae90a9061#diff-06c63748460168e12cbf03984f37c000908e0b7ff50ca0dfe28db286a1dfd36eR267
It's unnecessary to do it, unless for some strong reasons?
@@ -341,9 +341,6 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types. | |||
amount = amount.Mul(amount, big.NewInt(params.GWei)) | |||
state.AddBalance(w.Address, amount) | |||
} | |||
// The block reward is no longer handled here. It's done by the | |||
// external consensus engine. | |||
header.Root = state.IntermediateRoot(true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You removed the IntermediateRoot from Finalize
. Finalize
is called from FinaliseAndAssemble
, where you added a call to IntermediateRoot after the call to Finalize
.
Finalize
is however also called from state_processor.go:L95
, and there you have not added any corresponding call to intermediate root. How come?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In state_processor.go:L95
, all this function should do is:
- apply the transactions inside of the block on top on the provided stateDB
- apply the post-process ethereum rules, e.g. pow block rewards, uncle rules, withdrawals, etc
- return the generated receipts and logs
and that all.
header.Root = state.IntermediateRoot(true)
is just to derive the hash of the mutated stateDB
and assign it to header. In case of ``state_processor.go:L95`, the block is already generated
and retrieved from the network, we don't need to re-generate/assign the new hash to the header.
What's more, the header is just a copied from the block, it's noop.
In block insertion, the real hash comparison is happened in block validation,
// Validate the state root against the received state root and throw
// an error if they don't match.
root, err := statedb.IntermediateRoot(v.config.IsEIP158(header.Number))
if err != nil {
return fmt.Errorf("failed to derive state root %v", err)
}
if header.Root != root {
return fmt.Errorf("invalid merkle root (remote: %x local: %x)", header.Root, root)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In summary, the behavior is identical with old code, but just emphasize
- for block insertion,
Finalize
is only used to apply extra post-processing rules(e.g. block rewards, withdrawal, etc) but do nothing else. - for block generation,
FinalizeAndAssemble
is required to both doFinalize
work and also assemble a block locally, deriving the state hash from the stateDB and wrap it in a block.
Yep, very good question, and I will elaborate the rules of memorised error first so we can be quite What's the memorised error in stateDBStateDB is used by EVM to access ethereum state and cache mutations inside. However EVM is
Only these four types of errors will be memorised in stateDB. How memorised error will be usedmemorised error is only used when the stateDB needs to be rehashed, or when the stateDB mutations Specifically, memorised error is only checked in these functions:
State isolationThere are actually two types of stateDb we can classify:
|
Needs to fix CI failures |
Closing in favor of #26870 |
This PR bubble up the memorized database failure in stateDB and report it in critical places(e.g. block validation).