-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
fix: empty app hash on first block's FinalizeBlock #18524
Conversation
WalkthroughThe update to the Changes
TipsChat with CodeRabbit Bot (
|
)) | ||
} | ||
|
||
// In the case of a new chain, AppHash will be the hash of an empty string. | ||
// During an upgrade, it'll be the hash of the last committed block. | ||
var appHash []byte | ||
if !app.LastCommitID().IsZero() { | ||
appHash = app.LastCommitID().Hash | ||
} else { | ||
// $ echo -n '' | sha256sum | ||
// e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 | ||
emptyHash := sha256.Sum256([]byte{}) | ||
appHash = emptyHash[:] | ||
} |
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.
Change potentially affects state.
Call sequence:
(*github.com/cosmos/cosmos-sdk/baseapp.BaseApp).internalFinalizeBlock (baseapp/abci.go:712)
(*github.com/cosmos/cosmos-sdk/baseapp.BaseApp).FinalizeBlock (baseapp/abci.go:869)
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.
Is this really correct? In the case of the first block of a new chain, the app hash, IIRC, is the genesis hash which is supplied during BeginBlock.
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.
This is what I observed, i.e. a nil
app hash. Also set up a BeginBlock
under x/wasm
of wasmd
and observed the same behavior. Regarding the contents of the hash, I followed suit with what InitChain
was doing, but not sure if this is the intended behavior.
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.
Review Status
Actionable comments generated: 0
Configuration used: CodeRabbit UI
Files selected for processing (1)
- baseapp/abci.go (2 hunks)
Additional comments: 2
baseapp/abci.go (2)
726-749: The code correctly handles the generation of
appHash
based on whether the last commit ID is zero or not. This is a crucial change that addresses the issue of an emptyAppHash
for the first block after genesis. The logic to use the hash of an empty string when there is no last commit is consistent with the behavior inInitChain
. This change should ensure that theAppHash
is not nil even when there is no last commit, which is the expected behavior for the first block.763-766: The
coreheader.Info
struct is being populated with theappHash
which is correctly computed in the previous lines. This ensures that theAppHash
is consistent and reflects the correct state of the application after theInitChain
or the last commit. This is a critical fix for the issue described in the pull request summary.
My understanding on why this happened: Until v0.47.x the BeginBlockRequest included the appHash (which was returned before by InitChain), so that would get put into the context. On v0.50.x we don't have the app hash in the FinalizeBlock request so we take it directly from the store, which can be nil and we don't do the "special treatment" we have in InitChain. |
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.
Changes LGTM, but I'd like to see a unit test testing both flows.
// In the case of a new chain, AppHash will be the hash of an empty string. | ||
// During an upgrade, it'll be the hash of the last committed block. |
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 the case of a new chain, AppHash will be the hash of an empty string. | |
// During an upgrade, it'll be the hash of the last committed block. | |
// In the case of a new chain, AppHash will be the hash of an empty string | |
// for the first block. During an upgrade, it'll be the hash of the last committed block. |
header := cmtproto.Header{ | ||
ChainID: app.chainID, | ||
Height: req.Height, | ||
Time: req.Time, | ||
ProposerAddress: req.ProposerAddress, | ||
NextValidatorsHash: req.NextValidatorsHash, | ||
AppHash: app.LastCommitID().Hash, |
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.
whynot set app.LastCommitID() to an empty value on start? this would help in avoiding the above code and potentially make it cleaner
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.
if we assume a nil apphash should never happen we should fix it at the source instead of here. This would be a fix in store v1.0.0.
Is a nil apphash a bad thing?
Nil app hash is not a thing, we return the hash of an empty byte slice, which is different. I believe the problem is it's not present on the 1st block during |
That makes sense. Maybe we should disallow nil apphashes in general? would be a simple fix in store that would avoid having to be defensive every where we call .Hash() |
did this pr to illustrate what i meant in my comment. #18563 Personally i like to root cause being fixed instead of at the source causing use to have to patch in many areas |
Description
The
FinalizeBlock
call for the first block after genesis contains a nilAppHash
asapp.LastCommitId().Hash
isnil
. This PR uses the same functionality asInitChain
ref to handle an empty app hash for the first height.Author Checklist
All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.
I have...
!
to the type prefix if API or client breaking changeCHANGELOG.md
make lint
andmake test
Reviewers Checklist
All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.
I have...
!
in the type prefix if API or client breaking changeSummary by CodeRabbit
appHash
is determined and utilized.