From c11084dd51aa6103a8231e76973c45d705ce3e09 Mon Sep 17 00:00:00 2001 From: bianyuanop Date: Thu, 6 Feb 2025 16:05:11 -0500 Subject: [PATCH] get arcadia block with signature verification --- common/types.go | 18 +++++ common/utils.go | 13 ++++ datalayer/mocks/mock_IDASubmitter.go | 2 +- datastore/mocks/mock_IDatastore.go | 8 +- seq/consts.go | 4 + seq/mocks/mock_BaseSeqClient.go | 79 +++++++++++++++++--- seq/seqclient.go | 34 +++++++++ services/api/service.go | 63 +++++++++++++--- services/api/service_test.go | 63 ++++++++++++++-- simulator/mocks/mock_IBlockSimRateLimiter.go | 4 +- 10 files changed, 257 insertions(+), 31 deletions(-) create mode 100644 seq/consts.go diff --git a/common/types.go b/common/types.go index 70f32475..1de9d155 100644 --- a/common/types.go +++ b/common/types.go @@ -23,6 +23,7 @@ import ( "github.com/AnomalyFi/hypersdk/chain" "github.com/AnomalyFi/hypersdk/codec" + abls "github.com/AnomalyFi/hypersdk/crypto/bls" "github.com/AnomalyFi/hypersdk/utils" "github.com/AnomalyFi/nodekit-seq/actions" "github.com/ava-labs/avalanchego/ids" @@ -1135,6 +1136,23 @@ type GetBlockPayloadFromArcadia struct { BlockNumber uint64 `json:"blockNumber"` } +func (req *GetBlockPayloadFromArcadia) Payload() ([]byte, error) { + return json.Marshal(req) +} + +func (req *GetBlockPayloadFromArcadia) VerifyIssuer(networkID uint32, seqChainID ids.ID, pk *abls.PublicKey, sig *abls.Signature) (bool, error) { + payload, err := req.Payload() + if err != nil { + return false, err + } + uwm, err := warp.NewUnsignedMessage(networkID, seqChainID, payload) + if err != nil { + return false, err + } + uwmBytes := uwm.Bytes() + return abls.Verify(uwmBytes, pk, sig), nil +} + type SEQTxWrapper struct { Tx *chain.Transaction Size int diff --git a/common/utils.go b/common/utils.go index 323bb94e..a56b909f 100644 --- a/common/utils.go +++ b/common/utils.go @@ -12,6 +12,7 @@ import ( "strings" "time" + abls "github.com/AnomalyFi/hypersdk/crypto/bls" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/AnomalyFi/hypersdk/chain" @@ -221,3 +222,15 @@ func BuildDACert(chunk *ArcadiaChunk, epoch uint64, certificate []byte) *seqtype return robDA } } + +func HeaderToSEQSignature(sigHeader string) (*abls.Signature, error) { + sigBytes, err := hexutil.Decode(sigHeader) + if err != nil { + return nil, err + } + return abls.SignatureFromBytes(sigBytes) +} + +func BytesToSEQPubkey(pkBytes []byte) (*abls.PublicKey, error) { + return abls.PublicKeyFromBytes(pkBytes) +} diff --git a/datalayer/mocks/mock_IDASubmitter.go b/datalayer/mocks/mock_IDASubmitter.go index b83dcace..0f0ea340 100644 --- a/datalayer/mocks/mock_IDASubmitter.go +++ b/datalayer/mocks/mock_IDASubmitter.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.50.0. DO NOT EDIT. +// Code generated by mockery v2.39.0. DO NOT EDIT. package mocks diff --git a/datastore/mocks/mock_IDatastore.go b/datastore/mocks/mock_IDatastore.go index bb2c836b..01d011c3 100644 --- a/datastore/mocks/mock_IDatastore.go +++ b/datastore/mocks/mock_IDatastore.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.50.0. DO NOT EDIT. +// Code generated by mockery v2.39.0. DO NOT EDIT. package mocks @@ -372,7 +372,7 @@ func (_c *MockIDatastore_LoadChunksWithToBNonce_Call) RunAndReturn(run func(uint return _c } -// LoadCurrentToBNonce provides a mock function with no fields +// LoadCurrentToBNonce provides a mock function with given fields: func (_m *MockIDatastore) LoadCurrentToBNonce() (*uint64, error) { ret := _m.Called() @@ -429,7 +429,7 @@ func (_c *MockIDatastore_LoadCurrentToBNonce_Call) RunAndReturn(run func() (*uin return _c } -// LoadHighestSettledToBNonce provides a mock function with no fields +// LoadHighestSettledToBNonce provides a mock function with given fields: func (_m *MockIDatastore) LoadHighestSettledToBNonce() (*uint64, error) { ret := _m.Called() @@ -486,7 +486,7 @@ func (_c *MockIDatastore_LoadHighestSettledToBNonce_Call) RunAndReturn(run func( return _c } -// LoadLowestManagedStateToBNonce provides a mock function with no fields +// LoadLowestManagedStateToBNonce provides a mock function with given fields: func (_m *MockIDatastore) LoadLowestManagedStateToBNonce() (*uint64, error) { ret := _m.Called() diff --git a/seq/consts.go b/seq/consts.go new file mode 100644 index 00000000..2f0c7f48 --- /dev/null +++ b/seq/consts.go @@ -0,0 +1,4 @@ +package seq + +const DefaultProposerLRUSize = 20 +const GetArcadiaBlockSignatureHeader = "X-Arcadia-GetBlock-Sig" diff --git a/seq/mocks/mock_BaseSeqClient.go b/seq/mocks/mock_BaseSeqClient.go index 822354e2..eb932b09 100644 --- a/seq/mocks/mock_BaseSeqClient.go +++ b/seq/mocks/mock_BaseSeqClient.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.50.0. DO NOT EDIT. +// Code generated by mockery v2.39.0. DO NOT EDIT. package mocks @@ -30,7 +30,7 @@ func (_m *MockBaseSeqClient) EXPECT() *MockBaseSeqClient_Expecter { return &MockBaseSeqClient_Expecter{mock: &_m.Mock} } -// CurrentEpoch provides a mock function with no fields +// CurrentEpoch provides a mock function with given fields: func (_m *MockBaseSeqClient) CurrentEpoch() uint64 { ret := _m.Called() @@ -123,7 +123,7 @@ func (_c *MockBaseSeqClient_CurrentValidators_Call) RunAndReturn(run func(contex return _c } -// CurrentValidatorsTotalWeight provides a mock function with no fields +// CurrentValidatorsTotalWeight provides a mock function with given fields: func (_m *MockBaseSeqClient) CurrentValidatorsTotalWeight() uint64 { ret := _m.Called() @@ -284,7 +284,7 @@ func (_c *MockBaseSeqClient_GetBalance_Call) RunAndReturn(run func(context.Conte return _c } -// GetChainID provides a mock function with no fields +// GetChainID provides a mock function with given fields: func (_m *MockBaseSeqClient) GetChainID() ids.ID { ret := _m.Called() @@ -331,7 +331,7 @@ func (_c *MockBaseSeqClient_GetChainID_Call) RunAndReturn(run func() ids.ID) *Mo return _c } -// GetNetworkID provides a mock function with no fields +// GetNetworkID provides a mock function with given fields: func (_m *MockBaseSeqClient) GetNetworkID() uint32 { ret := _m.Called() @@ -481,7 +481,7 @@ func (_c *MockBaseSeqClient_GetValidatorWeight_Call) RunAndReturn(run func([]byt return _c } -// Parser provides a mock function with no fields +// Parser provides a mock function with given fields: func (_m *MockBaseSeqClient) Parser() chain.Parser { ret := _m.Called() @@ -528,7 +528,66 @@ func (_c *MockBaseSeqClient_Parser_Call) RunAndReturn(run func() chain.Parser) * return _c } -// SeqHead provides a mock function with no fields +// ProposerAtHeight provides a mock function with given fields: ctx, height +func (_m *MockBaseSeqClient) ProposerAtHeight(ctx context.Context, height uint64) (*rpc.Validator, error) { + ret := _m.Called(ctx, height) + + if len(ret) == 0 { + panic("no return value specified for ProposerAtHeight") + } + + var r0 *rpc.Validator + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64) (*rpc.Validator, error)); ok { + return rf(ctx, height) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64) *rpc.Validator); ok { + r0 = rf(ctx, height) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*rpc.Validator) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64) error); ok { + r1 = rf(ctx, height) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockBaseSeqClient_ProposerAtHeight_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ProposerAtHeight' +type MockBaseSeqClient_ProposerAtHeight_Call struct { + *mock.Call +} + +// ProposerAtHeight is a helper method to define mock.On call +// - ctx context.Context +// - height uint64 +func (_e *MockBaseSeqClient_Expecter) ProposerAtHeight(ctx interface{}, height interface{}) *MockBaseSeqClient_ProposerAtHeight_Call { + return &MockBaseSeqClient_ProposerAtHeight_Call{Call: _e.mock.On("ProposerAtHeight", ctx, height)} +} + +func (_c *MockBaseSeqClient_ProposerAtHeight_Call) Run(run func(ctx context.Context, height uint64)) *MockBaseSeqClient_ProposerAtHeight_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint64)) + }) + return _c +} + +func (_c *MockBaseSeqClient_ProposerAtHeight_Call) Return(_a0 *rpc.Validator, _a1 error) *MockBaseSeqClient_ProposerAtHeight_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockBaseSeqClient_ProposerAtHeight_Call) RunAndReturn(run func(context.Context, uint64) (*rpc.Validator, error)) *MockBaseSeqClient_ProposerAtHeight_Call { + _c.Call.Return(run) + return _c +} + +// SeqHead provides a mock function with given fields: func (_m *MockBaseSeqClient) SeqHead() *chain.StatefulBlock { ret := _m.Called() @@ -604,11 +663,11 @@ func (_c *MockBaseSeqClient_SetOnNewBlockHandler_Call) Return() *MockBaseSeqClie } func (_c *MockBaseSeqClient_SetOnNewBlockHandler_Call) RunAndReturn(run func(func(*chain.StatefulBlock, []*chain.Result))) *MockBaseSeqClient_SetOnNewBlockHandler_Call { - _c.Run(run) + _c.Call.Return(run) return _c } -// Stop provides a mock function with no fields +// Stop provides a mock function with given fields: func (_m *MockBaseSeqClient) Stop() { _m.Called() } @@ -636,7 +695,7 @@ func (_c *MockBaseSeqClient_Stop_Call) Return() *MockBaseSeqClient_Stop_Call { } func (_c *MockBaseSeqClient_Stop_Call) RunAndReturn(run func()) *MockBaseSeqClient_Stop_Call { - _c.Run(run) + _c.Call.Return(run) return _c } diff --git a/seq/seqclient.go b/seq/seqclient.go index 8ec721f9..6266c582 100644 --- a/seq/seqclient.go +++ b/seq/seqclient.go @@ -20,6 +20,7 @@ import ( "github.com/AnomalyFi/nodekit-seq/auth" "github.com/AnomalyFi/nodekit-seq/consts" srpc "github.com/AnomalyFi/nodekit-seq/rpc" + avacache "github.com/ava-labs/avalanchego/cache" "github.com/ava-labs/avalanchego/ids" "github.com/sirupsen/logrus" ) @@ -55,6 +56,7 @@ type BaseSeqClient interface { SubmitActions(ctx context.Context, action []chain.Action) (ids.ID, error) GenerateTransaction(ctx context.Context, acts []chain.Action) (*chain.Transaction, error) + ProposerAtHeight(ctx context.Context, height uint64) (*hrpc.Validator, error) } var _ BaseSeqClient = (*SeqClient)(nil) @@ -69,6 +71,7 @@ type SeqClient struct { blockHead *chain.StatefulBlock blockHeadL sync.RWMutex + proposerAtHeight *avacache.LRU[uint64, *hrpc.Validator] currentValidators []*hrpc.Validator // ETH Chain related @@ -128,6 +131,9 @@ func NewSeqClient(config *SeqClientConfig) (*SeqClient, error) { wsCli: wsCli, signer: config.PrivateKey, + currentValidators: make([]*hrpc.Validator, 0), + proposerAtHeight: &avacache.LRU[uint64, *hrpc.Validator]{Size: DefaultProposerLRUSize}, + Namespace: nil, parser: parser, @@ -180,6 +186,19 @@ func NewSeqClient(config *SeqClientConfig) (*SeqClient, error) { client.logger.WithField("validatorPubkeys", validatorPubkeys).Debug("setting new validator set") } + // query the proposer at height + 1 + go func() { + proposer, err := client.hrpc.NextProposer(ctx, blk.Hght+1) + if err != nil { + client.logger.WithFields(logrus.Fields{ + "seqHeight": blk.Hght, + "err": err, + }).Warn("unable to query the next proposer at height") + return + } + client.proposerAtHeight.Put(blk.Hght+1, proposer) + }() + // calculate total weight of current validators. var totalWeight uint64 for _, val := range currVal { @@ -366,3 +385,18 @@ func (s *SeqClient) GetRollupsValidAtEpoch(ctx context.Context, epoch uint64) ([ } return seqRollups.Rollups, nil } + +func (s *SeqClient) ProposerAtHeight(ctx context.Context, height uint64) (*hrpc.Validator, error) { + proposer, exists := s.proposerAtHeight.Get(height) + if exists { + return proposer, nil + } + + proposer, err := s.hrpc.NextProposer(ctx, height) + if err != nil { + return nil, err + } + + s.proposerAtHeight.Put(height, proposer) + return proposer, nil +} diff --git a/services/api/service.go b/services/api/service.go index 5c4c8f1d..d76d13bc 100644 --- a/services/api/service.go +++ b/services/api/service.go @@ -1064,7 +1064,7 @@ func (api *ArcadiaAPI) handleGetPayload(w http.ResponseWriter, req *http.Request payload := new(common.GetPayloadRequest) if err := json.Unmarshal(body, payload); err != nil { log.WithError(err).Warn("failed to decode getPayload request") - api.RespondError(w, http.StatusBadRequest, "failed to decode anchor payload request") + api.RespondError(w, http.StatusBadRequest, "failed to decode payload request") return } log = log.WithFields(logrus.Fields{ @@ -2327,22 +2327,68 @@ func (api *ArcadiaAPI) handleGetArcadiaBlock(w http.ResponseWriter, req *http.Re body, err := io.ReadAll(req.Body) if err != nil { if strings.Contains(err.Error(), "i/o timeout") { - api.log.WithError(err).Error("handleGetArcadiaBlock() request failed to decode (i/o timeout)") + log.WithError(err).Error("handleGetArcadiaBlock() request failed to decode (i/o timeout)") api.RespondError(w, http.StatusInternalServerError, err.Error()) return } - api.log.Error("could not read body of request for handleGetArcadiaBlock()") + log.Error("could not read body of request for handleGetArcadiaBlock()") api.RespondError(w, http.StatusBadRequest, err.Error()) return } plreq := new(common.GetBlockPayloadFromArcadia) if err := json.NewDecoder(bytes.NewReader(body)).Decode(plreq); err != nil { - api.log.Error("failed to decode arcadia block request") + log.Error("failed to decode arcadia block request") api.RespondError(w, http.StatusBadRequest, err.Error()) return } + log = log.WithField("seqHeight", plreq.BlockNumber) + + // do proposer verification + ctx := context.Background() + ctx, cancel := context.WithTimeout(ctx, 500*time.Second) + defer cancel() + proposer, err := api.seqClient.ProposerAtHeight(ctx, plreq.BlockNumber) + if err != nil { + log.WithError(err).Error("failed to fetch proposer at height") + api.RespondError(w, http.StatusBadRequest, err.Error()) + return + } + proposerPubkey, err := common.BytesToSEQPubkey(proposer.PublicKey) + if err != nil { + log.WithError(err).Error("failed to parse proposer pubkey") + api.RespondError(w, http.StatusBadRequest, err.Error()) + return + } + + proposerSigStr := req.Header.Get(seq.GetArcadiaBlockSignatureHeader) + proposerSig, err := common.HeaderToSEQSignature(proposerSigStr) + if err != nil { + log.WithError(err).Error("failed to extract proposer signature from header") + api.RespondError(w, http.StatusBadRequest, err.Error()) + return + } + seqNetworkID := api.seqClient.GetNetworkID() + seqChainID := api.seqClient.GetChainID() + log = log.WithFields(logrus.Fields{ + "proposerPubkey": hexutil.Encode(proposer.PublicKey), + "sig": proposerSigStr, + "seqNetworkID": seqNetworkID, + "seqChainID": seqChainID.String(), + }) + verified, err := plreq.VerifyIssuer(seqNetworkID, seqChainID, proposerPubkey, proposerSig) + if err != nil { + log.WithError(err).Error("failed to verify signature of the get block request") + api.RespondError(w, http.StatusBadRequest, err.Error()) + return + } + if !verified { + log.Error("wrong sigature against the given payload") + api.RespondError(w, http.StatusBadRequest, "unable to verify signature") + return + } + txsw := api.pendingTxs.StreamTxs(int(plreq.MaxBandwidth)) var txs []*chain.Transaction for _, tx := range txsw { @@ -2361,13 +2407,13 @@ func (api *ArcadiaAPI) handleGetArcadiaBlock(w http.ResponseWriter, req *http.Re } } if len(txs) == 0 { - api.log.Errorf("no transactions available, block: %d", plreq.BlockNumber) + log.Errorf("no transactions available, block: %d", plreq.BlockNumber) api.RespondError(w, http.StatusNoContent, "no transactions available") return } mtxs, err := chain.MarshalTxs(txs) if err != nil { - api.log.Errorf("no transactions available, block: %d", plreq.BlockNumber) + log.Errorf("no transactions available, block: %d", plreq.BlockNumber) api.RespondError(w, http.StatusNoContent, "no transactions available") return } @@ -2391,13 +2437,12 @@ func (api *ArcadiaAPI) handleSubscribeValidator(w http.ResponseWriter, req *http epoch := api.headEpoch.Load() - log := api.log.WithField("method", "subscribeValidator") - log.Info("Received subscribe validator request") - log = api.log.WithFields(logrus.Fields{ + log := api.log.WithFields(logrus.Fields{ "method": "subscribeValidator", "contentLength": req.ContentLength, "timestampRequestStart": time.Now().UTC().UnixMilli(), }) + log.Info("Received subscribe validator request") conn, err := api.upgrader.Upgrade(w, req, nil) if err != nil { diff --git a/services/api/service_test.go b/services/api/service_test.go index 56d06ea1..d1a313e9 100644 --- a/services/api/service_test.go +++ b/services/api/service_test.go @@ -40,6 +40,7 @@ import ( "github.com/AnomalyFi/Arcadia/common" "github.com/AnomalyFi/Arcadia/database" "github.com/AnomalyFi/Arcadia/datastore" + "github.com/AnomalyFi/Arcadia/seq" mseq "github.com/AnomalyFi/Arcadia/seq/mocks" "github.com/AnomalyFi/Arcadia/simulator" msim "github.com/AnomalyFi/Arcadia/simulator/mocks" @@ -228,7 +229,7 @@ func (be *testBackend) request(method, path string, payload any) *httptest.Respo return rr } -func (be *testBackend) RequestWithPayloadHeader(method, path string, payload any, sig string) *httptest.ResponseRecorder { +func (be *testBackend) RequestWithHeaders(method, path string, payload any, headers map[string]string) *httptest.ResponseRecorder { var req *http.Request var err error path = "/api" + path @@ -241,12 +242,20 @@ func (be *testBackend) RequestWithPayloadHeader(method, path string, payload any req, err = http.NewRequest(method, path, bytes.NewReader(payloadBytes)) } require.NoError(be.t, err) - req.Header.Set(GetPayloadHeaderRollupSig, sig) + for header, value := range headers { + req.Header.Set(header, value) + } rr := httptest.NewRecorder() be.arcadia.getRouter().ServeHTTP(rr, req) return rr } +func (be *testBackend) RequestWithPayloadHeader(method, path string, payload any, sig string) *httptest.ResponseRecorder { + return be.RequestWithHeaders(method, path, payload, map[string]string{ + GetPayloadHeaderRollupSig: sig, + }) +} + func (be *testBackend) SetupRegisteredRollups(epoch uint64, chainID *big.Int) { namespace := common.ChainIDToNamespace(chainID) rollup := &actions.RollupInfo{ @@ -1132,9 +1141,14 @@ func TestAuctionBid(t *testing.T) { func TestArcadiaBlock(t *testing.T) { path := "/arcadia/v1/validator/block" + seqNetworkID := uint32(1337) seqChainID := ids.GenerateTestID() parser := srpc.Parser{} chainIDs := []*big.Int{big.NewInt(42000), big.NewInt(43000)} + proposerSK, err := abls.NewSecretKey() + require.NoError(t, err) + proposerPK := abls.PublicFromSecretKey(proposerSK) + proposerPKBytes := proposerPK.Compress() t.Run("baseline case", func(t *testing.T) { backend := newTestBackend(t) @@ -1149,12 +1163,33 @@ func TestArcadiaBlock(t *testing.T) { maxBandwidth := uint64(20000) blockNumber := uint64(15) + + // setup seq client mock + backend.seqcli.EXPECT().GetNetworkID().Return(seqNetworkID) + backend.seqcli.EXPECT().GetChainID().Return(seqChainID) + backend.seqcli.EXPECT().ProposerAtHeight(mock.Anything, blockNumber).Return(&hrpc.Validator{ + NodeID: ids.GenerateTestNodeID(), + PublicKey: proposerPKBytes, + Weight: 1000, + }, nil) + + // prepare request and signature req := common.GetBlockPayloadFromArcadia{ MaxBandwidth: maxBandwidth, BlockNumber: blockNumber, } - rr := backend.request(http.MethodPost, path, req) + payload, err := req.Payload() + require.NoError(t, err) + uwm, err := warp.NewUnsignedMessage(seqNetworkID, seqChainID, payload) + require.NoError(t, err) + uwmBytes := uwm.Bytes() + sig := abls.Sign(proposerSK, uwmBytes) + sigStr := hexutil.Encode(sig.Compress()) + + rr := backend.RequestWithHeaders(http.MethodPost, path, req, map[string]string{ + seq.GetArcadiaBlockSignatureHeader: sigStr, + }) require.Equal(t, http.StatusOK, rr.Code) var response common.GetBlockPayloadFromArcadiaResponse @@ -1168,15 +1203,33 @@ func TestArcadiaBlock(t *testing.T) { maxBandwidth := uint64(1000) blockNumber := uint64(15) + + // setup seq client mock + backend.seqcli.EXPECT().GetNetworkID().Return(seqNetworkID) + backend.seqcli.EXPECT().GetChainID().Return(seqChainID) + backend.seqcli.EXPECT().ProposerAtHeight(mock.Anything, blockNumber).Return(&hrpc.Validator{ + NodeID: ids.GenerateTestNodeID(), + PublicKey: proposerPKBytes, + Weight: 1000, + }, nil) + req := common.GetBlockPayloadFromArcadia{ MaxBandwidth: maxBandwidth, BlockNumber: blockNumber, } + payload, err := req.Payload() + require.NoError(t, err) + uwm, err := warp.NewUnsignedMessage(seqNetworkID, seqChainID, payload) + require.NoError(t, err) + uwmBytes := uwm.Bytes() + sig := abls.Sign(proposerSK, uwmBytes) + sigStr := hexutil.Encode(sig.Compress()) - rr := backend.request(http.MethodPost, path, req) + rr := backend.RequestWithHeaders(http.MethodPost, path, req, map[string]string{ + seq.GetArcadiaBlockSignatureHeader: sigStr, + }) require.Equal(t, http.StatusNoContent, rr.Code) }) - } func TestSubmitChunkToSEQValidators(t *testing.T) { diff --git a/simulator/mocks/mock_IBlockSimRateLimiter.go b/simulator/mocks/mock_IBlockSimRateLimiter.go index 227fbe28..4b7b1539 100644 --- a/simulator/mocks/mock_IBlockSimRateLimiter.go +++ b/simulator/mocks/mock_IBlockSimRateLimiter.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.50.0. DO NOT EDIT. +// Code generated by mockery v2.39.0. DO NOT EDIT. package mocks @@ -30,7 +30,7 @@ func (_m *MockIBlockSimRateLimiter) EXPECT() *MockIBlockSimRateLimiter_Expecter return &MockIBlockSimRateLimiter_Expecter{mock: &_m.Mock} } -// CurrentCounter provides a mock function with no fields +// CurrentCounter provides a mock function with given fields: func (_m *MockIBlockSimRateLimiter) CurrentCounter() int64 { ret := _m.Called()