github.com/lino-network/lino@v0.6.11/x/bandwidth/manager/manager.go (about)

     1  package manager
     2  
     3  import (
     4  	sdk "github.com/cosmos/cosmos-sdk/types"
     5  	"github.com/cosmos/cosmos-sdk/x/auth"
     6  
     7  	"github.com/lino-network/lino/param"
     8  	linotypes "github.com/lino-network/lino/types"
     9  	account "github.com/lino-network/lino/x/account"
    10  	"github.com/lino-network/lino/x/bandwidth/model"
    11  	"github.com/lino-network/lino/x/bandwidth/types"
    12  	developer "github.com/lino-network/lino/x/developer"
    13  	global "github.com/lino-network/lino/x/global"
    14  	vote "github.com/lino-network/lino/x/vote"
    15  )
    16  
    17  var BandwidthManagerTestMode bool = false
    18  
    19  // BandwidthManager - bandwidth manager
    20  type BandwidthManager struct {
    21  	storage     model.BandwidthStorage
    22  	paramHolder param.ParamKeeper
    23  	// deps
    24  	gm global.GlobalKeeper
    25  	vm vote.VoteKeeper
    26  	dm developer.DeveloperKeeper
    27  	am account.AccountKeeper
    28  }
    29  
    30  func NewBandwidthManager(key sdk.StoreKey, holder param.ParamKeeper, gm global.GlobalKeeper, vm vote.VoteKeeper, dm developer.DeveloperKeeper, am account.AccountKeeper) *BandwidthManager {
    31  	return &BandwidthManager{
    32  		storage:     model.NewBandwidthStorage(key),
    33  		paramHolder: holder,
    34  		gm:          gm,
    35  		vm:          vm,
    36  		dm:          dm,
    37  		am:          am,
    38  	}
    39  }
    40  
    41  // InitGenesis - initialize KV Store
    42  func (bm BandwidthManager) InitGenesis(ctx sdk.Context) error {
    43  	bandwidthInfo := &model.BandwidthInfo{
    44  		GeneralMsgEMA: sdk.NewDec(0),
    45  		AppMsgEMA:     sdk.NewDec(0),
    46  		MaxMPS:        sdk.NewDec(0),
    47  	}
    48  
    49  	if err := bm.storage.SetBandwidthInfo(ctx, bandwidthInfo); err != nil {
    50  		return err
    51  	}
    52  
    53  	blockInfo := &model.BlockInfo{
    54  		TotalMsgSignedByApp:  0,
    55  		TotalMsgSignedByUser: 0,
    56  		CurMsgFee:            linotypes.NewCoinFromInt64(int64(0)),
    57  		CurU:                 sdk.NewDec(1),
    58  	}
    59  
    60  	if err := bm.storage.SetBlockInfo(ctx, blockInfo); err != nil {
    61  		return err
    62  	}
    63  	return nil
    64  }
    65  
    66  func (bm BandwidthManager) PrecheckAndConsumeBandwidthCredit(ctx sdk.Context, accKey linotypes.AccountKey) sdk.Error {
    67  	appBandwidthInfo, err := bm.storage.GetAppBandwidthInfo(ctx, accKey)
    68  	if err != nil {
    69  		return err
    70  	}
    71  
    72  	blockInfo, err := bm.storage.GetBlockInfo(ctx)
    73  	if err != nil {
    74  		return err
    75  	}
    76  	if appBandwidthInfo.CurBandwidthCredit.LT(blockInfo.CurU) {
    77  		return types.ErrAppBandwidthNotEnough()
    78  	}
    79  
    80  	// consume u at first
    81  	appBandwidthInfo.CurBandwidthCredit = appBandwidthInfo.CurBandwidthCredit.Sub(blockInfo.CurU)
    82  	if err := bm.storage.SetAppBandwidthInfo(ctx, accKey, appBandwidthInfo); err != nil {
    83  		return err
    84  	}
    85  	return nil
    86  }
    87  
    88  func (bm BandwidthManager) IsUserMsgFeeEnough(ctx sdk.Context, fee auth.StdFee) bool {
    89  	if !fee.Amount.IsValid() {
    90  		return false
    91  	}
    92  	providedFee := linotypes.NewCoinFromInt64(fee.Amount.AmountOf(linotypes.LinoCoinDenom).Int64())
    93  	info, err := bm.storage.GetBlockInfo(ctx)
    94  	if err != nil {
    95  		return false
    96  	}
    97  	return providedFee.IsGTE(info.CurMsgFee)
    98  }
    99  
   100  func (bm BandwidthManager) AddMsgSignedByApp(ctx sdk.Context, accKey linotypes.AccountKey, num int64) sdk.Error {
   101  	info, err := bm.storage.GetBlockInfo(ctx)
   102  	if err != nil {
   103  		return err
   104  	}
   105  	info.TotalMsgSignedByApp += num
   106  
   107  	if err := bm.storage.SetBlockInfo(ctx, info); err != nil {
   108  		return err
   109  	}
   110  
   111  	appBandwidthInfo, err := bm.storage.GetAppBandwidthInfo(ctx, accKey)
   112  	if err != nil {
   113  		return err
   114  	}
   115  	appBandwidthInfo.MessagesInCurBlock += 1
   116  	if err := bm.storage.SetAppBandwidthInfo(ctx, accKey, appBandwidthInfo); err != nil {
   117  		return err
   118  	}
   119  	return nil
   120  }
   121  
   122  func (bm BandwidthManager) AddMsgSignedByUser(ctx sdk.Context, num int64) sdk.Error {
   123  	info, err := bm.storage.GetBlockInfo(ctx)
   124  	if err != nil {
   125  		return err
   126  	}
   127  	info.TotalMsgSignedByUser += num
   128  
   129  	if err := bm.storage.SetBlockInfo(ctx, info); err != nil {
   130  		return err
   131  	}
   132  	return nil
   133  }
   134  
   135  func (bm BandwidthManager) ClearBlockInfo(ctx sdk.Context) sdk.Error {
   136  	info, err := bm.storage.GetBlockInfo(ctx)
   137  	if err != nil {
   138  		return err
   139  	}
   140  	info.TotalMsgSignedByUser = 0
   141  	info.TotalMsgSignedByApp = 0
   142  
   143  	if err := bm.storage.SetBlockInfo(ctx, info); err != nil {
   144  		return err
   145  	}
   146  	return nil
   147  }
   148  
   149  // calcuate the new EMA at the end of each block
   150  func (bm BandwidthManager) UpdateMaxMPSAndEMA(ctx sdk.Context) sdk.Error {
   151  	lastBlockTime := bm.gm.GetLastBlockTime(ctx)
   152  	if lastBlockTime >= ctx.BlockHeader().Time.Unix() {
   153  		return nil
   154  	}
   155  
   156  	bandwidthInfo, err := bm.storage.GetBandwidthInfo(ctx)
   157  	if err != nil {
   158  		return err
   159  	}
   160  
   161  	blockInfo, err := bm.storage.GetBlockInfo(ctx)
   162  	if err != nil {
   163  		return err
   164  	}
   165  
   166  	params, err := bm.paramHolder.GetBandwidthParam(ctx)
   167  	if err != nil {
   168  		return err
   169  	}
   170  
   171  	pastTime := ctx.BlockHeader().Time.Unix() - lastBlockTime
   172  
   173  	// EMA_general = EMA_general_prev * (1 - k_general) + generalMPS * k_general
   174  	generalMPS := linotypes.NewDecFromRat(blockInfo.TotalMsgSignedByUser, pastTime)
   175  	bandwidthInfo.GeneralMsgEMA = bm.calculateEMA(bandwidthInfo.GeneralMsgEMA, params.GeneralMsgEMAFactor, generalMPS)
   176  
   177  	// EMA_app = EMA_app_prev * (1 - k_app) + appMPS * k_app
   178  	appMPS := linotypes.NewDecFromRat(blockInfo.TotalMsgSignedByApp, pastTime)
   179  	bandwidthInfo.AppMsgEMA = bm.calculateEMA(bandwidthInfo.AppMsgEMA, params.AppMsgEMAFactor, appMPS)
   180  
   181  	// MaxMPS = max( (totalMsgSignedByUser + totalMsgSignedByApp)/(curBlockTime - lastBlockTime), MaxMPS)
   182  	totalMPS := linotypes.NewDecFromRat(blockInfo.TotalMsgSignedByUser+blockInfo.TotalMsgSignedByApp, pastTime)
   183  	if totalMPS.GT(bandwidthInfo.MaxMPS) {
   184  		bandwidthInfo.MaxMPS = totalMPS
   185  	}
   186  
   187  	if err := bm.storage.SetBandwidthInfo(ctx, bandwidthInfo); err != nil {
   188  		return err
   189  	}
   190  
   191  	return nil
   192  }
   193  
   194  // calcuate the current msg fee based on last block info at the beginning of each block
   195  func (bm BandwidthManager) CalculateCurMsgFee(ctx sdk.Context) sdk.Error {
   196  	params, err := bm.paramHolder.GetBandwidthParam(ctx)
   197  	if err != nil {
   198  		return err
   199  	}
   200  
   201  	bandwidthInfo, err := bm.storage.GetBandwidthInfo(ctx)
   202  	if err != nil {
   203  		return err
   204  	}
   205  
   206  	blockInfo, err := bm.storage.GetBlockInfo(ctx)
   207  	if err != nil {
   208  		return err
   209  	}
   210  
   211  	generalMsgQuota, err := bm.getGeneralMsgQuota(ctx)
   212  	if err != nil {
   213  		return err
   214  	}
   215  
   216  	expResult := bm.approximateExp(bandwidthInfo.GeneralMsgEMA.Sub(generalMsgQuota).Quo(generalMsgQuota).Mul(params.MsgFeeFactorA))
   217  	msgFeeLino := expResult.Mul(params.MsgFeeFactorB)
   218  	blockInfo.CurMsgFee = linotypes.NewCoinFromInt64(msgFeeLino.Mul(sdk.NewDec(linotypes.Decimals)).RoundInt64())
   219  
   220  	if err := bm.storage.SetBlockInfo(ctx, blockInfo); err != nil {
   221  		return err
   222  	}
   223  	return nil
   224  }
   225  
   226  // calcuate the current vacancy coeef u based on last block info at the beginning of each block
   227  func (bm BandwidthManager) CalculateCurU(ctx sdk.Context) sdk.Error {
   228  	bandwidthInfo, err := bm.storage.GetBandwidthInfo(ctx)
   229  	if err != nil {
   230  		return err
   231  	}
   232  
   233  	params, err := bm.paramHolder.GetBandwidthParam(ctx)
   234  	if err != nil {
   235  		return err
   236  	}
   237  
   238  	appMsgQuota, err := bm.getAppMsgQuota(ctx)
   239  	if err != nil {
   240  		return err
   241  	}
   242  
   243  	blockInfo, err := bm.storage.GetBlockInfo(ctx)
   244  	if err != nil {
   245  		return err
   246  	}
   247  
   248  	delta := bandwidthInfo.AppMsgEMA.Sub(appMsgQuota)
   249  	blockInfo.CurU = bm.approximateExp(delta.Quo(appMsgQuota).Mul(params.AppVacancyFactor))
   250  	if err := bm.storage.SetBlockInfo(ctx, blockInfo); err != nil {
   251  		return err
   252  	}
   253  	return nil
   254  }
   255  
   256  func (bm BandwidthManager) DecayMaxMPS(ctx sdk.Context) sdk.Error {
   257  	bandwidthInfo, err := bm.storage.GetBandwidthInfo(ctx)
   258  	if err != nil {
   259  		return err
   260  	}
   261  
   262  	params, err := bm.paramHolder.GetBandwidthParam(ctx)
   263  	if err != nil {
   264  		return err
   265  	}
   266  
   267  	bandwidthInfo.MaxMPS = bandwidthInfo.MaxMPS.Mul(params.MaxMPSDecayRate)
   268  	if err := bm.storage.SetBandwidthInfo(ctx, bandwidthInfo); err != nil {
   269  		return err
   270  	}
   271  	return nil
   272  }
   273  
   274  func (bm BandwidthManager) RefillAppBandwidthCredit(ctx sdk.Context, accKey linotypes.AccountKey) sdk.Error {
   275  	info, err := bm.storage.GetAppBandwidthInfo(ctx, accKey)
   276  	if err != nil {
   277  		return err
   278  	}
   279  
   280  	curTime := ctx.BlockHeader().Time.Unix()
   281  	if info.LastRefilledAt >= curTime {
   282  		return nil
   283  	}
   284  
   285  	if info.CurBandwidthCredit.GTE(info.MaxBandwidthCredit) {
   286  		return nil
   287  	}
   288  
   289  	pastSeconds := curTime - info.LastRefilledAt
   290  	// assume refill rate is equal to expectedMPS
   291  	newCredit := info.ExpectedMPS.Mul(sdk.NewDec(pastSeconds)).Add(info.CurBandwidthCredit)
   292  	if newCredit.GTE(info.MaxBandwidthCredit) {
   293  		info.CurBandwidthCredit = info.MaxBandwidthCredit
   294  	} else {
   295  		info.CurBandwidthCredit = newCredit
   296  	}
   297  	info.LastRefilledAt = curTime
   298  
   299  	if err := bm.storage.SetAppBandwidthInfo(ctx, accKey, info); err != nil {
   300  		return err
   301  	}
   302  	return nil
   303  }
   304  
   305  func (bm BandwidthManager) GetPunishmentCoeff(ctx sdk.Context, accKey linotypes.AccountKey) (sdk.Dec, sdk.Error) {
   306  	lastBlockTime := bm.gm.GetLastBlockTime(ctx)
   307  	pastTime := ctx.BlockHeader().Time.Unix() - lastBlockTime
   308  	if pastTime <= 0 {
   309  		return sdk.NewDec(1), nil
   310  	}
   311  	appInfo, err := bm.storage.GetAppBandwidthInfo(ctx, accKey)
   312  	if err != nil {
   313  		return sdk.NewDec(1), err
   314  	}
   315  	if !appInfo.ExpectedMPS.IsPositive() {
   316  		return sdk.NewDec(1), types.ErrInvalidExpectedMPS()
   317  	}
   318  
   319  	curMPS := linotypes.NewDecFromRat(appInfo.MessagesInCurBlock, pastTime)
   320  	delta := curMPS.Sub(appInfo.ExpectedMPS)
   321  	if delta.IsNegative() {
   322  		delta = sdk.NewDec(0)
   323  	}
   324  
   325  	params, err := bm.paramHolder.GetBandwidthParam(ctx)
   326  	if err != nil {
   327  		return sdk.NewDec(1), err
   328  	}
   329  	return bm.approximateExp(delta.Quo(appInfo.ExpectedMPS).Mul(params.AppPunishmentFactor)), nil
   330  }
   331  
   332  func (bm BandwidthManager) ConsumeBandwidthCredit(ctx sdk.Context, u sdk.Dec, p sdk.Dec, accKey linotypes.AccountKey) sdk.Error {
   333  	info, err := bm.storage.GetAppBandwidthInfo(ctx, accKey)
   334  	if err != nil {
   335  		return err
   336  	}
   337  	numMsgs := sdk.NewDec(info.MessagesInCurBlock)
   338  	// add back pre-check consumed bandwidth credit
   339  	info.CurBandwidthCredit = info.CurBandwidthCredit.Add(numMsgs.Mul(u))
   340  	// consume credit, currently allow the credit be negative
   341  	costPerMsg := bm.GetBandwidthCostPerMsg(ctx, u, p)
   342  	info.CurBandwidthCredit = info.CurBandwidthCredit.Sub(numMsgs.Mul(costPerMsg))
   343  	info.MessagesInCurBlock = 0
   344  	if err := bm.storage.SetAppBandwidthInfo(ctx, accKey, info); err != nil {
   345  		return err
   346  	}
   347  	return nil
   348  }
   349  
   350  func (bm BandwidthManager) ReCalculateAppBandwidthInfo(ctx sdk.Context) sdk.Error {
   351  	totalAppStakeCoin := linotypes.NewCoinFromInt64(0)
   352  	// calculate all app total stake
   353  	for _, app := range bm.dm.GetLiveDevelopers(ctx) {
   354  		appStakeCoin, err := bm.vm.GetLinoStake(ctx, app.Username)
   355  		if err != nil {
   356  			return err
   357  		}
   358  		totalAppStakeCoin = totalAppStakeCoin.Plus(appStakeCoin)
   359  	}
   360  
   361  	if !totalAppStakeCoin.IsPositive() {
   362  		return nil
   363  	}
   364  
   365  	// calculate all app MPS quota
   366  	appMsgQuota, err := bm.getAppMsgQuota(ctx)
   367  	if err != nil {
   368  		return err
   369  	}
   370  
   371  	// calculate each app's share and expected MPS
   372  	params, err := bm.paramHolder.GetBandwidthParam(ctx)
   373  	if err != nil {
   374  		return err
   375  	}
   376  
   377  	for _, app := range bm.dm.GetLiveDevelopers(ctx) {
   378  		appStakeCoin, err := bm.vm.GetLinoStake(ctx, app.Username)
   379  		if err != nil {
   380  			return err
   381  		}
   382  		appStakePct := appStakeCoin.ToDec().Quo(totalAppStakeCoin.ToDec())
   383  		expectedMPS := appMsgQuota.Mul(appStakePct)
   384  		maxBandwidthCredit := expectedMPS.Mul(params.AppBandwidthPoolSize)
   385  
   386  		// first time app, refill it's current pool to the full
   387  		if !bm.storage.DoesAppBandwidthInfoExist(ctx, app.Username) {
   388  			newAppInfo := model.AppBandwidthInfo{
   389  				Username:           app.Username,
   390  				MaxBandwidthCredit: maxBandwidthCredit,
   391  				CurBandwidthCredit: maxBandwidthCredit,
   392  				MessagesInCurBlock: 0,
   393  				ExpectedMPS:        expectedMPS,
   394  				LastRefilledAt:     ctx.BlockHeader().Time.Unix(),
   395  			}
   396  
   397  			if err := bm.storage.SetAppBandwidthInfo(ctx, app.Username, &newAppInfo); err != nil {
   398  				return err
   399  			}
   400  
   401  		} else {
   402  			// refill the bandwidth credit with old expectedMPS (refill rate)
   403  			if err := bm.RefillAppBandwidthCredit(ctx, app.Username); err != nil {
   404  				return err
   405  			}
   406  			// update it's max and expected MPS
   407  			info, err := bm.storage.GetAppBandwidthInfo(ctx, app.Username)
   408  			if err != nil {
   409  				return err
   410  			}
   411  			info.ExpectedMPS = expectedMPS
   412  			info.MaxBandwidthCredit = maxBandwidthCredit
   413  
   414  			if err := bm.storage.SetAppBandwidthInfo(ctx, app.Username, info); err != nil {
   415  				return err
   416  			}
   417  		}
   418  	}
   419  	return nil
   420  }
   421  
   422  func (bm BandwidthManager) CheckBandwidth(ctx sdk.Context, addr sdk.AccAddress, fee auth.StdFee) sdk.Error {
   423  	bank, err := bm.am.GetBankByAddress(ctx, addr)
   424  	if err != nil {
   425  		return err
   426  	}
   427  	if bank.Username != "" {
   428  		appName, err := bm.dm.GetAffiliatingApp(ctx, bank.Username)
   429  		if err == nil {
   430  			// refill bandwidth for apps with messages in current block
   431  			if err := bm.RefillAppBandwidthCredit(ctx, appName); err != nil {
   432  				return err
   433  			}
   434  
   435  			// app bandwidth model
   436  			if err := bm.PrecheckAndConsumeBandwidthCredit(ctx, appName); err != nil {
   437  				return err
   438  			}
   439  
   440  			// add app message stats
   441  			if err := bm.AddMsgSignedByApp(ctx, appName, 1); err != nil {
   442  				return err
   443  			}
   444  			return nil
   445  		}
   446  	}
   447  
   448  	// msg fee for general message
   449  	if !bm.IsUserMsgFeeEnough(ctx, fee) {
   450  		return types.ErrUserMsgFeeNotEnough()
   451  	}
   452  
   453  	// minus message fee
   454  	info, err := bm.storage.GetBlockInfo(ctx)
   455  	if err != nil {
   456  		return err
   457  	}
   458  
   459  	//  minus msg fee
   460  	if !BandwidthManagerTestMode {
   461  		err := bm.am.MoveToPool(ctx, linotypes.InflationValidatorPool,
   462  			linotypes.NewAccOrAddrFromAddr(addr), info.CurMsgFee)
   463  		if err != nil {
   464  			return err
   465  		}
   466  	}
   467  	// add general message stats
   468  	if err := bm.AddMsgSignedByUser(ctx, 1); err != nil {
   469  		return err
   470  	}
   471  
   472  	return nil
   473  }
   474  
   475  func (bm BandwidthManager) BeginBlocker(ctx sdk.Context) sdk.Error {
   476  	// calculate the new general msg fee for the current block
   477  	if err := bm.CalculateCurMsgFee(ctx); err != nil {
   478  		return err
   479  	}
   480  
   481  	// calculate the new vacancy coeff
   482  	if err := bm.CalculateCurU(ctx); err != nil {
   483  		return err
   484  	}
   485  
   486  	// clear stats for block info
   487  	if err := bm.ClearBlockInfo(ctx); err != nil {
   488  		return err
   489  	}
   490  	return nil
   491  }
   492  
   493  func (bm BandwidthManager) EndBlocker(ctx sdk.Context) sdk.Error {
   494  	// update maxMPS and EMA for different msgs and store cur block info
   495  	if err := bm.UpdateMaxMPSAndEMA(ctx); err != nil {
   496  		return err
   497  	}
   498  
   499  	blockInfo, err := bm.storage.GetBlockInfo(ctx)
   500  	if err != nil {
   501  		return err
   502  	}
   503  
   504  	// get all app bandwidth info
   505  	allInfo, err := bm.GetAllAppInfo(ctx)
   506  	if err != nil {
   507  		return err
   508  	}
   509  
   510  	for _, info := range allInfo {
   511  		if info.MessagesInCurBlock == 0 {
   512  			continue
   513  		}
   514  		// calculate cost and consume bandwidth credit
   515  		p, err := bm.GetPunishmentCoeff(ctx, info.Username)
   516  		if err != nil {
   517  			return err
   518  		}
   519  		if err := bm.ConsumeBandwidthCredit(ctx, blockInfo.CurU, p, info.Username); err != nil {
   520  			return err
   521  		}
   522  
   523  	}
   524  	return nil
   525  }
   526  
   527  func (bm BandwidthManager) GetBandwidthCostPerMsg(ctx sdk.Context, u sdk.Dec, p sdk.Dec) sdk.Dec {
   528  	return u.Mul(p)
   529  }
   530  
   531  func (bm BandwidthManager) GetAllAppInfo(ctx sdk.Context) ([]*model.AppBandwidthInfo, sdk.Error) {
   532  	return bm.storage.GetAllAppBandwidthInfo(ctx)
   533  }
   534  
   535  func (bm BandwidthManager) calculateEMA(prevEMA sdk.Dec, k sdk.Dec, curMPS sdk.Dec) sdk.Dec {
   536  	pre := prevEMA.Mul(sdk.NewDec(1).Sub(k))
   537  	cur := curMPS.Mul(k)
   538  	return pre.Add(cur)
   539  }
   540  
   541  func (bm BandwidthManager) approximateExp(x sdk.Dec) sdk.Dec {
   542  	prev := x
   543  	x = sdk.NewDec(1).Add(x.Abs().Quo(sdk.NewDec(1024)))
   544  	x = x.Mul(x)
   545  	x = x.Mul(x)
   546  	x = x.Mul(x)
   547  	x = x.Mul(x)
   548  	x = x.Mul(x)
   549  	x = x.Mul(x)
   550  	x = x.Mul(x)
   551  	x = x.Mul(x)
   552  	x = x.Mul(x)
   553  	x = x.Mul(x)
   554  
   555  	if prev.LT(sdk.NewDec(0)) {
   556  		return sdk.NewDec(1).Quo(x)
   557  	}
   558  	return x
   559  }
   560  
   561  func (bm BandwidthManager) getAppMsgQuota(ctx sdk.Context) (sdk.Dec, sdk.Error) {
   562  	bandwidthInfo, err := bm.storage.GetBandwidthInfo(ctx)
   563  	if err != nil {
   564  		return sdk.NewDec(1), err
   565  	}
   566  
   567  	params, err := bm.paramHolder.GetBandwidthParam(ctx)
   568  	if err != nil {
   569  		return sdk.NewDec(1), err
   570  	}
   571  
   572  	var curMaxMPS sdk.Dec
   573  	if params.ExpectedMaxMPS.GT(bandwidthInfo.MaxMPS) {
   574  		curMaxMPS = params.ExpectedMaxMPS
   575  	} else {
   576  		curMaxMPS = bandwidthInfo.MaxMPS
   577  	}
   578  
   579  	appMsgQuota := params.AppMsgQuotaRatio.Mul(curMaxMPS)
   580  	if !appMsgQuota.IsPositive() {
   581  		return sdk.NewDec(1), types.ErrInvalidMsgQuota()
   582  	}
   583  	return appMsgQuota, nil
   584  }
   585  
   586  func (bm BandwidthManager) getGeneralMsgQuota(ctx sdk.Context) (sdk.Dec, sdk.Error) {
   587  	bandwidthInfo, err := bm.storage.GetBandwidthInfo(ctx)
   588  	if err != nil {
   589  		return sdk.NewDec(1), err
   590  	}
   591  
   592  	params, err := bm.paramHolder.GetBandwidthParam(ctx)
   593  	if err != nil {
   594  		return sdk.NewDec(1), err
   595  	}
   596  
   597  	var curMaxMPS sdk.Dec
   598  	if params.ExpectedMaxMPS.GT(bandwidthInfo.MaxMPS) {
   599  		curMaxMPS = params.ExpectedMaxMPS
   600  	} else {
   601  		curMaxMPS = bandwidthInfo.MaxMPS
   602  	}
   603  
   604  	generalMsgQuota := params.GeneralMsgQuotaRatio.Mul(curMaxMPS)
   605  	if !generalMsgQuota.IsPositive() {
   606  		return sdk.NewDec(1), types.ErrInvalidMsgQuota()
   607  	}
   608  	return generalMsgQuota, nil
   609  }
   610  
   611  // getter
   612  func (bm BandwidthManager) GetBandwidthInfo(ctx sdk.Context) (*model.BandwidthInfo, sdk.Error) {
   613  	return bm.storage.GetBandwidthInfo(ctx)
   614  }
   615  
   616  func (bm BandwidthManager) GetBlockInfo(ctx sdk.Context) (*model.BlockInfo, sdk.Error) {
   617  	return bm.storage.GetBlockInfo(ctx)
   618  }
   619  
   620  func (bm BandwidthManager) GetAppBandwidthInfo(ctx sdk.Context, accKey linotypes.AccountKey) (*model.AppBandwidthInfo, sdk.Error) {
   621  	return bm.storage.GetAppBandwidthInfo(ctx, accKey)
   622  }