-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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: use deliverState in prepare and processProposal at height 1 #14505
Conversation
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.
PHENomenal. Great job. Thanks 👏
The more folks that understand ABCI++ the better 🙌
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.
Nice!!
baseapp/abci.go
Outdated
} | ||
|
||
ctx := app.prepareProposalState.ctx | ||
// Here we use deliverState on the first block given that we want to be able |
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.
Curious - why is the state with changes that InitChain made not available to the app?
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.
wdym "not available to the app"?
After InitChain
, changes are not committed. They're technically staged/cached on the (cached) root multi-store. This isn't what prepareProposal
state is based off of until Commit
is called.
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.
InitChain initializes and applies changes (params, genesis and such) to deliverState
, which is not persisted until Commit(): see here.
In Commit()
deliverState
is set to nil while the other states are set to the latest header (that's why we were seeing the previous block height in PrepareProposal
before adding WithBlockHeight(req.Height)
in this PR).
So PrepareProposal
and ProcessProposal
will always be seeing persisted state (from the previous produced block), except for the first block that we feed it with the genesis state. Also it's good to note that we shouldn't be making any persistable state changes during these stages.
Also BeginBlock
is the one in charge of setting deliverState; except when we are at the first block: in that case we just want to update the context retaining any state changes made in InitChain
. see here
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.
I see, thanks for the explanation. That makes sense.
Random alternative thoughts:
- Would it be better to dedicate height == 1 to
InitChain
only? meaning that the at height 1, CosmosSDK just runsInitChain
and then callsCommit
. No special logic to override the ctx state to be thedeliverState
which has not been committed. My main reasoning around this is if there would be any weird behavior for thePrepareProposal
to be based off of state that has not been committed to state. - Similarly, is it possible to introduce some special height 0 that does the
InitChain
andCommit
only
[Cosmos SDK] Kudos, SonarCloud Quality Gate passed! |
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.
lgtm! thank you for the fix and the explanations 👍
left some random alternative thoughts out of curiosity
@facundomedica lets resolve the merge conflict and get this merged 🙌 |
) (cherry picked from commit 3fc4f33) # Conflicts: # CHANGELOG.md
Description
Ref: #14446
Audit: #13951
Issue: State couldn't be queried on PrepareProposal and ProcessProposal on the first block, so you couldn't get params or get stuff changed during the InitChain (mainly genesis).
We now use a cached context from
deliverState
during the first block. This allows us to query any state changed duringInitChain
(which is done ondeliverState
).After the first block we use
prepareProposalState
orprocessProposalState
, asdeliverState
is not initialized and there's no state being changed prior toPrepareProposal
(in the ABCI flow there's no step prior after the first block is produced).A check for invalid height was added to
PrepareProposal
as it's invalid to pass anything < 1. I don't see this happening in real life but there were some invalid tests.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
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 change