From 87acc7acc18cf87f0cfcfbf3849cb1cb4ba7adea Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Wed, 10 Apr 2024 18:33:25 +0800 Subject: [PATCH] feat: add check for payment data --- app/app.go | 2 + app/config.go | 20 ++ cmd/gnfd/cmd/root.go | 2 +- testutil/app.go | 2 +- x/payment/keeper/stream_record.go | 2 +- x/storage/keeper/abci.go | 9 + x/storage/keeper/keeper.go | 17 ++ x/storage/keeper/payment_check.go | 283 ++++++++++++++++++++++ x/storage/types/expected_keepers.go | 2 + x/storage/types/expected_keepers_mocks.go | 270 +++++++++++++++++++++ 10 files changed, 606 insertions(+), 3 deletions(-) create mode 100644 x/storage/keeper/payment_check.go diff --git a/app/app.go b/app/app.go index 7cb184c3d..94542b87d 100644 --- a/app/app.go +++ b/app/app.go @@ -746,6 +746,8 @@ func (app *App) initBridge() { func (app *App) initStorage() { storagemodulekeeper.RegisterCrossApps(app.StorageKeeper) + storagemodulekeeper.InitPaymentCheck(app.StorageKeeper, app.appConfig.PaymentCheck.Enabled, + app.appConfig.PaymentCheck.Interval) } func (app *App) initGov() { diff --git a/app/config.go b/app/config.go index 017a094d8..ed64ff7f0 100644 --- a/app/config.go +++ b/app/config.go @@ -8,6 +8,8 @@ type AppConfig struct { serverconfig.Config CrossChain CrossChainConfig `mapstructure:"cross-chain"` + + PaymentCheck PaymentCheckConfig `mapstructure:"payment-check"` } type CrossChainConfig struct { @@ -18,6 +20,11 @@ type CrossChainConfig struct { DestOpChainId uint32 `mapstructure:"dest-op-chain-id"` } +type PaymentCheckConfig struct { + Enabled bool `mapstructure:"enabled"` + Interval uint32 `mapstructure:"interval"` +} + var CustomAppTemplate = serverconfig.DefaultConfigTemplate + ` ############################################################################### ### CrossChain Config ### @@ -29,6 +36,15 @@ src-chain-id = {{ .CrossChain.SrcChainId }} dest-bsc-chain-id = {{ .CrossChain.DestBscChainId }} # chain-id for op bnb destination chain dest-op-chain-id = {{ .CrossChain.DestOpChainId }} + +############################################################################### +### PaymentCheck Config ### +############################################################################### +[payment-check] +# enabled - the flag to enable/disable payment check +enabled = {{ .PaymentCheck.Enabled }} +# interval - the block interval run check payment +interval = {{ .PaymentCheck.Interval }} ` func NewDefaultAppConfig() *AppConfig { @@ -54,5 +70,9 @@ func NewDefaultAppConfig() *AppConfig { DestBscChainId: 2, DestOpChainId: 3, }, + PaymentCheck: PaymentCheckConfig{ + Enabled: false, + Interval: 100, + }, } } diff --git a/cmd/gnfd/cmd/root.go b/cmd/gnfd/cmd/root.go index 0b864b42a..0df872495 100644 --- a/cmd/gnfd/cmd/root.go +++ b/cmd/gnfd/cmd/root.go @@ -352,7 +352,7 @@ func (a appCreator) newApp( cast.ToString(appOpts.Get(flags.FlagHome)), cast.ToUint(appOpts.Get(server.FlagInvCheckPeriod)), a.encodingConfig, - &app.AppConfig{Config: *serverConfig, CrossChain: appConfig.CrossChain}, + &app.AppConfig{Config: *serverConfig, CrossChain: appConfig.CrossChain, PaymentCheck: appConfig.PaymentCheck}, appOpts, baseapp.SetPruning(pruningOpts), baseapp.SetEventing(cast.ToString(appOpts.Get(server.FlagEventing))), diff --git a/testutil/app.go b/testutil/app.go index 4a62c3237..b6574d2b3 100644 --- a/testutil/app.go +++ b/testutil/app.go @@ -58,7 +58,7 @@ func NewTestApp( app.DefaultNodeHome, 0, encCfg, - &app.AppConfig{CrossChain: app.NewDefaultAppConfig().CrossChain}, + &app.AppConfig{CrossChain: app.NewDefaultAppConfig().CrossChain, PaymentCheck: app.NewDefaultAppConfig().PaymentCheck}, simtestutil.EmptyAppOptions{}, options..., ) diff --git a/x/payment/keeper/stream_record.go b/x/payment/keeper/stream_record.go index be288b600..1fb01a63e 100644 --- a/x/payment/keeper/stream_record.go +++ b/x/payment/keeper/stream_record.go @@ -104,7 +104,7 @@ func (k Keeper) GetAllStreamRecord(ctx sdk.Context) (list []types.StreamRecord) for ; iterator.Valid(); iterator.Next() { var val types.StreamRecord k.cdc.MustUnmarshal(iterator.Value(), &val) - val.Account = string(iterator.Key()) + val.Account = sdk.AccAddress(iterator.Key()).String() list = append(list, val) } diff --git a/x/storage/keeper/abci.go b/x/storage/keeper/abci.go index 6ab311789..40cf51868 100644 --- a/x/storage/keeper/abci.go +++ b/x/storage/keeper/abci.go @@ -60,4 +60,13 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) { // Permission GC keeper.GarbageCollectResourcesStalePolicy(ctx) + + // Payment Data Check + interval := int64(keeper.GetPaymentCheckInterval()) + if keeper.IsPaymentCheckEnabled() && interval > 0 && ctx.BlockHeight()%interval == 0 { + err = keeper.RunPaymentCheck(ctx) + if err != nil { + panic(err) + } + } } diff --git a/x/storage/keeper/keeper.go b/x/storage/keeper/keeper.go index 3b30ff330..4d16b800c 100644 --- a/x/storage/keeper/keeper.go +++ b/x/storage/keeper/keeper.go @@ -46,9 +46,17 @@ type ( groupSeq sequence.Sequence[sdkmath.Uint] authority string + + // payment check config + cfg *paymentCheckConfig } ) +type paymentCheckConfig struct { + Enabled bool + Interval uint32 +} + func NewKeeper( cdc codec.BinaryCodec, storeKey storetypes.StoreKey, @@ -72,6 +80,7 @@ func NewKeeper( crossChainKeeper: crossChainKeeper, virtualGroupKeeper: virtualGroupKeeper, authority: authority, + cfg: &paymentCheckConfig{Enabled: false, Interval: 0}, } k.bucketSeq = sequence.NewSequence[sdkmath.Uint](types.BucketSequencePrefix) @@ -84,6 +93,14 @@ func (k Keeper) GetAuthority() string { return k.authority } +func (k Keeper) IsPaymentCheckEnabled() bool { + return k.cfg.Enabled +} + +func (k Keeper) GetPaymentCheckInterval() uint32 { + return k.cfg.Interval +} + func (k Keeper) Logger(ctx sdk.Context) log.Logger { return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) } diff --git a/x/storage/keeper/payment_check.go b/x/storage/keeper/payment_check.go new file mode 100644 index 000000000..96efe1891 --- /dev/null +++ b/x/storage/keeper/payment_check.go @@ -0,0 +1,283 @@ +package keeper + +import ( + sdkmath "cosmossdk.io/math" + "github.com/bnb-chain/greenfield/internal/sequence" + paymenttypes "github.com/bnb-chain/greenfield/x/payment/types" + "github.com/bnb-chain/greenfield/x/storage/types" + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/pkg/errors" +) + +// InitPaymentCheck initializes the payment check configuration. +func InitPaymentCheck(k Keeper, enabled bool, interval uint32) { + k.cfg.Enabled = enabled + k.cfg.Interval = interval +} + +// RunPaymentCheck checks the payment data of all buckets and objects. +// It will compare the lock balance, net flow rate of users and gvg families/gvgs/validator tax pool. +func (k Keeper) RunPaymentCheck(ctx sdk.Context) error { + ctx.Logger().Info("start checking payment data") + + type Detail struct { + address string + amount sdkmath.Int + } + + lockBalanceMap := make(map[string]sdkmath.Int) // payment address -> lock balance + lockBalanceDetailMap := make(map[string][]Detail) // payment address -> {bucket name, lock balance} + userFlowRateMap := make(map[string]sdkmath.Int) // payment address -> net flow rate + userFlowRateDetailMap := make(map[string][]Detail) // payment address -> {bucket name, net flow rate} + receiverFlowRateMap := make(map[string]sdkmath.Int) // gvg family/gvg/validator tax pool address -> net flow rate + receiverFlowRateDetailMap := make(map[string][]Detail) // gvg family/gvg/validator tax pool address -> {bucket name, net flow rate} + + store := ctx.KVStore(k.storeKey) + bucketStore := prefix.NewStore(store, types.BucketByIDPrefix) + bucketIt := bucketStore.Iterator(nil, nil) + defer bucketIt.Close() + + // cache all stream records to speed up + streamRecordMap := make(map[string]paymenttypes.StreamRecord) + allStreamRecords := k.paymentKeeper.GetAllStreamRecord(ctx) + for _, record := range allStreamRecords { + streamRecordMap[record.Account] = record + } + + var result error + +Exit: + for ; bucketIt.Valid(); bucketIt.Next() { + var bucket types.BucketInfo + k.cdc.MustUnmarshal(bucketIt.Value(), &bucket) + if bucket.Id.IsZero() { + continue + } + + // get net flow rate + internalBucketInfo, found := k.GetInternalBucketInfo(ctx, bucket.Id) + if !found { + result = errors.New("internal bucket info not found") + ctx.Logger().Error("internal bucket info not found", "bucket", bucket.BucketName) + continue Exit + } + userFlows, err := k.GetBucketReadStoreBill(ctx, &bucket, internalBucketInfo) + if err != nil { + result = errors.New("fail to get bucket read and store bill") + ctx.Logger().Error("fail to get bucket read and store bill", "bucket", bucket.BucketName, "error", err) + continue Exit + } + + rateLimited := false + paymentAddress := bucket.PaymentAddress + rateLimitStatus, found := k.getBucketFlowRateLimitStatus(ctx, bucket.BucketName) + if found { + rateLimited = rateLimitStatus.IsBucketLimited + paymentAddress = rateLimitStatus.PaymentAddress + } + + if len(userFlows.Flows) > 0 && !rateLimited { // if rate limited, there should not payment bills + expectedNetFlowRate := sdkmath.ZeroInt() + for _, flow := range userFlows.Flows { + expectedNetFlowRate = expectedNetFlowRate.Add(flow.Rate) + // gvg family/gvg/validator tax pool + _, ok := receiverFlowRateMap[flow.ToAddress] + if !ok { + receiverFlowRateMap[flow.ToAddress] = sdkmath.ZeroInt() + receiverFlowRateDetailMap[flow.ToAddress] = []Detail{} + } + receiverFlowRateMap[flow.ToAddress] = receiverFlowRateMap[flow.ToAddress].Add(flow.Rate) + receiverFlowRateDetailMap[flow.ToAddress] = append(receiverFlowRateDetailMap[flow.ToAddress], + Detail{bucket.BucketName, flow.Rate}) + } + + // user payment account + expectedNetFlowRate = expectedNetFlowRate.Neg() + _, ok := userFlowRateMap[paymentAddress] + if !ok { + userFlowRateMap[paymentAddress] = sdkmath.ZeroInt() + userFlowRateDetailMap[paymentAddress] = []Detail{} + } + userFlowRateMap[paymentAddress] = userFlowRateMap[paymentAddress].Add(expectedNetFlowRate) + userFlowRateDetailMap[paymentAddress] = append(userFlowRateDetailMap[paymentAddress], + Detail{bucket.BucketName, expectedNetFlowRate}) + } + + // get lock balance + objectPrefixStore := prefix.NewStore(store, types.GetObjectKeyOnlyBucketPrefix(bucket.BucketName)) + it := objectPrefixStore.Iterator(nil, nil) + defer it.Close() + + expectedLockBalance := sdkmath.ZeroInt() + for ; it.Valid(); it.Next() { + u256Seq := sequence.Sequence[sdkmath.Uint]{} + objectInfo, found := k.GetObjectInfoById(ctx, u256Seq.DecodeSequence(it.Value())) + if found && (objectInfo.ObjectStatus == types.OBJECT_STATUS_CREATED || objectInfo.IsUpdating) { + priceTime := objectInfo.CreateAt + payloadSize := objectInfo.PayloadSize + if objectInfo.IsUpdating { + shadowObject, found := k.GetShadowObjectInfo(ctx, bucket.BucketName, objectInfo.ObjectName) + if !found { + result = errors.New("shadow object not found") + ctx.Logger().Error("shadow object not found", "bucket", bucket.BucketName, "object", objectInfo.ObjectName) + continue Exit + } + priceTime = shadowObject.UpdatedAt + payloadSize = shadowObject.PayloadSize + } + + lockAmount, _, err := k.GetObjectLockFee(ctx, priceTime, payloadSize) + if err != nil { + result = errors.New("get object lock fee failed") + ctx.Logger().Error("get object lock fee failed", "bucket", bucket.BucketName, "object", objectInfo.ObjectName, "error", err) + continue Exit + } + expectedLockBalance = expectedLockBalance.Add(lockAmount) + } + } + + if expectedLockBalance.IsPositive() { + _, ok := lockBalanceMap[bucket.PaymentAddress] + if !ok { + lockBalanceMap[bucket.PaymentAddress] = sdkmath.ZeroInt() + lockBalanceDetailMap[bucket.PaymentAddress] = []Detail{} + } + lockBalanceMap[bucket.PaymentAddress] = lockBalanceMap[bucket.PaymentAddress].Add(expectedLockBalance) + lockBalanceDetailMap[bucket.PaymentAddress] = append(lockBalanceDetailMap[bucket.PaymentAddress], + Detail{bucket.BucketName, expectedLockBalance}) + } + } + + if result != nil { // if already has error, do not check the following + ctx.Logger().Info("stop checking payment data due to error") + return result + } + + // compare lock balance: expected -> actual side + for address, expectedLockBalance := range lockBalanceMap { + streamRecord, found := streamRecordMap[address] + if !found { + result = errors.New("comparing lock balance - stream record not found") + ctx.Logger().Error("comparing lock balance - stream record not found", "address", address) + continue // to print all errors if there are any + } + + actualLockBalance := streamRecord.LockBalance + if !expectedLockBalance.Equal(actualLockBalance) { + result = errors.New("lock balance not equal") + ctx.Logger().Error("lock balance not equal", "address", address, "expected", expectedLockBalance, "actual", actualLockBalance) + details := lockBalanceDetailMap[address] + for _, detail := range details { + ctx.Logger().Error("lock balance detail", "bucket", detail.address, "amount", detail.amount) + } + } + } + + // compare user net flow rate: expected -> actual side + frozenReceiverFlowRateMap := make(map[string]sdkmath.Int) + for address, expectedNetFlowRate := range userFlowRateMap { + streamRecord, found := streamRecordMap[address] + if !found { + result = errors.New("comparing user net flow rate - stream record not found") + ctx.Logger().Error("comparing user net flow rate - stream record not found", "address", address) + continue // to print all errors if there are any + } + + actualNetFlowRate := streamRecord.NetflowRate + if streamRecord.Status == paymenttypes.STREAM_ACCOUNT_STATUS_FROZEN { + actualNetFlowRate = actualNetFlowRate.Add(streamRecord.FrozenNetflowRate) + + // be noted, payment outflows can be in different status even if the stream account is frozen, + // for we are force settling a stream account in multiple blocks + outFlows := k.paymentKeeper.GetOutFlows(ctx, sdk.MustAccAddressFromHex(address)) + for _, outFlow := range outFlows { + if outFlow.Status == paymenttypes.OUT_FLOW_STATUS_FROZEN { + _, ok := frozenReceiverFlowRateMap[outFlow.ToAddress] + if !ok { + frozenReceiverFlowRateMap[outFlow.ToAddress] = sdkmath.ZeroInt() + } + frozenReceiverFlowRateMap[outFlow.ToAddress] = frozenReceiverFlowRateMap[outFlow.ToAddress].Add(outFlow.Rate) + } + } + } + + if actualNetFlowRate.IsNegative() && streamRecord.OutFlowCount <= 0 { + result = errors.New("user net flow rate invalid status or out flow count") + ctx.Logger().Error("user net flow rate invalid flow rate or out flow count", + "address", address, "status", actualNetFlowRate, "outflow count", streamRecord.OutFlowCount) + } + + if !expectedNetFlowRate.Equal(actualNetFlowRate) { + result = errors.New("user net flow rate not equal") + ctx.Logger().Error("user net flow rate not equal", "address", address, "expected", expectedNetFlowRate, "actual", actualNetFlowRate) + details := userFlowRateDetailMap[address] + for _, detail := range details { + ctx.Logger().Error("user net flow rate detail", "bucket", detail.address, "amount", detail.amount) + } + } + } + + // compare receiver net flow rate: expected -> actual side + for address, expectedNetFlowRate := range receiverFlowRateMap { + streamRecord, found := streamRecordMap[address] + if !found { + result = errors.New("comparing receiver net flow rate - stream record not found") + ctx.Logger().Error("comparing receiver net flow rate - stream record not found", "address", address) + continue // to print all errors if there are any + } + + if streamRecord.Status == paymenttypes.STREAM_ACCOUNT_STATUS_FROZEN || streamRecord.OutFlowCount > 0 { + result = errors.New("receiver net flow rate invalid status or out flow count") + ctx.Logger().Error("receiver net flow rate invalid status or out flow count", + "address", address, "status", streamRecord.Status, "outflow count", streamRecord.OutFlowCount) + } + + actualNetFlowRate := streamRecord.NetflowRate + frozenRate, ok := frozenReceiverFlowRateMap[address] + if ok { + actualNetFlowRate = actualNetFlowRate.Add(frozenRate) + } + + if !expectedNetFlowRate.Equal(actualNetFlowRate) { + result = errors.New("receiver net flow rate not equal") + ctx.Logger().Error("receiver net flow rate not equal", "address", address, "expected", expectedNetFlowRate, "actual", actualNetFlowRate) + details := receiverFlowRateDetailMap[address] + for _, detail := range details { + ctx.Logger().Error("receiver net flow rate detail", "bucket", detail.address, "amount", detail.amount) + } + } + } + + // compare lock balance: actual -> expected side + // compare user net flow rate: actual -> expected side + // compare receiver net flow rate: actual -> expected side + for _, streamRecord := range streamRecordMap { + if streamRecord.LockBalance.IsPositive() { + _, found := lockBalanceMap[streamRecord.Account] + if !found { + result = errors.New("the stream record has lock balance which is not expected") + ctx.Logger().Error("the stream record has lock balance which is not expected", "address", streamRecord.Account) + } + } + + if streamRecord.NetflowRate.IsNegative() || streamRecord.FrozenNetflowRate.IsNegative() { + _, found := userFlowRateMap[streamRecord.Account] + if !found { + result = errors.New("the stream record has negative flow rate which is not expected") + ctx.Logger().Error("the stream record has negative flow rate which is not expected", "address", streamRecord.Account) + } + } + + if streamRecord.NetflowRate.IsPositive() { + _, found := receiverFlowRateMap[streamRecord.Account] + if !found { + result = errors.New("the stream record has positive flow rate which is not expected") + ctx.Logger().Error("the stream record has positive flow rate which is not expected", "address", streamRecord.Account) + } + } + } + + ctx.Logger().Info("finish checking payment data") + return result +} diff --git a/x/storage/types/expected_keepers.go b/x/storage/types/expected_keepers.go index 890758c6b..5cddd04ae 100644 --- a/x/storage/types/expected_keepers.go +++ b/x/storage/types/expected_keepers.go @@ -50,6 +50,8 @@ type PaymentKeeper interface { UpdateStreamRecordByAddr(ctx sdk.Context, change *paymenttypes.StreamRecordChange) (ret *paymenttypes.StreamRecord, err error) GetStreamRecord(ctx sdk.Context, account sdk.AccAddress) (ret *paymenttypes.StreamRecord, found bool) MergeOutFlows(flows []paymenttypes.OutFlow) []paymenttypes.OutFlow + GetAllStreamRecord(ctx sdk.Context) (list []paymenttypes.StreamRecord) + GetOutFlows(ctx sdk.Context, addr sdk.AccAddress) []paymenttypes.OutFlow } type PermissionKeeper interface { diff --git a/x/storage/types/expected_keepers_mocks.go b/x/storage/types/expected_keepers_mocks.go index ff4f05972..67aae3609 100644 --- a/x/storage/types/expected_keepers_mocks.go +++ b/x/storage/types/expected_keepers_mocks.go @@ -5,6 +5,7 @@ package types import ( + context "context" big "math/big" reflect "reflect" time "time" @@ -300,6 +301,34 @@ func (mr *MockPaymentKeeperMockRecorder) ApplyUserFlowsList(ctx, userFlows inter return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ApplyUserFlowsList", reflect.TypeOf((*MockPaymentKeeper)(nil).ApplyUserFlowsList), ctx, userFlows) } +// GetAllStreamRecord mocks base method. +func (m *MockPaymentKeeper) GetAllStreamRecord(ctx types3.Context) []types.StreamRecord { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetAllStreamRecord", ctx) + ret0, _ := ret[0].([]types.StreamRecord) + return ret0 +} + +// GetAllStreamRecord indicates an expected call of GetAllStreamRecord. +func (mr *MockPaymentKeeperMockRecorder) GetAllStreamRecord(ctx interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllStreamRecord", reflect.TypeOf((*MockPaymentKeeper)(nil).GetAllStreamRecord), ctx) +} + +// GetOutFlows mocks base method. +func (m *MockPaymentKeeper) GetOutFlows(ctx types3.Context, addr types3.AccAddress) []types.OutFlow { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetOutFlows", ctx, addr) + ret0, _ := ret[0].([]types.OutFlow) + return ret0 +} + +// GetOutFlows indicates an expected call of GetOutFlows. +func (mr *MockPaymentKeeperMockRecorder) GetOutFlows(ctx, addr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetOutFlows", reflect.TypeOf((*MockPaymentKeeper)(nil).GetOutFlows), ctx, addr) +} + // GetStreamRecord mocks base method. func (m *MockPaymentKeeper) GetStreamRecord(ctx types3.Context, account types3.AccAddress) (*types.StreamRecord, bool) { m.ctrl.T.Helper() @@ -1164,3 +1193,244 @@ func (mr *MockStorageKeeperMockRecorder) ValidatePrincipal(ctx, resOwner, princi mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidatePrincipal", reflect.TypeOf((*MockStorageKeeper)(nil).ValidatePrincipal), ctx, resOwner, principal) } + +// MockPaymentMsgServer is a mock of PaymentMsgServer interface. +type MockPaymentMsgServer struct { + ctrl *gomock.Controller + recorder *MockPaymentMsgServerMockRecorder +} + +// MockPaymentMsgServerMockRecorder is the mock recorder for MockPaymentMsgServer. +type MockPaymentMsgServerMockRecorder struct { + mock *MockPaymentMsgServer +} + +// NewMockPaymentMsgServer creates a new mock instance. +func NewMockPaymentMsgServer(ctrl *gomock.Controller) *MockPaymentMsgServer { + mock := &MockPaymentMsgServer{ctrl: ctrl} + mock.recorder = &MockPaymentMsgServerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockPaymentMsgServer) EXPECT() *MockPaymentMsgServerMockRecorder { + return m.recorder +} + +// CreatePaymentAccount mocks base method. +func (m *MockPaymentMsgServer) CreatePaymentAccount(arg0 context.Context, arg1 *types.MsgCreatePaymentAccount) (*types.MsgCreatePaymentAccountResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreatePaymentAccount", arg0, arg1) + ret0, _ := ret[0].(*types.MsgCreatePaymentAccountResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreatePaymentAccount indicates an expected call of CreatePaymentAccount. +func (mr *MockPaymentMsgServerMockRecorder) CreatePaymentAccount(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreatePaymentAccount", reflect.TypeOf((*MockPaymentMsgServer)(nil).CreatePaymentAccount), arg0, arg1) +} + +// Deposit mocks base method. +func (m *MockPaymentMsgServer) Deposit(arg0 context.Context, arg1 *types.MsgDeposit) (*types.MsgDepositResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Deposit", arg0, arg1) + ret0, _ := ret[0].(*types.MsgDepositResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Deposit indicates an expected call of Deposit. +func (mr *MockPaymentMsgServerMockRecorder) Deposit(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Deposit", reflect.TypeOf((*MockPaymentMsgServer)(nil).Deposit), arg0, arg1) +} + +// DisableRefund mocks base method. +func (m *MockPaymentMsgServer) DisableRefund(arg0 context.Context, arg1 *types.MsgDisableRefund) (*types.MsgDisableRefundResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DisableRefund", arg0, arg1) + ret0, _ := ret[0].(*types.MsgDisableRefundResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DisableRefund indicates an expected call of DisableRefund. +func (mr *MockPaymentMsgServerMockRecorder) DisableRefund(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DisableRefund", reflect.TypeOf((*MockPaymentMsgServer)(nil).DisableRefund), arg0, arg1) +} + +// Withdraw mocks base method. +func (m *MockPaymentMsgServer) Withdraw(arg0 context.Context, arg1 *types.MsgWithdraw) (*types.MsgWithdrawResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Withdraw", arg0, arg1) + ret0, _ := ret[0].(*types.MsgWithdrawResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Withdraw indicates an expected call of Withdraw. +func (mr *MockPaymentMsgServerMockRecorder) Withdraw(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Withdraw", reflect.TypeOf((*MockPaymentMsgServer)(nil).Withdraw), arg0, arg1) +} + +// MockStorageMsgServer is a mock of StorageMsgServer interface. +type MockStorageMsgServer struct { + ctrl *gomock.Controller + recorder *MockStorageMsgServerMockRecorder +} + +// MockStorageMsgServerMockRecorder is the mock recorder for MockStorageMsgServer. +type MockStorageMsgServerMockRecorder struct { + mock *MockStorageMsgServer +} + +// NewMockStorageMsgServer creates a new mock instance. +func NewMockStorageMsgServer(ctrl *gomock.Controller) *MockStorageMsgServer { + mock := &MockStorageMsgServer{ctrl: ctrl} + mock.recorder = &MockStorageMsgServerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockStorageMsgServer) EXPECT() *MockStorageMsgServerMockRecorder { + return m.recorder +} + +// CancelMigrateBucket mocks base method. +func (m *MockStorageMsgServer) CancelMigrateBucket(arg0 context.Context, arg1 *MsgCancelMigrateBucket) (*MsgCancelMigrateBucketResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CancelMigrateBucket", arg0, arg1) + ret0, _ := ret[0].(*MsgCancelMigrateBucketResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CancelMigrateBucket indicates an expected call of CancelMigrateBucket. +func (mr *MockStorageMsgServerMockRecorder) CancelMigrateBucket(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CancelMigrateBucket", reflect.TypeOf((*MockStorageMsgServer)(nil).CancelMigrateBucket), arg0, arg1) +} + +// CopyObject mocks base method. +func (m *MockStorageMsgServer) CopyObject(arg0 context.Context, arg1 *MsgCopyObject) (*MsgCopyObjectResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CopyObject", arg0, arg1) + ret0, _ := ret[0].(*MsgCopyObjectResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CopyObject indicates an expected call of CopyObject. +func (mr *MockStorageMsgServerMockRecorder) CopyObject(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CopyObject", reflect.TypeOf((*MockStorageMsgServer)(nil).CopyObject), arg0, arg1) +} + +// MigrateBucket mocks base method. +func (m *MockStorageMsgServer) MigrateBucket(arg0 context.Context, arg1 *MsgMigrateBucket) (*MsgMigrateBucketResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "MigrateBucket", arg0, arg1) + ret0, _ := ret[0].(*MsgMigrateBucketResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// MigrateBucket indicates an expected call of MigrateBucket. +func (mr *MockStorageMsgServerMockRecorder) MigrateBucket(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MigrateBucket", reflect.TypeOf((*MockStorageMsgServer)(nil).MigrateBucket), arg0, arg1) +} + +// SetBucketFlowRateLimit mocks base method. +func (m *MockStorageMsgServer) SetBucketFlowRateLimit(arg0 context.Context, arg1 *MsgSetBucketFlowRateLimit) (*MsgSetBucketFlowRateLimitResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SetBucketFlowRateLimit", arg0, arg1) + ret0, _ := ret[0].(*MsgSetBucketFlowRateLimitResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// SetBucketFlowRateLimit indicates an expected call of SetBucketFlowRateLimit. +func (mr *MockStorageMsgServerMockRecorder) SetBucketFlowRateLimit(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetBucketFlowRateLimit", reflect.TypeOf((*MockStorageMsgServer)(nil).SetBucketFlowRateLimit), arg0, arg1) +} + +// SetTag mocks base method. +func (m *MockStorageMsgServer) SetTag(arg0 context.Context, arg1 *MsgSetTag) (*MsgSetTagResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SetTag", arg0, arg1) + ret0, _ := ret[0].(*MsgSetTagResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// SetTag indicates an expected call of SetTag. +func (mr *MockStorageMsgServerMockRecorder) SetTag(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetTag", reflect.TypeOf((*MockStorageMsgServer)(nil).SetTag), arg0, arg1) +} + +// ToggleSPAsDelegatedAgent mocks base method. +func (m *MockStorageMsgServer) ToggleSPAsDelegatedAgent(arg0 context.Context, arg1 *MsgToggleSPAsDelegatedAgent) (*MsgToggleSPAsDelegatedAgentResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ToggleSPAsDelegatedAgent", arg0, arg1) + ret0, _ := ret[0].(*MsgToggleSPAsDelegatedAgentResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ToggleSPAsDelegatedAgent indicates an expected call of ToggleSPAsDelegatedAgent. +func (mr *MockStorageMsgServerMockRecorder) ToggleSPAsDelegatedAgent(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ToggleSPAsDelegatedAgent", reflect.TypeOf((*MockStorageMsgServer)(nil).ToggleSPAsDelegatedAgent), arg0, arg1) +} + +// UpdateBucketInfo mocks base method. +func (m *MockStorageMsgServer) UpdateBucketInfo(arg0 context.Context, arg1 *MsgUpdateBucketInfo) (*MsgUpdateBucketInfoResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateBucketInfo", arg0, arg1) + ret0, _ := ret[0].(*MsgUpdateBucketInfoResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateBucketInfo indicates an expected call of UpdateBucketInfo. +func (mr *MockStorageMsgServerMockRecorder) UpdateBucketInfo(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateBucketInfo", reflect.TypeOf((*MockStorageMsgServer)(nil).UpdateBucketInfo), arg0, arg1) +} + +// UpdateGroupExtra mocks base method. +func (m *MockStorageMsgServer) UpdateGroupExtra(arg0 context.Context, arg1 *MsgUpdateGroupExtra) (*MsgUpdateGroupExtraResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateGroupExtra", arg0, arg1) + ret0, _ := ret[0].(*MsgUpdateGroupExtraResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateGroupExtra indicates an expected call of UpdateGroupExtra. +func (mr *MockStorageMsgServerMockRecorder) UpdateGroupExtra(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateGroupExtra", reflect.TypeOf((*MockStorageMsgServer)(nil).UpdateGroupExtra), arg0, arg1) +} + +// UpdateObjectInfo mocks base method. +func (m *MockStorageMsgServer) UpdateObjectInfo(arg0 context.Context, arg1 *MsgUpdateObjectInfo) (*MsgUpdateObjectInfoResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateObjectInfo", arg0, arg1) + ret0, _ := ret[0].(*MsgUpdateObjectInfoResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateObjectInfo indicates an expected call of UpdateObjectInfo. +func (mr *MockStorageMsgServerMockRecorder) UpdateObjectInfo(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateObjectInfo", reflect.TypeOf((*MockStorageMsgServer)(nil).UpdateObjectInfo), arg0, arg1) +}