From d7f9160188d764c10e897417c9f9c6b2abfa751b Mon Sep 17 00:00:00 2001 From: Jongwon Park Date: Tue, 10 Dec 2024 16:52:46 +0900 Subject: [PATCH] fix(evmengine): get next proposer via comet algo (#409) use comet's exposed validators functions to check if the local node is the next (predicted) proposer issue: closes #388 --- .golangci.yml | 8 ++ client/app/start.go | 2 +- client/comet/comet.go | 109 +++------------ client/x/evmengine/keeper/abci.go | 4 +- .../x/evmengine/keeper/abci_internal_test.go | 50 +++++-- client/x/evmengine/keeper/keeper.go | 19 +-- .../evmengine/keeper/keeper_internal_test.go | 128 +++++++----------- .../keeper/msg_server_internal_test.go | 2 +- .../keeper/upgrades_internal_test.go | 2 +- client/x/mint/keeper/genesis_test.go | 1 - client/x/mint/keeper/grpc_query_test.go | 1 - client/x/mint/keeper/keeper_test.go | 1 - lib/expbackoff/expbackoff_test.go | 1 - 13 files changed, 122 insertions(+), 206 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index ef08cb01..c8ad4656 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -35,6 +35,14 @@ linters-settings: nolintlint: require-explanation: true require-specific: true + paralleltest: + # Ignore missing calls to `t.Parallel()` and only report incorrect uses of it. + # Default: false + ignore-missing: true + # Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are + # still required to have `t.Parallel`, but subtests are allowed to skip it. + # Default: false + ignore-missing-subtests: true revive: enable-all-rules: true severity: warning diff --git a/client/app/start.go b/client/app/start.go index 0b99ded4..6460758f 100644 --- a/client/app/start.go +++ b/client/app/start.go @@ -136,7 +136,7 @@ func Start(ctx context.Context, cfg Config) (func(context.Context) error, error) } rpcClient := rpclocal.New(cmtNode) - cmtAPI := comet.NewAPI(rpcClient) + cmtAPI := comet.NewAPI(rpcClient, app.ChainID()) app.SetCometAPI(cmtAPI) log.Info(ctx, "Starting CometBFT", "listeners", cmtNode.Listeners()) diff --git a/client/comet/comet.go b/client/comet/comet.go index c6573af0..376669e3 100644 --- a/client/comet/comet.go +++ b/client/comet/comet.go @@ -3,118 +3,53 @@ package comet import ( "context" + lightprovider "github.com/cometbft/cometbft/light/provider" + lighthttp "github.com/cometbft/cometbft/light/provider/http" rpcclient "github.com/cometbft/cometbft/rpc/client" cmttypes "github.com/cometbft/cometbft/types" - "github.com/ethereum/go-ethereum/common" "github.com/piplabs/story/lib/errors" - "github.com/piplabs/story/lib/k1util" "github.com/piplabs/story/lib/tracer" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) -const perPageConst = 100 - var _ API = adapter{} type API interface { - // Validators returns the cometBFT validators at the given height or false if not - // available (probably due to snapshot sync after height). - Validators(ctx context.Context, height int64) (*cmttypes.ValidatorSet, bool, error) - - // IsValidator returns true if the given address is a validator at the latest height. - // It is best-effort, so returns false on any error. - IsValidator(ctx context.Context, valAddress common.Address) bool + // Validators returns the cometBFT validators at the given height. + Validators(ctx context.Context, height int64) (*cmttypes.ValidatorSet, error) } -func NewAPI(cl rpcclient.Client) API { - return adapter{cl: cl} +func NewAPI(cl rpcclient.Client, chainID string) API { + return adapter{ + cl: lighthttp.NewWithClient(chainID, remoteCl{cl}), + } } type adapter struct { - cl rpcclient.Client -} - -// IsValidator returns true if the given address is a validator at the latest height. -// It is best-effort, so returns false on any error. -func (a adapter) IsValidator(ctx context.Context, valAddress common.Address) bool { - ctx, span := tracer.Start(ctx, "comet/is_validator") - defer span.End() - - status, err := a.cl.Status(ctx) - if err != nil || status.SyncInfo.CatchingUp { - return false // Best effort - } - - valset, ok, err := a.Validators(ctx, status.SyncInfo.LatestBlockHeight) - if !ok || err != nil { - return false // Best effort - } - - for _, val := range valset.Validators { - addr, err := k1util.PubKeyToAddress(val.PubKey) - if err != nil { - continue // Best effort - } - - if addr == valAddress { - return true - } - } - - return false + cl lightprovider.Provider } -// Validators returns the cometBFT validators at the given height or false if not -// available (probably due to snapshot sync after height). -func (a adapter) Validators(ctx context.Context, height int64) (*cmttypes.ValidatorSet, bool, error) { +// Validators returns the cometBFT validators at the given height. +func (a adapter) Validators(ctx context.Context, height int64) (*cmttypes.ValidatorSet, error) { ctx, span := tracer.Start(ctx, "comet/validators", trace.WithAttributes(attribute.Int64("height", height))) defer span.End() - perPage := perPageConst // Can't take a pointer to a const directly. - - var vals []*cmttypes.Validator - for page := 1; ; page++ { // Pages are 1-indexed. - if page > 10 { // Sanity check. - return nil, false, errors.New("too many validators [BUG]") - } - - status, err := a.cl.Status(ctx) - if err != nil { - return nil, false, errors.Wrap(err, "fetch status") - } else if height < status.SyncInfo.EarliestBlockHeight { - // This can happen if height is before snapshot restore. - return nil, false, nil - } - - valResp, err := a.cl.Validators(ctx, &height, &page, &perPage) - if err != nil { - return nil, false, errors.Wrap(err, "fetch validators") - } - - for _, v := range valResp.Validators { - vals = append(vals, cmttypes.NewValidator(v.PubKey, v.VotingPower)) - } - - if len(vals) == valResp.Total { - break - } + block, err := a.cl.LightBlock(ctx, height) // LightBlock does all the heavy lifting to query the validator set. + if err != nil { + return nil, errors.Wrap(err, "fetch light block") } - // cmttypes.NewValidatorSet() panics on error, so manually construct it for proper error handling. - valset := new(cmttypes.ValidatorSet) - if err := valset.UpdateWithChangeSet(vals); err != nil { - return nil, false, errors.Wrap(err, "update with change set") - } - if len(vals) > 0 { - valset.IncrementProposerPriority(1) // See cmttypes.NewValidatorSet - } + return block.ValidatorSet, nil +} - if err := valset.ValidateBasic(); err != nil { - return nil, false, errors.Wrap(err, "validate basic") - } +// remoteCl is a wrapper around rpcclient.Client to implement rpcclient.RemoteClient. +type remoteCl struct { + rpcclient.Client +} - return valset, true, nil +func (remoteCl) Remote() string { + return "" } diff --git a/client/x/evmengine/keeper/abci.go b/client/x/evmengine/keeper/abci.go index ef1f39e6..a87f7551 100644 --- a/client/x/evmengine/keeper/abci.go +++ b/client/x/evmengine/keeper/abci.go @@ -93,6 +93,7 @@ func (k *Keeper) PrepareProposal(ctx sdk.Context, req *abci.RequestPreparePropos return nil, err } triggeredAt = time.Now() + log.Debug(ctx, "Started non-optimistic payload", "height", req.Height, "payload", payloadID.String()) } else { log.Info(ctx, "Using optimistic payload", "height", height, "payload", payloadID.String()) } @@ -183,12 +184,11 @@ func (k *Keeper) PostFinalize(ctx sdk.Context) error { // Extract context values height := ctx.BlockHeight() - proposer := ctx.BlockHeader().ProposerAddress timestamp := ctx.BlockTime() appHash := common.BytesToHash(ctx.BlockHeader().AppHash) // This is the app hash after the block is finalized. // Maybe start building the next block if we are the next proposer. - isNext, err := k.isNextProposer(ctx, proposer, height) + isNext, err := k.isNextProposer(ctx, height) if err != nil { // IsNextProposer does non-deterministic cometBFT queries, don't stall node due to errors. log.Warn(ctx, "Next proposer failed, skipping optimistic EVM payload build", err) diff --git a/client/x/evmengine/keeper/abci_internal_test.go b/client/x/evmengine/keeper/abci_internal_test.go index 50634ade..26848aba 100644 --- a/client/x/evmengine/keeper/abci_internal_test.go +++ b/client/x/evmengine/keeper/abci_internal_test.go @@ -60,7 +60,7 @@ func TestKeeper_PrepareProposal(t *testing.T) { // such as when no transactions are provided, when errors occur while fetching block information, // or when errors occur during fork choice update. t.Run("TestRunErrScenarios", func(t *testing.T) { - t.Parallel() + // t.Parallel() // disable parallel testing for now tests := []struct { name string mockEngine mockEngineAPI @@ -70,7 +70,7 @@ func TestKeeper_PrepareProposal(t *testing.T) { setupMocks func(esk *moduletestutil.MockEvmStakingKeeper) }{ { - name: "no transactions", + name: "pass: no transactions", mockEngine: mockEngineAPI{}, mockClient: mock.MockClient{}, req: &abci.RequestPrepareProposal{ @@ -82,14 +82,14 @@ func TestKeeper_PrepareProposal(t *testing.T) { wantErr: false, }, { - name: "max bytes is less than 9/10 of max block size", + name: "fail: max bytes is less than 9/10 of max block size", mockEngine: mockEngineAPI{}, mockClient: mock.MockClient{}, req: &abci.RequestPrepareProposal{MaxTxBytes: cmttypes.MaxBlockSizeBytes * 1 / 10}, wantErr: true, }, { - name: "with transactions", + name: "fail: with transactions", mockEngine: mockEngineAPI{}, mockClient: mock.MockClient{}, req: &abci.RequestPrepareProposal{ @@ -101,7 +101,7 @@ func TestKeeper_PrepareProposal(t *testing.T) { wantErr: true, }, { - name: "failed to peek eligible withdrawals", + name: "fail: peek eligible withdrawals", mockEngine: mockEngineAPI{}, mockClient: mock.MockClient{}, setupMocks: func(esk *moduletestutil.MockEvmStakingKeeper) { @@ -117,7 +117,7 @@ func TestKeeper_PrepareProposal(t *testing.T) { wantErr: true, }, { - name: "forkchoiceUpdateV3 not valid", + name: "fail: forkchoiceUpdateV3 not valid", mockEngine: mockEngineAPI{ headerByTypeFunc: func(context.Context, ethclient.HeadType) (*types.Header, error) { fuzzer := ethclient.NewFuzzer(0) @@ -153,7 +153,7 @@ func TestKeeper_PrepareProposal(t *testing.T) { }, }, { - name: "unknown payload", + name: "fail: unknown payload", mockEngine: mockEngineAPI{ forkchoiceUpdatedV3Func: func(ctx context.Context, update eengine.ForkchoiceStateV1, payloadAttributes *eengine.PayloadAttributes) (eengine.ForkChoiceResponse, error) { @@ -185,7 +185,7 @@ func TestKeeper_PrepareProposal(t *testing.T) { }, }, { - name: "optimistic payload exists but unknown payload is returned by EL", + name: "fail: optimistic payload exists but unknown payload is returned by EL", mockEngine: mockEngineAPI{ forkchoiceUpdatedV3Func: func(ctx context.Context, update eengine.ForkchoiceStateV1, payloadAttributes *eengine.PayloadAttributes) (eengine.ForkChoiceResponse, error) { @@ -219,7 +219,7 @@ func TestKeeper_PrepareProposal(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - t.Parallel() + // t.Parallel() ctx, storeKey, storeService := setupCtxStore(t, nil) cdc := getCodec(t) txConfig := authtx.NewTxConfig(cdc, nil) @@ -316,7 +316,6 @@ func TestKeeper_PrepareProposal(t *testing.T) { }) } -//nolint:paralleltest // no parallel test for now func TestKeeper_PostFinalize(t *testing.T) { payloadID := eengine.PayloadID{0x1} payloadFailedToSet := func(k *Keeper) { @@ -334,15 +333,26 @@ func TestKeeper_PostFinalize(t *testing.T) { mockClient mock.MockClient wantErr bool enableOptimistic bool + isNextProposer bool setupMocks func(esk *moduletestutil.MockEvmStakingKeeper) postStateCheck func(k *Keeper) }{ { - name: "nothing happens when enableOptimistic is false", + name: "pass: nothing happens when enableOptimistic is false", mockEngine: mockEngineAPI{}, mockClient: mock.MockClient{}, wantErr: false, enableOptimistic: false, + isNextProposer: false, + postStateCheck: payloadFailedToSet, + }, + { + name: "pass: node is not next proposer", + mockEngine: mockEngineAPI{}, + mockClient: mock.MockClient{}, + wantErr: false, + enableOptimistic: true, + isNextProposer: false, postStateCheck: payloadFailedToSet, }, { @@ -351,6 +361,7 @@ func TestKeeper_PostFinalize(t *testing.T) { mockClient: mock.MockClient{}, wantErr: false, enableOptimistic: true, + isNextProposer: true, setupMocks: func(esk *moduletestutil.MockEvmStakingKeeper) { esk.EXPECT().MaxWithdrawalPerBlock(gomock.Any()).Return(uint32(0), nil) esk.EXPECT().PeekEligibleWithdrawals(gomock.Any(), gomock.Any()).Return(nil, errors.New("failed to peek eligible withdrawals")) @@ -375,6 +386,7 @@ func TestKeeper_PostFinalize(t *testing.T) { mockClient: mock.MockClient{}, wantErr: false, enableOptimistic: true, + isNextProposer: true, setupMocks: func(esk *moduletestutil.MockEvmStakingKeeper) { esk.EXPECT().MaxWithdrawalPerBlock(gomock.Any()).Return(uint32(0), nil) esk.EXPECT().PeekEligibleWithdrawals(gomock.Any(), gomock.Any()).Return(nil, nil) @@ -400,6 +412,7 @@ func TestKeeper_PostFinalize(t *testing.T) { mockClient: mock.MockClient{}, wantErr: false, enableOptimistic: true, + isNextProposer: true, setupMocks: func(esk *moduletestutil.MockEvmStakingKeeper) { esk.EXPECT().MaxWithdrawalPerBlock(gomock.Any()).Return(uint32(0), nil) esk.EXPECT().PeekEligibleWithdrawals(gomock.Any(), gomock.Any()).Return(nil, nil) @@ -408,7 +421,7 @@ func TestKeeper_PostFinalize(t *testing.T) { postStateCheck: payloadFailedToSet, }, { - name: "pass", + name: "pass: optimistic build payload", mockEngine: mockEngineAPI{ forkchoiceUpdatedV3Func: func(ctx context.Context, update eengine.ForkchoiceStateV1, payloadAttributes *eengine.PayloadAttributes) (eengine.ForkChoiceResponse, error) { @@ -425,6 +438,7 @@ func TestKeeper_PostFinalize(t *testing.T) { mockClient: mock.MockClient{}, wantErr: false, enableOptimistic: true, + isNextProposer: true, setupMocks: func(esk *moduletestutil.MockEvmStakingKeeper) { esk.EXPECT().MaxWithdrawalPerBlock(gomock.Any()).Return(uint32(0), nil) esk.EXPECT().PeekEligibleWithdrawals(gomock.Any(), gomock.Any()).Return(nil, nil) @@ -453,11 +467,19 @@ func TestKeeper_PostFinalize(t *testing.T) { var err error cmtAPI := newMockCometAPI(t, nil) + // set the header and proposer so we have the correct next proposer header := cmtproto.Header{Height: 1, AppHash: tutil.RandomHash().Bytes()} - header.ProposerAddress = cmtAPI.validatorSet.Validators[0].Address - nxtAddr, err := k1util.PubKeyToAddress(cmtAPI.validatorSet.Validators[1].PubKey) + header.ProposerAddress = cmtAPI.validatorSet.CopyIncrementProposerPriority(1).Proposer.Address + + var nxtAddr common.Address + if tt.isNextProposer { + nxtAddr, err = k1util.PubKeyToAddress(cmtAPI.validatorSet.CopyIncrementProposerPriority(1).Proposer.PubKey) + } else { + nxtAddr = common.HexToAddress("0x0000000000000000000000000000000000000000") + } require.NoError(t, err) + ctx, storeKey, storeService := setupCtxStore(t, &header) ctx = ctx.WithExecMode(sdk.ExecModeFinalize) tt.mockEngine.EngineClient, err = ethclient.NewEngineMock(storeKey) diff --git a/client/x/evmengine/keeper/keeper.go b/client/x/evmengine/keeper/keeper.go index 9a3545cf..038b02ab 100644 --- a/client/x/evmengine/keeper/keeper.go +++ b/client/x/evmengine/keeper/keeper.go @@ -177,32 +177,23 @@ func (k *Keeper) parseAndVerifyProposedPayload(ctx context.Context, msg *types.M return payload, nil } -// isNextProposer returns true if the local node is the proposer -// for the next block. It also returns the next block height. +// isNextProposer returns true if the local node is the proposer for the next block // // Note that the validator set can change, so this is an optimistic check. -func (k *Keeper) isNextProposer(ctx context.Context, currentProposer []byte, currentHeight int64) (bool, error) { +func (k *Keeper) isNextProposer(ctx context.Context, currentHeight int64) (bool, error) { // PostFinalize can be called during block replay (performed in newCometNode), // but cmtAPI is set only after newCometNode completes (see app.SetCometAPI), so a nil check is necessary. if k.cmtAPI == nil { return false, nil } - valset, ok, err := k.cmtAPI.Validators(ctx, currentHeight) + valset, err := k.cmtAPI.Validators(ctx, currentHeight) if err != nil { return false, err - } else if !ok || len(valset.Validators) == 0 { - return false, errors.New("validators not available") } - idx, _ := valset.GetByAddress(currentProposer) - if idx < 0 { - return false, errors.New("proposer not in validator set") - } - - nextIdx := int(idx+1) % len(valset.Validators) - nextProposer := valset.Validators[nextIdx] - nextAddr, err := k1util.PubKeyToAddress(nextProposer.PubKey) + nextProposer := valset.CopyIncrementProposerPriority(1).Proposer + nextAddr, err := k1util.PubKeyToAddress(nextProposer.PubKey) // Convert to EVM address if err != nil { return false, err } diff --git a/client/x/evmengine/keeper/keeper_internal_test.go b/client/x/evmengine/keeper/keeper_internal_test.go index 594c47af..62213768 100644 --- a/client/x/evmengine/keeper/keeper_internal_test.go +++ b/client/x/evmengine/keeper/keeper_internal_test.go @@ -29,10 +29,9 @@ import ( type args struct { height int64 - validatorsFunc func(context.Context, int64) (*cmttypes.ValidatorSet, bool, error) - current int - next int - header func(height int64, address []byte) cmtproto.Header + validatorsFunc func(context.Context, int64) (*cmttypes.ValidatorSet, error) + isNextProposer bool + header func(height int64) cmtproto.Header } func createTestKeeper(t *testing.T) (context.Context, *Keeper) { @@ -69,9 +68,15 @@ func createKeeper(t *testing.T, args args) (sdk.Context, *mockCometAPI, *Keeper) txConfig := authtx.NewTxConfig(cdc, nil) cmtAPI := newMockCometAPI(t, args.validatorsFunc) - header := args.header(args.height, cmtAPI.validatorSet.Validators[args.current].Address) - - nxtAddr, err := k1util.PubKeyToAddress(cmtAPI.validatorSet.Validators[args.next].PubKey) + header := args.header(args.height) + + var nxtAddr common.Address + var err error + if args.isNextProposer { + nxtAddr, err = k1util.PubKeyToAddress(cmtAPI.validatorSet.CopyIncrementProposerPriority(1).Proposer.PubKey) + } else { + nxtAddr = common.HexToAddress("0x0000000000000000000000000000000000000000") + } require.NoError(t, err) ctrl := gomock.NewController(t) @@ -118,11 +123,9 @@ func TestKeeper_parseAndVerifyProposedPayload(t *testing.T) { now := time.Now() fuzzer := ethclient.NewFuzzer(now.Unix()) ctx, _, keeper := createKeeper(t, args{ - height: 0, - current: 0, - next: 1, - header: func(height int64, address []byte) cmtproto.Header { - return cmtproto.Header{Height: height, ProposerAddress: address} + height: 0, + header: func(height int64) cmtproto.Header { + return cmtproto.Header{Height: height} }, }) @@ -270,11 +273,9 @@ func TestKeeper_parseAndVerifyProposedPayload(t *testing.T) { func TestKeeper_setOptimisticPayload(t *testing.T) { t.Parallel() _, _, keeper := createKeeper(t, args{ - height: 0, - current: 0, - next: 1, - header: func(height int64, address []byte) cmtproto.Header { - return cmtproto.Header{Height: height, ProposerAddress: address} + height: 0, + header: func(height int64) cmtproto.Header { + return cmtproto.Header{Height: height} }, }) @@ -292,81 +293,44 @@ func TestKeeper_isNextProposer(t *testing.T) { t.Parallel() height := int64(1) tests := []struct { - name string - args args - want bool - wantHeight uint64 - wantErr bool + name string + args args + want bool + wantErr bool }{ { - name: "is next proposer", + name: "not proposer", args: args{ - height: height, - current: 0, - next: 1, - header: func(height int64, address []byte) cmtproto.Header { - return cmtproto.Header{Height: height, ProposerAddress: address} + height: height, + isNextProposer: false, + header: func(height int64) cmtproto.Header { + return cmtproto.Header{Height: height} }, }, - want: true, - wantHeight: 2, - wantErr: false, + want: false, + wantErr: false, }, { - name: "proposer false", + name: "next proposer", args: args{ - height: height, - current: 0, - next: 2, - header: func(height int64, address []byte) cmtproto.Header { - return cmtproto.Header{Height: height, ProposerAddress: address} + height: height, + isNextProposer: true, + header: func(height int64) cmtproto.Header { + return cmtproto.Header{Height: height} }, }, - want: false, - wantHeight: 2, - wantErr: false, + want: true, + wantErr: false, }, { name: "validatorsFunc error", args: args{ - height: height, - current: 0, - next: 1, - validatorsFunc: func(ctx context.Context, i int64) (*cmttypes.ValidatorSet, bool, error) { - return nil, false, errors.New("error") + height: height, + validatorsFunc: func(ctx context.Context, i int64) (*cmttypes.ValidatorSet, error) { + return nil, errors.New("error") }, - header: func(height int64, address []byte) cmtproto.Header { - return cmtproto.Header{Height: height, ProposerAddress: address} - }, - }, - want: false, - wantErr: true, - }, - { - name: "validatorsFunc not ok", - args: args{ - height: height, - current: 0, - next: 1, - validatorsFunc: func(ctx context.Context, i int64) (*cmttypes.ValidatorSet, bool, error) { - return nil, false, nil - }, - header: func(height int64, address []byte) cmtproto.Header { - return cmtproto.Header{Height: height, ProposerAddress: address} - }, - }, - want: false, - wantErr: true, - }, - { - name: "invalid val index", - args: args{ - height: height, - current: 0, - next: 1, - - header: func(height int64, address []byte) cmtproto.Header { - return cmtproto.Header{Height: height, ProposerAddress: []byte("invalid")} + header: func(height int64) cmtproto.Header { + return cmtproto.Header{Height: height} }, }, want: false, @@ -379,7 +343,7 @@ func TestKeeper_isNextProposer(t *testing.T) { ctx, cmtAPI, keeper := createKeeper(t, tt.args) - got, err := keeper.isNextProposer(ctx, ctx.BlockHeader().ProposerAddress, ctx.BlockHeader().Height) + got, err := keeper.isNextProposer(ctx, ctx.BlockHeader().Height) if (err != nil) != tt.wantErr { t.Errorf("isNextProposer() error = %v, wantErr %v", err, tt.wantErr) return @@ -399,11 +363,11 @@ type mockCometAPI struct { comet.API fuzzer *fuzz.Fuzzer validatorSet *cmttypes.ValidatorSet - validatorsFunc func(context.Context, int64) (*cmttypes.ValidatorSet, bool, error) + validatorsFunc func(context.Context, int64) (*cmttypes.ValidatorSet, error) height int64 } -func newMockCometAPI(t *testing.T, valFun func(context.Context, int64) (*cmttypes.ValidatorSet, bool, error)) *mockCometAPI { +func newMockCometAPI(t *testing.T, valFun func(context.Context, int64) (*cmttypes.ValidatorSet, error)) *mockCometAPI { t.Helper() fuzzer := newFuzzer(0) valSet := fuzzValidators(t, fuzzer) @@ -428,13 +392,13 @@ func fuzzValidators(t *testing.T, fuzzer *fuzz.Fuzzer) *cmttypes.ValidatorSet { return valSet } -func (m *mockCometAPI) Validators(ctx context.Context, height int64) (*cmttypes.ValidatorSet, bool, error) { +func (m *mockCometAPI) Validators(ctx context.Context, height int64) (*cmttypes.ValidatorSet, error) { m.height = height if m.validatorsFunc != nil { return m.validatorsFunc(ctx, height) } - return m.validatorSet, true, nil + return m.validatorSet, nil } // newFuzzer - create a new custom cmttypes.Validator fuzzer. diff --git a/client/x/evmengine/keeper/msg_server_internal_test.go b/client/x/evmengine/keeper/msg_server_internal_test.go index bd38adb2..baa46868 100644 --- a/client/x/evmengine/keeper/msg_server_internal_test.go +++ b/client/x/evmengine/keeper/msg_server_internal_test.go @@ -46,7 +46,7 @@ func Test_msgServer_ExecutionPayload(t *testing.T) { // set the header and proposer so we have the correct next proposer header := cmtproto.Header{Height: 1, AppHash: tutil.RandomHash().Bytes()} header.ProposerAddress = cmtAPI.validatorSet.Validators[0].Address - nxtAddr, err := k1util.PubKeyToAddress(cmtAPI.validatorSet.Validators[1].PubKey) + nxtAddr, err := k1util.PubKeyToAddress(cmtAPI.validatorSet.CopyIncrementProposerPriority(1).Proposer.PubKey) require.NoError(t, err) ctx, storeKey, storeService := setupCtxStore(t, &header) diff --git a/client/x/evmengine/keeper/upgrades_internal_test.go b/client/x/evmengine/keeper/upgrades_internal_test.go index cc0af494..9e0e0947 100644 --- a/client/x/evmengine/keeper/upgrades_internal_test.go +++ b/client/x/evmengine/keeper/upgrades_internal_test.go @@ -278,7 +278,7 @@ func setupTestEnvironment(t *testing.T) (*Keeper, sdk.Context, *gomock.Controlle keeper, err := NewKeeper(cdc, storeService, &mockEngine, mockClient, txConfig, ak, esk, uk, dk) require.NoError(t, err) keeper.SetCometAPI(cmtAPI) - nxtAddr, err := k1util.PubKeyToAddress(cmtAPI.validatorSet.Validators[1].PubKey) + nxtAddr, err := k1util.PubKeyToAddress(cmtAPI.validatorSet.CopyIncrementProposerPriority(1).Proposer.PubKey) require.NoError(t, err) keeper.SetValidatorAddress(nxtAddr) populateGenesisHead(ctx, t, keeper) diff --git a/client/x/mint/keeper/genesis_test.go b/client/x/mint/keeper/genesis_test.go index dbf24ee1..660e4ae4 100644 --- a/client/x/mint/keeper/genesis_test.go +++ b/client/x/mint/keeper/genesis_test.go @@ -1,4 +1,3 @@ -//nolint:paralleltest // just for testing package keeper_test import ( diff --git a/client/x/mint/keeper/grpc_query_test.go b/client/x/mint/keeper/grpc_query_test.go index 0f7ce6da..1416dfbe 100644 --- a/client/x/mint/keeper/grpc_query_test.go +++ b/client/x/mint/keeper/grpc_query_test.go @@ -1,4 +1,3 @@ -//nolint:paralleltest // just for testing package keeper_test import ( diff --git a/client/x/mint/keeper/keeper_test.go b/client/x/mint/keeper/keeper_test.go index ace6bf97..fc3c2d75 100644 --- a/client/x/mint/keeper/keeper_test.go +++ b/client/x/mint/keeper/keeper_test.go @@ -1,4 +1,3 @@ -//nolint:paralleltest // just for testing package keeper_test import ( diff --git a/lib/expbackoff/expbackoff_test.go b/lib/expbackoff/expbackoff_test.go index 7716f533..bad8c69c 100644 --- a/lib/expbackoff/expbackoff_test.go +++ b/lib/expbackoff/expbackoff_test.go @@ -1,4 +1,3 @@ -//nolint:paralleltest // Parallel tests not supported since test-alias globals are used. package expbackoff_test import (