core/state: fix codeLen=0 corruption of bintrie BasicData#34677
Open
CPerezz wants to merge 1 commit intoethereum:masterfrom
Open
core/state: fix codeLen=0 corruption of bintrie BasicData#34677CPerezz wants to merge 1 commit intoethereum:masterfrom
CPerezz wants to merge 1 commit intoethereum:masterfrom
Conversation
updateStateObject passed len(obj.code) as the codeLen argument to trie.UpdateAccount. obj.code is only populated when the contract code was modified in the current block — for plain balance or nonce updates the field is left empty and len(obj.code) is 0. For MPT, StateTrie.UpdateAccount ignores its codeLen parameter (the parameter is named `_ int`), so the zero was harmless. For the binary trie the code size is packed into the BasicData leaf blob at bytes 4-7: passing 0 overwrites the previously-stored code size with zero every time the account is touched, corrupting the state root silently whenever a contract's balance or nonce changes without a code write. Use obj.CodeSize() instead. It returns the cached code length if obj.code is loaded, otherwise falls back to a code-size lookup via the state reader, so it always reflects the account's current total code size. Regression test TestVerkleCodeSizePreserved verifies that the state root produced by "create contract, commit, reload, modify balance, commit" matches the root of a single-step construction of the same final state. Before the fix the two roots diverge: path A (reload + balance): 1a675599... path B (fresh, same state): de0cfb03...
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
updateStateObjectpassedlen(obj.code)as thecodeLenargument totrie.UpdateAccount.obj.codeis only populated when the contract code was modified in the current block — for plain balance or nonce updates the field is left empty andlen(obj.code)is 0.For MPT,
StateTrie.UpdateAccountignores itscodeLenparameter (the parameter is named_ int), so the zero was harmless. For the binary trie the code size is packed into the BasicData leaf blob at bytes 4-7: passing 0 overwrites the previously-stored code size with zero every time the account is touched, corrupting the state root silently whenever a contract's balance or nonce changes without a code write.This fix uses
obj.CodeSize()instead. It returns the cached code length ifobj.codeis loaded, otherwise falls back to a code-size lookup via the state reader, so it always reflects the account's current total code size.Test plan
TestVerkleCodeSizePreserved— regression test that verifies the state root produced by create contract → commit → reload → modify balance → commit matches the root of a single-step construction of the same final state. Before the fix, the two roots diverge:1a675599...de0cfb03...go test ./core/state/ -count=1— all existing tests passgo test ./trie/bintrie/ -count=1— all bintrie tests passImpact
StateTrie.UpdateAccountdiscardscodeLen.