-
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: remove previous header in Prepare/Process Proposal + provide chain id in baseapp + fix context for verifying txs #15303
Changes from all commits
5600add
a07fd6f
fbe491f
ac12759
233a4a4
fe1cd5b
257f4be
06d2021
4a79357
71d93ca
755611d
be89d62
bf4c3f2
d7e7bd8
09ae43a
a578ddb
630175a
950cd21
966dba8
820e34e
b17f178
adfac48
3f23381
3bcaa15
bc1b4c1
f5e883e
52a64aa
6b8b529
02b6ad1
143af44
f307b3b
89b90da
ed69776
814fc92
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,10 @@ const ( | |
// InitChain implements the ABCI interface. It runs the initialization logic | ||
// directly on the CommitMultiStore. | ||
func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitChain) { | ||
if req.ChainId != app.chainID { | ||
panic(fmt.Sprintf("invalid chain-id on InitChain; expected: %s, got: %s", app.chainID, req.ChainId)) | ||
} | ||
|
||
// On a new chain, we consider the init chain block height as 0, even though | ||
// req.InitialHeight is 1 by default. | ||
initHeader := cmtproto.Header{ChainID: req.ChainId, Time: req.Time} | ||
|
@@ -57,8 +61,14 @@ func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitC | |
// initialize states with a correct header | ||
app.setState(runTxModeDeliver, initHeader) | ||
app.setState(runTxModeCheck, initHeader) | ||
app.setState(runTxPrepareProposal, initHeader) | ||
app.setState(runTxProcessProposal, initHeader) | ||
|
||
// Use an empty header for prepare and process proposal states. The header | ||
// will be overwritten for the first block (see getContextForProposal()) and | ||
// cleaned up on every Commit(). Only the ChainID is needed so it's set in | ||
// the context. | ||
emptyHeader := cmtproto.Header{ChainID: req.ChainId} | ||
app.setState(runTxPrepareProposal, emptyHeader) | ||
app.setState(runTxProcessProposal, emptyHeader) | ||
|
||
// Store the consensus params in the BaseApp's paramstore. Note, this must be | ||
// done after the deliver state and context have been set as it's persisted | ||
|
@@ -154,6 +164,10 @@ func (app *BaseApp) FilterPeerByID(info string) abci.ResponseQuery { | |
|
||
// BeginBlock implements the ABCI application interface. | ||
func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeginBlock) { | ||
if req.Header.ChainID != app.chainID { | ||
panic(fmt.Sprintf("invalid chain-id on BeginBlock; expected: %s, got: %s", app.chainID, req.Header.ChainID)) | ||
Check warning Code scanning / CodeQL Panic in BeginBock or EndBlock consensus methods
path flow from Begin/EndBlock to a panic call
|
||
} | ||
|
||
if app.cms.TracingEnabled() { | ||
app.cms.SetTracingContext(storetypes.TraceContext( | ||
map[string]interface{}{"blockHeight": req.Header.Height}, | ||
|
@@ -264,15 +278,15 @@ func (app *BaseApp) PrepareProposal(req abci.RequestPrepareProposal) (resp abci. | |
panic("PrepareProposal called with invalid height") | ||
} | ||
|
||
gasMeter := app.getBlockGasMeter(app.prepareProposalState.ctx) | ||
ctx := app.getContextForProposal(app.prepareProposalState.ctx, req.Height) | ||
|
||
ctx = ctx.WithVoteInfos(app.voteInfos). | ||
app.prepareProposalState.ctx = app.getContextForProposal(app.prepareProposalState.ctx, req.Height). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So now we set There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, so the issue here is that we were passing |
||
WithVoteInfos(app.voteInfos). | ||
WithBlockHeight(req.Height). | ||
WithBlockTime(req.Time). | ||
WithProposer(req.ProposerAddress). | ||
WithConsensusParams(app.GetConsensusParams(ctx)). | ||
WithBlockGasMeter(gasMeter) | ||
WithProposer(req.ProposerAddress) | ||
|
||
app.prepareProposalState.ctx = app.prepareProposalState.ctx. | ||
WithConsensusParams(app.GetConsensusParams(app.prepareProposalState.ctx)). | ||
WithBlockGasMeter(app.getBlockGasMeter(app.prepareProposalState.ctx)) | ||
|
||
defer func() { | ||
if err := recover(); err != nil { | ||
|
@@ -287,7 +301,7 @@ func (app *BaseApp) PrepareProposal(req abci.RequestPrepareProposal) (resp abci. | |
} | ||
}() | ||
|
||
resp = app.prepareProposal(ctx, req) | ||
resp = app.prepareProposal(app.prepareProposalState.ctx, req) | ||
return resp | ||
} | ||
|
||
|
@@ -311,17 +325,16 @@ func (app *BaseApp) ProcessProposal(req abci.RequestProcessProposal) (resp abci. | |
panic("app.ProcessProposal is not set") | ||
} | ||
|
||
gasMeter := app.getBlockGasMeter(app.processProposalState.ctx) | ||
ctx := app.getContextForProposal(app.processProposalState.ctx, req.Height) | ||
|
||
ctx = ctx. | ||
app.processProposalState.ctx = app.getContextForProposal(app.processProposalState.ctx, req.Height). | ||
WithVoteInfos(app.voteInfos). | ||
WithBlockHeight(req.Height). | ||
WithBlockTime(req.Time). | ||
WithHeaderHash(req.Hash). | ||
WithProposer(req.ProposerAddress). | ||
WithConsensusParams(app.GetConsensusParams(ctx)). | ||
WithBlockGasMeter(gasMeter) | ||
WithProposer(req.ProposerAddress) | ||
|
||
app.processProposalState.ctx = app.processProposalState.ctx. | ||
WithConsensusParams(app.GetConsensusParams(app.processProposalState.ctx)). | ||
WithBlockGasMeter(app.getBlockGasMeter(app.processProposalState.ctx)) | ||
|
||
defer func() { | ||
if err := recover(); err != nil { | ||
|
@@ -336,7 +349,7 @@ func (app *BaseApp) ProcessProposal(req abci.RequestProcessProposal) (resp abci. | |
} | ||
}() | ||
|
||
resp = app.processProposal(ctx, req) | ||
resp = app.processProposal(app.processProposalState.ctx, req) | ||
return resp | ||
} | ||
|
||
|
@@ -450,8 +463,12 @@ func (app *BaseApp) Commit() abci.ResponseCommit { | |
// NOTE: This is safe because CometBFT holds a lock on the mempool for | ||
// Commit. Use the header from this latest block. | ||
app.setState(runTxModeCheck, header) | ||
app.setState(runTxPrepareProposal, header) | ||
app.setState(runTxProcessProposal, header) | ||
|
||
// Reset state to the latest committed but with an empty header to avoid | ||
// leaking the header from the last block. | ||
emptyHeader := cmtproto.Header{ChainID: app.chainID} | ||
app.setState(runTxPrepareProposal, emptyHeader) | ||
app.setState(runTxProcessProposal, emptyHeader) | ||
|
||
// empty/reset the deliver state | ||
app.deliverState = nil | ||
|
@@ -969,6 +986,8 @@ func SplitABCIQueryPath(requestPath string) (path []string) { | |
func (app *BaseApp) getContextForProposal(ctx sdk.Context, height int64) sdk.Context { | ||
if height == 1 { | ||
ctx, _ = app.deliverState.ctx.CacheContext() | ||
// clear all context data set during InitChain to avoid inconsistent behavior | ||
ctx = ctx.WithBlockHeader(cmtproto.Header{}) | ||
return ctx | ||
} | ||
return ctx | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,7 @@ import ( | |
sdk "github.com/cosmos/cosmos-sdk/types" | ||
"github.com/cosmos/cosmos-sdk/types/mempool" | ||
"github.com/cosmos/cosmos-sdk/version" | ||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" | ||
) | ||
|
||
// ServerContextKey defines the context key used to retrieve a server.Context from | ||
|
@@ -455,7 +456,19 @@ func DefaultBaseappOptions(appOpts types.AppOptions) []func(*baseapp.BaseApp) { | |
panic(err) | ||
} | ||
|
||
snapshotDir := filepath.Join(cast.ToString(appOpts.Get(flags.FlagHome)), "data", "snapshots") | ||
homeDir := cast.ToString(appOpts.Get(flags.FlagHome)) | ||
chainID := cast.ToString(appOpts.Get(flags.FlagChainID)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. genesis does not always have the correct genesis, in most cases the file is incorrect |
||
if chainID == "" { | ||
// fallback to genesis chain-id | ||
appGenesis, err := genutiltypes.AppGenesisFromFile(filepath.Join(homeDir, "config", "genesis.json")) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
chainID = appGenesis.ChainID | ||
} | ||
|
||
snapshotDir := filepath.Join(homeDir, "data", "snapshots") | ||
if err = os.MkdirAll(snapshotDir, os.ModePerm); err != nil { | ||
panic(fmt.Errorf("failed to create snapshots directory: %w", err)) | ||
} | ||
|
@@ -492,5 +505,6 @@ func DefaultBaseappOptions(appOpts types.AppOptions) []func(*baseapp.BaseApp) { | |
), | ||
), | ||
baseapp.SetIAVLLazyLoading(cast.ToBool(appOpts.Get(FlagIAVLLazyLoading))), | ||
baseapp.SetChainID(chainID), | ||
} | ||
} |
Check warning
Code scanning / CodeQL
Panic in BeginBock or EndBlock consensus methods