Co-authored-by: Facundo Medica <14063057+facundomedica@users.noreply.github.com>
This commit is contained in:
co-authored by
Facundo Medica
parent
9e2abf8ef4
commit
86ca92a5cf
+11
-6
@@ -548,7 +548,8 @@ func (app *BaseApp) ExtendVote(_ context.Context, req *abci.RequestExtendVote) (
|
||||
// Always reset state given that ExtendVote and VerifyVoteExtension can timeout
|
||||
// and be called again in a subsequent round.
|
||||
emptyHeader := cmtproto.Header{ChainID: app.chainID, Height: req.Height}
|
||||
app.setState(execModeVoteExtension, emptyHeader)
|
||||
ms := app.cms.CacheMultiStore()
|
||||
ctx := sdk.NewContext(ms, emptyHeader, false, app.logger).WithStreamingManager(app.streamingManager)
|
||||
|
||||
if app.extendVote == nil {
|
||||
return nil, errors.New("application ExtendVote handler not set")
|
||||
@@ -556,14 +557,14 @@ func (app *BaseApp) ExtendVote(_ context.Context, req *abci.RequestExtendVote) (
|
||||
|
||||
// If vote extensions are not enabled, as a safety precaution, we return an
|
||||
// error.
|
||||
cp := app.GetConsensusParams(app.voteExtensionState.ctx)
|
||||
cp := app.GetConsensusParams(ctx)
|
||||
|
||||
extsEnabled := cp.Abci != nil && req.Height >= cp.Abci.VoteExtensionsEnableHeight && cp.Abci.VoteExtensionsEnableHeight != 0
|
||||
if !extsEnabled {
|
||||
return nil, fmt.Errorf("vote extensions are not enabled; unexpected call to ExtendVote at height %d", req.Height)
|
||||
}
|
||||
|
||||
app.voteExtensionState.ctx = app.voteExtensionState.ctx.
|
||||
ctx = ctx.
|
||||
WithConsensusParams(cp).
|
||||
WithBlockGasMeter(storetypes.NewInfiniteGasMeter()).
|
||||
WithBlockHeight(req.Height).
|
||||
@@ -588,7 +589,7 @@ func (app *BaseApp) ExtendVote(_ context.Context, req *abci.RequestExtendVote) (
|
||||
}
|
||||
}()
|
||||
|
||||
resp, err = app.extendVote(app.voteExtensionState.ctx, req)
|
||||
resp, err = app.extendVote(ctx, req)
|
||||
if err != nil {
|
||||
app.logger.Error("failed to extend vote", "height", req.Height, "error", err)
|
||||
return &abci.ResponseExtendVote{VoteExtension: []byte{}}, nil
|
||||
@@ -608,9 +609,13 @@ func (app *BaseApp) VerifyVoteExtension(req *abci.RequestVerifyVoteExtension) (r
|
||||
return nil, errors.New("application VerifyVoteExtension handler not set")
|
||||
}
|
||||
|
||||
emptyHeader := cmtproto.Header{ChainID: app.chainID, Height: req.Height}
|
||||
ms := app.cms.CacheMultiStore()
|
||||
ctx := sdk.NewContext(ms, emptyHeader, false, app.logger).WithStreamingManager(app.streamingManager)
|
||||
|
||||
// If vote extensions are not enabled, as a safety precaution, we return an
|
||||
// error.
|
||||
cp := app.GetConsensusParams(app.voteExtensionState.ctx)
|
||||
cp := app.GetConsensusParams(ctx)
|
||||
|
||||
extsEnabled := cp.Abci != nil && req.Height >= cp.Abci.VoteExtensionsEnableHeight && cp.Abci.VoteExtensionsEnableHeight != 0
|
||||
if !extsEnabled {
|
||||
@@ -631,7 +636,7 @@ func (app *BaseApp) VerifyVoteExtension(req *abci.RequestVerifyVoteExtension) (r
|
||||
}
|
||||
}()
|
||||
|
||||
resp, err = app.verifyVoteExt(app.voteExtensionState.ctx, req)
|
||||
resp, err = app.verifyVoteExt(ctx, req)
|
||||
if err != nil {
|
||||
app.logger.Error("failed to verify vote extension", "height", req.Height, "error", err)
|
||||
return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, nil
|
||||
|
||||
@@ -364,6 +364,63 @@ func TestABCI_ExtendVote(t *testing.T) {
|
||||
require.Equal(t, abci.ResponseVerifyVoteExtension_REJECT, vres.Status)
|
||||
}
|
||||
|
||||
// TestABCI_OnlyVerifyVoteExtension makes sure we can call VerifyVoteExtension
|
||||
// without having called ExtendVote before.
|
||||
func TestABCI_OnlyVerifyVoteExtension(t *testing.T) {
|
||||
name := t.Name()
|
||||
db := dbm.NewMemDB()
|
||||
app := baseapp.NewBaseApp(name, log.NewTestLogger(t), db, nil)
|
||||
|
||||
app.SetVerifyVoteExtensionHandler(func(ctx sdk.Context, req *abci.RequestVerifyVoteExtension) (*abci.ResponseVerifyVoteExtension, error) {
|
||||
// do some kind of verification here
|
||||
expectedVoteExt := "foo" + hex.EncodeToString(req.Hash) + strconv.FormatInt(req.Height, 10)
|
||||
if !bytes.Equal(req.VoteExtension, []byte(expectedVoteExt)) {
|
||||
return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, nil
|
||||
}
|
||||
|
||||
return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_ACCEPT}, nil
|
||||
})
|
||||
|
||||
app.SetParamStore(¶mStore{db: dbm.NewMemDB()})
|
||||
_, err := app.InitChain(
|
||||
&abci.RequestInitChain{
|
||||
InitialHeight: 1,
|
||||
ConsensusParams: &cmtproto.ConsensusParams{
|
||||
Abci: &cmtproto.ABCIParams{
|
||||
VoteExtensionsEnableHeight: 200,
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify Vote Extensions
|
||||
_, err = app.VerifyVoteExtension(&abci.RequestVerifyVoteExtension{Height: 123, VoteExtension: []byte("1234567")})
|
||||
require.ErrorContains(t, err, "vote extensions are not enabled")
|
||||
|
||||
// First vote on the first enabled height
|
||||
vres, err := app.VerifyVoteExtension(&abci.RequestVerifyVoteExtension{Height: 200, Hash: []byte("thehash"), VoteExtension: []byte("foo74686568617368200")})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, abci.ResponseVerifyVoteExtension_ACCEPT, vres.Status)
|
||||
|
||||
vres, err = app.VerifyVoteExtension(&abci.RequestVerifyVoteExtension{Height: 1000, Hash: []byte("thehash"), VoteExtension: []byte("foo746865686173681000")})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, abci.ResponseVerifyVoteExtension_ACCEPT, vres.Status)
|
||||
|
||||
// Reject because it's just some random bytes
|
||||
vres, err = app.VerifyVoteExtension(&abci.RequestVerifyVoteExtension{Height: 201, Hash: []byte("thehash"), VoteExtension: []byte("12345678")})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, abci.ResponseVerifyVoteExtension_REJECT, vres.Status)
|
||||
|
||||
// Reject because the verification failed (no error)
|
||||
app.SetVerifyVoteExtensionHandler(func(ctx sdk.Context, req *abci.RequestVerifyVoteExtension) (*abci.ResponseVerifyVoteExtension, error) {
|
||||
return nil, errors.New("some error")
|
||||
})
|
||||
vres, err = app.VerifyVoteExtension(&abci.RequestVerifyVoteExtension{Height: 201, Hash: []byte("thehash"), VoteExtension: []byte("12345678")})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, abci.ResponseVerifyVoteExtension_REJECT, vres.Status)
|
||||
}
|
||||
|
||||
func TestABCI_GRPCQuery(t *testing.T) {
|
||||
grpcQueryOpt := func(bapp *baseapp.BaseApp) {
|
||||
testdata.RegisterQueryServer(
|
||||
|
||||
@@ -104,11 +104,6 @@ type BaseApp struct {
|
||||
// previous block's state. This state is never committed. In case of multiple
|
||||
// consensus rounds, the state is always reset to the previous block's state.
|
||||
//
|
||||
// - voteExtensionState: Used for ExtendVote and VerifyVoteExtension, which is
|
||||
// set based on the previous block's state. This state is never committed. In
|
||||
// case of multiple rounds, the state is always reset to the previous block's
|
||||
// state.
|
||||
//
|
||||
// - processProposalState: Used for ProcessProposal, which is set based on the
|
||||
// the previous block's state. This state is never committed. In case of
|
||||
// multiple rounds, the state is always reset to the previous block's state.
|
||||
@@ -118,7 +113,6 @@ type BaseApp struct {
|
||||
checkState *state
|
||||
prepareProposalState *state
|
||||
processProposalState *state
|
||||
voteExtensionState *state
|
||||
finalizeBlockState *state
|
||||
|
||||
// An inter-block write-through cache provided to the context during the ABCI
|
||||
@@ -475,9 +469,6 @@ func (app *BaseApp) setState(mode execMode, header cmtproto.Header) {
|
||||
case execModeProcessProposal:
|
||||
app.processProposalState = baseState
|
||||
|
||||
case execModeVoteExtension:
|
||||
app.voteExtensionState = baseState
|
||||
|
||||
case execModeFinalize:
|
||||
app.finalizeBlockState = baseState
|
||||
|
||||
|
||||
Reference in New Issue
Block a user