github.com/lino-network/lino@v0.6.11/app/app_test.go (about)

     1  //nolint:deadcode,unused
     2  package app
     3  
     4  import (
     5  	"encoding/json"
     6  	"os"
     7  	"strconv"
     8  	"testing"
     9  	"time"
    10  
    11  	wire "github.com/cosmos/cosmos-sdk/codec"
    12  	sdk "github.com/cosmos/cosmos-sdk/types"
    13  	"github.com/stretchr/testify/assert"
    14  	abci "github.com/tendermint/tendermint/abci/types"
    15  	crypto "github.com/tendermint/tendermint/crypto"
    16  	"github.com/tendermint/tendermint/crypto/secp256k1"
    17  	"github.com/tendermint/tendermint/libs/log"
    18  	dbm "github.com/tendermint/tm-db"
    19  
    20  	"github.com/lino-network/lino/param"
    21  	"github.com/lino-network/lino/types"
    22  	votemodel "github.com/lino-network/lino/x/vote/model"
    23  )
    24  
    25  var (
    26  	user1 = "validator0"
    27  	priv1 = secp256k1.GenPrivKey()
    28  	addr1 = priv1.PubKey().Address()
    29  	priv2 = secp256k1.GenPrivKey()
    30  	addr2 = priv2.PubKey().Address()
    31  
    32  	genesisTotalCoin    = types.NewCoinFromInt64(2100000000 * types.Decimals)
    33  	coinPerValidator    = types.NewCoinFromInt64(100000000 * types.Decimals)
    34  	growthRate          = types.NewDecFromRat(98, 1000)
    35  	validatorAllocation = types.NewDecFromRat(5, 100)
    36  )
    37  
    38  func loggerAndDB() (logger log.Logger, db dbm.DB) {
    39  	logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "lino/app")
    40  	db = dbm.NewMemDB()
    41  	return
    42  }
    43  
    44  func newLinoBlockchain(t *testing.T, numOfValidators int) *LinoBlockchain {
    45  	logger, db := loggerAndDB()
    46  	lb := NewLinoBlockchain(logger, db, nil)
    47  
    48  	genesisState := GenesisState{
    49  		GenesisPools: GenesisPools{
    50  			Pools: []GenesisPool{
    51  				{Name: types.InflationDeveloperPool},
    52  				{Name: types.InflationValidatorPool},
    53  				{Name: types.InflationConsumptionPool},
    54  				{Name: types.VoteStakeInPool},
    55  				{Name: types.VoteStakeReturnPool},
    56  				{Name: types.VoteFrictionPool},
    57  				{
    58  					Name: types.DevIDAReservePool,
    59  				},
    60  				{
    61  					Name:   types.AccountVestingPool,
    62  					Amount: genesisTotalCoin,
    63  				},
    64  			},
    65  			Total: genesisTotalCoin,
    66  		},
    67  		InitCoinPrice: types.NewMiniDollar(1200),
    68  		Accounts:      []GenesisAccount{},
    69  	}
    70  
    71  	// Generate 21 validators
    72  	genesisAcc := GenesisAccount{
    73  		Name:        user1,
    74  		Coin:        coinPerValidator,
    75  		TxKey:       priv1.PubKey(),
    76  		SignKey:     secp256k1.GenPrivKey().PubKey(),
    77  		IsValidator: true,
    78  		ValPubKey:   priv2.PubKey(),
    79  	}
    80  	genesisState.Accounts = append(genesisState.Accounts, genesisAcc)
    81  	for i := 1; i < numOfValidators; i++ {
    82  		genesisAcc := GenesisAccount{
    83  			Name:        "validator" + strconv.Itoa(i),
    84  			Coin:        coinPerValidator,
    85  			TxKey:       secp256k1.GenPrivKey().PubKey(),
    86  			SignKey:     secp256k1.GenPrivKey().PubKey(),
    87  			IsValidator: true,
    88  			ValPubKey:   secp256k1.GenPrivKey().PubKey(),
    89  		}
    90  		genesisState.Accounts = append(genesisState.Accounts, genesisAcc)
    91  	}
    92  	result, err := wire.MarshalJSONIndent(lb.cdc, genesisState)
    93  	assert.Nil(t, err)
    94  
    95  	lb.InitChain(abci.RequestInitChain{
    96  		Time:          time.Unix(0, 0),
    97  		AppStateBytes: json.RawMessage(result),
    98  	})
    99  	lb.BeginBlock(abci.RequestBeginBlock{
   100  		Header: abci.Header{Height: 1, ChainID: "Lino", Time: time.Unix(0, 0)}})
   101  	lb.EndBlock(abci.RequestEndBlock{})
   102  	lb.Commit()
   103  	return lb
   104  }
   105  
   106  func TestGenesisAcc(t *testing.T) {
   107  	logger, db := loggerAndDB()
   108  	lb := NewLinoBlockchain(logger, db, nil)
   109  
   110  	accs := []struct {
   111  		genesisAccountName string
   112  		coin               types.Coin
   113  		resetKey           crypto.PubKey
   114  		transactionKey     crypto.PubKey
   115  		isValidator        bool
   116  		valPubKey          crypto.PubKey
   117  	}{
   118  		{"lino", types.NewCoinFromInt64(9000000 * types.Decimals),
   119  			secp256k1.GenPrivKey().PubKey(), secp256k1.GenPrivKey().PubKey(),
   120  			true, secp256k1.GenPrivKey().PubKey()},
   121  		{"genesis", types.NewCoinFromInt64(50000000 * types.Decimals),
   122  			secp256k1.GenPrivKey().PubKey(), secp256k1.GenPrivKey().PubKey(),
   123  			true, secp256k1.GenPrivKey().PubKey()},
   124  		{"nonvalidator", types.NewCoinFromInt64(500 * types.Decimals),
   125  			secp256k1.GenPrivKey().PubKey(), secp256k1.GenPrivKey().PubKey(),
   126  			false, secp256k1.GenPrivKey().PubKey()},
   127  		{"developer", types.NewCoinFromInt64(5000 * types.Decimals),
   128  			secp256k1.GenPrivKey().PubKey(), secp256k1.GenPrivKey().PubKey(),
   129  			false, secp256k1.GenPrivKey().PubKey()},
   130  	}
   131  	genesisState := GenesisState{
   132  		GenesisPools: GenesisPools{
   133  			Pools: []GenesisPool{
   134  				{Name: types.InflationDeveloperPool},
   135  				{Name: types.InflationValidatorPool},
   136  				{Name: types.InflationConsumptionPool},
   137  				{Name: types.VoteStakeInPool},
   138  				{Name: types.VoteStakeReturnPool},
   139  				{Name: types.VoteFrictionPool},
   140  				{
   141  					Name:   types.DevIDAReservePool,
   142  					Amount: types.MustLinoToCoin("2000000000"),
   143  				},
   144  				{
   145  					Name:   types.AccountVestingPool,
   146  					Amount: types.MustLinoToCoin("8000000000"),
   147  				},
   148  			},
   149  			Total: types.MustLinoToCoin("10000000000"),
   150  		},
   151  		InitCoinPrice: types.NewMiniDollar(1200),
   152  		Accounts:      []GenesisAccount{},
   153  	}
   154  	for _, acc := range accs {
   155  		genesisAcc := GenesisAccount{
   156  			Name:        acc.genesisAccountName,
   157  			Coin:        acc.coin,
   158  			TxKey:       acc.resetKey,
   159  			SignKey:     acc.transactionKey,
   160  			IsValidator: acc.isValidator,
   161  			ValPubKey:   acc.valPubKey,
   162  		}
   163  		genesisState.Accounts = append(genesisState.Accounts, genesisAcc)
   164  	}
   165  	// TODO(yumin): add developer genesis test back.
   166  	// genesisAppDeveloper := GenesisAppDeveloper{
   167  	// 	Name:        "developer",
   168  	// 	Deposit:     types.NewCoinFromInt64(1000000 * types.Decimals),
   169  	// 	Website:     "https://lino.network/",
   170  	// 	Description: "",
   171  	// 	AppMetaData: "",
   172  	// }
   173  	// genesisState.Developers = append(genesisState.Developers, genesisAppDeveloper)
   174  	result, err := wire.MarshalJSONIndent(lb.cdc, genesisState)
   175  	assert.Nil(t, err)
   176  
   177  	lb.InitChain(abci.RequestInitChain{AppStateBytes: json.RawMessage(result)})
   178  	lb.Commit()
   179  
   180  	ctx := lb.BaseApp.NewContext(true, abci.Header{})
   181  	for _, acc := range accs {
   182  		expectBalance := acc.coin
   183  		if acc.isValidator {
   184  			param := lb.paramHolder.GetValidatorParam(ctx)
   185  			expectBalance = expectBalance.Minus(param.ValidatorMinDeposit)
   186  		}
   187  		if acc.genesisAccountName == "developer" {
   188  			param, _ := lb.paramHolder.GetDeveloperParam(ctx)
   189  			expectBalance = expectBalance.Minus(param.DeveloperMinDeposit)
   190  			// TODO(yumin): add developer genesis test back.
   191  			continue
   192  		}
   193  		saving, err :=
   194  			lb.accountManager.GetSavingFromUsername(ctx, types.AccountKey(acc.genesisAccountName))
   195  		assert.Nil(t, err)
   196  		assert.Equal(
   197  			t, expectBalance, saving,
   198  			"account %s saving is %s, expect is %s, struct: %+v", acc.genesisAccountName, saving.String(), expectBalance.String(), acc)
   199  	}
   200  }
   201  
   202  func TestGenesisFromConfig(t *testing.T) {
   203  	logger, db := loggerAndDB()
   204  	lb := NewLinoBlockchain(logger, db, nil)
   205  	genesisState := GenesisState{
   206  		GenesisPools: GenesisPools{
   207  			Pools: []GenesisPool{
   208  				{Name: types.InflationDeveloperPool},
   209  				{Name: types.InflationValidatorPool},
   210  				{Name: types.InflationConsumptionPool},
   211  				{Name: types.VoteStakeInPool},
   212  				{Name: types.VoteStakeReturnPool},
   213  				{Name: types.VoteFrictionPool},
   214  				{
   215  					Name:   types.DevIDAReservePool,
   216  					Amount: types.MustLinoToCoin("2000000000"),
   217  				},
   218  				{
   219  					Name:   types.AccountVestingPool,
   220  					Amount: types.MustLinoToCoin("8000000000"),
   221  				},
   222  			},
   223  			Total: types.MustLinoToCoin("10000000000"),
   224  		},
   225  		InitCoinPrice: types.NewMiniDollar(1200),
   226  		Accounts:      []GenesisAccount{},
   227  	}
   228  	genesisState.GenesisParam = GenesisParam{
   229  		true,
   230  		param.GlobalAllocationParam{
   231  			GlobalGrowthRate:         types.NewDecFromRat(98, 1000),
   232  			ContentCreatorAllocation: types.NewDecFromRat(85, 100),
   233  			DeveloperAllocation:      types.NewDecFromRat(10, 100),
   234  			ValidatorAllocation:      types.NewDecFromRat(5, 100),
   235  		},
   236  		param.VoteParam{
   237  			MinStakeIn:                     types.NewCoinFromInt64(1000 * types.Decimals),
   238  			VoterCoinReturnIntervalSec:     int64(7 * 24 * 3600),
   239  			VoterCoinReturnTimes:           int64(7),
   240  			DelegatorCoinReturnIntervalSec: int64(7 * 24 * 3600),
   241  			DelegatorCoinReturnTimes:       int64(7),
   242  		},
   243  		param.ProposalParam{
   244  			ContentCensorshipDecideSec:  int64(24 * 7 * 3600),
   245  			ContentCensorshipPassRatio:  types.NewDecFromRat(50, 100),
   246  			ContentCensorshipPassVotes:  types.NewCoinFromInt64(10000 * types.Decimals),
   247  			ContentCensorshipMinDeposit: types.NewCoinFromInt64(100 * types.Decimals),
   248  
   249  			ChangeParamDecideSec:  int64(24 * 7 * 3600),
   250  			ChangeParamPassRatio:  types.NewDecFromRat(70, 100),
   251  			ChangeParamPassVotes:  types.NewCoinFromInt64(1000000 * types.Decimals),
   252  			ChangeParamMinDeposit: types.NewCoinFromInt64(100000 * types.Decimals),
   253  
   254  			ProtocolUpgradeDecideSec:  int64(24 * 7 * 3600),
   255  			ProtocolUpgradePassRatio:  types.NewDecFromRat(80, 100),
   256  			ProtocolUpgradePassVotes:  types.NewCoinFromInt64(10000000 * types.Decimals),
   257  			ProtocolUpgradeMinDeposit: types.NewCoinFromInt64(1000000 * types.Decimals),
   258  		},
   259  		param.DeveloperParam{
   260  			DeveloperMinDeposit:            types.NewCoinFromInt64(1000000 * types.Decimals),
   261  			DeveloperCoinReturnIntervalSec: int64(7 * 24 * 3600),
   262  			DeveloperCoinReturnTimes:       int64(7),
   263  		},
   264  		param.ValidatorParam{
   265  			ValidatorMinDeposit:            types.NewCoinFromInt64(200000 * types.Decimals),
   266  			ValidatorCoinReturnIntervalSec: int64(7 * 24 * 3600),
   267  			ValidatorCoinReturnTimes:       int64(7),
   268  			PenaltyMissCommit:              types.NewCoinFromInt64(200 * types.Decimals),
   269  			PenaltyByzantine:               types.NewCoinFromInt64(1000 * types.Decimals),
   270  			AbsentCommitLimitation:         int64(600), // 30min
   271  			OncallSize:                     int64(22),
   272  			StandbySize:                    int64(7),
   273  			ValidatorRevokePendingSec:      int64(7 * 24 * 3600),
   274  			OncallInflationWeight:          int64(2),
   275  			StandbyInflationWeight:         int64(1),
   276  			MaxVotedValidators:             int64(3),
   277  			SlashLimitation:                int64(5),
   278  		},
   279  		param.CoinDayParam{
   280  			SecondsToRecoverCoinDay: int64(7 * 24 * 3600),
   281  		},
   282  		param.BandwidthParam{
   283  			SecondsToRecoverBandwidth:   int64(7 * 24 * 3600),
   284  			CapacityUsagePerTransaction: types.NewCoinFromInt64(1 * types.Decimals),
   285  			VirtualCoin:                 types.NewCoinFromInt64(1 * types.Decimals),
   286  			GeneralMsgQuotaRatio:        types.NewDecFromRat(20, 100),
   287  			GeneralMsgEMAFactor:         types.NewDecFromRat(1, 10),
   288  			AppMsgQuotaRatio:            types.NewDecFromRat(80, 100),
   289  			AppMsgEMAFactor:             types.NewDecFromRat(1, 10),
   290  			ExpectedMaxMPS:              types.NewDecFromRat(1000, 1),
   291  			MsgFeeFactorA:               types.NewDecFromRat(6, 1),
   292  			MsgFeeFactorB:               types.NewDecFromRat(10, 1),
   293  			MaxMPSDecayRate:             types.NewDecFromRat(99, 100),
   294  			AppBandwidthPoolSize:        types.NewDecFromRat(10, 1),
   295  			AppVacancyFactor:            types.NewDecFromRat(69, 100),
   296  			AppPunishmentFactor:         types.NewDecFromRat(14, 5),
   297  		},
   298  		param.AccountParam{
   299  			MinimumBalance:               types.NewCoinFromInt64(1 * types.Decimals),
   300  			RegisterFee:                  types.NewCoinFromInt64(0),
   301  			FirstDepositFullCoinDayLimit: types.NewCoinFromInt64(0),
   302  			MaxNumFrozenMoney:            10,
   303  		},
   304  		param.PostParam{
   305  			ReportOrUpvoteIntervalSec: 24 * 3600,
   306  			PostIntervalSec:           600,
   307  			MaxReportReputation:       types.NewCoinFromInt64(100 * types.Decimals),
   308  		},
   309  		param.ReputationParam{
   310  			BestContentIndexN: 200,
   311  			UserMaxN:          50,
   312  		},
   313  		param.PriceParam{
   314  			TestnetMode:     true,
   315  			UpdateEverySec:  int64(time.Hour.Seconds()),
   316  			FeedEverySec:    int64((10 * time.Minute).Seconds()),
   317  			HistoryMaxLen:   71,
   318  			PenaltyMissFeed: types.NewCoinFromInt64(10000 * types.Decimals),
   319  		},
   320  	}
   321  	result, err := wire.MarshalJSONIndent(lb.cdc, genesisState)
   322  	assert.Nil(t, err)
   323  
   324  	lb.InitChain(abci.RequestInitChain{AppStateBytes: json.RawMessage(result)})
   325  	lb.Commit()
   326  	assert.True(t, genesisState.GenesisParam.InitFromConfig)
   327  	ctx := lb.BaseApp.NewContext(true, abci.Header{})
   328  	accParam := lb.paramHolder.GetAccountParam(ctx)
   329  	assert.Equal(t, genesisState.GenesisParam.AccountParam, *accParam)
   330  	postParam, err := lb.paramHolder.GetPostParam(ctx)
   331  	assert.Nil(t, err)
   332  	assert.Equal(t, genesisState.GenesisParam.PostParam, *postParam)
   333  	bandwidthParam, err := lb.paramHolder.GetBandwidthParam(ctx)
   334  	assert.Nil(t, err)
   335  	assert.Equal(t, genesisState.GenesisParam.BandwidthParam, *bandwidthParam)
   336  	coinDayParam, err := lb.paramHolder.GetCoinDayParam(ctx)
   337  	assert.Nil(t, err)
   338  	assert.Equal(t, genesisState.GenesisParam.CoinDayParam, *coinDayParam)
   339  	validatorParam := lb.paramHolder.GetValidatorParam(ctx)
   340  	assert.Equal(t, genesisState.GenesisParam.ValidatorParam, *validatorParam)
   341  	voteParam := lb.paramHolder.GetVoteParam(ctx)
   342  	assert.Equal(t, genesisState.GenesisParam.VoteParam, *voteParam)
   343  	proposalParam, err := lb.paramHolder.GetProposalParam(ctx)
   344  	assert.Nil(t, err)
   345  	assert.Equal(t, genesisState.GenesisParam.ProposalParam, *proposalParam)
   346  	globalParam := lb.paramHolder.GetGlobalAllocationParam(ctx)
   347  	assert.Equal(t, genesisState.GenesisParam.GlobalAllocationParam, *globalParam)
   348  }
   349  
   350  func TestDistributeInflationToValidators(t *testing.T) {
   351  	lb := newLinoBlockchain(t, 21)
   352  
   353  	ctx := lb.BaseApp.NewContext(true, abci.Header{ChainID: "Lino", Time: time.Unix(0, 0)})
   354  	remainValidatorPool := types.DecToCoin(
   355  		genesisTotalCoin.ToDec().Mul(
   356  			growthRate.Mul(validatorAllocation)))
   357  	param := lb.paramHolder.GetValidatorParam(ctx)
   358  
   359  	expectBaseBalance := coinPerValidator.Minus(param.ValidatorMinDeposit)
   360  	expectBalanceList := make([]types.Coin, 21)
   361  	for i := 0; i < len(expectBalanceList); i++ {
   362  		expectBalanceList[i] = expectBaseBalance
   363  	}
   364  	ctx = ctx.WithBlockTime(time.Unix(3600, 0))
   365  	err := lb.accountManager.Mint(ctx)
   366  	if err != nil {
   367  		panic(err)
   368  	}
   369  	if err := lb.valManager.DistributeInflationToValidator(ctx); err != nil {
   370  		panic(err)
   371  	}
   372  	// simulate app
   373  	// hourly inflation
   374  	inflationForValidator :=
   375  		types.DecToCoin(remainValidatorPool.ToDec().Mul(
   376  			types.NewDecFromRat(1, types.HoursPerYear)))
   377  	// expectBalance for all validators
   378  	for i := 0; i < 21; i++ {
   379  		inflation := types.DecToCoin(
   380  			inflationForValidator.ToDec().Quo(sdk.NewDec(int64(21 - i))))
   381  		expectBalanceList[i] = expectBalanceList[i].Plus(inflation)
   382  		inflationForValidator = inflationForValidator.Minus(inflation)
   383  		saving, err :=
   384  			lb.accountManager.GetSavingFromUsername(
   385  				ctx, types.AccountKey("validator"+strconv.Itoa(i)))
   386  		assert.Nil(t, err)
   387  		assert.Equal(t, expectBalanceList[i], saving)
   388  	}
   389  }
   390  
   391  func TestFireByzantineValidators(t *testing.T) {
   392  	lb := newLinoBlockchain(t, 21)
   393  	lb.BeginBlock(abci.RequestBeginBlock{
   394  		Header: abci.Header{
   395  			Height:  lb.LastBlockHeight() + 1,
   396  			ChainID: "Lino", Time: time.Unix(1, 0)},
   397  		ByzantineValidators: []abci.Evidence{
   398  			{
   399  				Validator: abci.Validator{
   400  					Address: priv2.PubKey().Address(),
   401  					Power:   1000,
   402  				},
   403  			},
   404  		},
   405  	})
   406  	lb.EndBlock(abci.RequestEndBlock{})
   407  	lb.Commit()
   408  	ctx := lb.BaseApp.NewContext(true, abci.Header{ChainID: "Lino", Time: time.Unix(1, 0)})
   409  	lst := lb.valManager.GetValidatorList(ctx)
   410  	assert.Equal(t, 20, len(lst.Oncall)+len(lst.Standby))
   411  }
   412  
   413  // TODO(yumin):
   414  // This testcase only covers that the pool is distributed to empty, but the amount
   415  // is not checked.
   416  func TestDistributeInflationToValidator(t *testing.T) {
   417  	lb := newLinoBlockchain(t, 21)
   418  	cases := map[string]struct {
   419  		beforeDistributionInflationPool types.Coin
   420  		pastMinutes                     int64
   421  	}{
   422  		"first distribution": {
   423  			beforeDistributionInflationPool: types.NewCoinFromInt64(1000 * types.Decimals),
   424  			pastMinutes:                     types.MinutesPerMonth,
   425  		},
   426  		"last distribution of first year": {
   427  			beforeDistributionInflationPool: types.NewCoinFromInt64(1000 * types.Decimals),
   428  			pastMinutes:                     types.MinutesPerMonth * 12,
   429  		},
   430  		"first distribution of second year": {
   431  			beforeDistributionInflationPool: types.NewCoinFromInt64(1000 * types.Decimals),
   432  			pastMinutes:                     types.MinutesPerMonth * 13,
   433  		},
   434  		"last distribution of second year": {
   435  			beforeDistributionInflationPool: types.NewCoinFromInt64(1000 * types.Decimals),
   436  			pastMinutes:                     types.MinutesPerMonth * 24,
   437  		},
   438  	}
   439  	for testName, cs := range cases {
   440  		ctx := lb.BaseApp.NewContext(true, abci.Header{})
   441  		ctx = ctx.WithBlockTime(time.Unix(cs.pastMinutes*60, 0))
   442  
   443  		if err := lb.valManager.DistributeInflationToValidator(ctx); err != nil {
   444  			t.Errorf("%s: failed to set inflation pool, got err %v", testName, err)
   445  		}
   446  		inflationPool, err := lb.accountManager.GetPool(ctx, types.InflationValidatorPool)
   447  		if err != nil {
   448  			t.Errorf("%s: failed to get inflation pool, got err %v", testName, err)
   449  		}
   450  		if !inflationPool.IsZero() {
   451  			t.Errorf(
   452  				"%s: diff validator inflation pool, got %v, want %v",
   453  				testName, inflationPool,
   454  				types.NewCoinFromInt64(0))
   455  			return
   456  		}
   457  	}
   458  }
   459  
   460  func TestHourlyInflation(t *testing.T) {
   461  	lb := newLinoBlockchain(t, 21)
   462  	ctx := lb.BaseApp.NewContext(true, abci.Header{Time: time.Unix(0, 0)})
   463  	ph := param.NewParamHolder(lb.CapKeyParamStore)
   464  	globalAllocation := ph.GetGlobalAllocationParam(ctx)
   465  
   466  	expectConsumptionPool := types.NewCoinFromInt64(0)
   467  	lb.globalManager.OnBeginBlock(ctx) // initialize genesis.
   468  	for i := 1; i <= types.MinutesPerMonth/10; i++ {
   469  		supply := lb.accountManager.GetSupply(ctx)
   470  		ctx = lb.BaseApp.NewContext(true, abci.Header{Time: time.Unix(int64(i*60), 0)})
   471  		// functhat that handles previous hourly inflation.
   472  		if i%60 == 0 {
   473  			lb.globalManager.OnBeginBlock(ctx)
   474  			hourlyInflation :=
   475  				types.DecToCoin(
   476  					supply.LastYearTotal.ToDec().
   477  						Mul(globalAllocation.GlobalGrowthRate).Mul(
   478  						types.NewDecFromRat(1, types.HoursPerYear)))
   479  			expectConsumptionPool =
   480  				expectConsumptionPool.Plus(
   481  					types.DecToCoin(hourlyInflation.ToDec().Mul(
   482  						globalAllocation.ContentCreatorAllocation)))
   483  			cPool, err := lb.accountManager.GetPool(ctx, types.InflationConsumptionPool)
   484  			assert.Nil(t, err)
   485  			assert.Equal(t, expectConsumptionPool, cPool)
   486  
   487  			vPool, err := lb.accountManager.GetPool(ctx, types.InflationValidatorPool)
   488  			assert.Nil(t, err)
   489  			assert.Equal(t, types.NewCoinFromInt64(0), vPool)
   490  		}
   491  	}
   492  }
   493  
   494  func TestDailyEvents(t *testing.T) {
   495  	lb := newLinoBlockchain(t, 21)
   496  	ctx := lb.BaseApp.NewContext(true, abci.Header{})
   497  	validatorParam := lb.paramHolder.GetValidatorParam(ctx)
   498  	minVotingDeposit, _ := validatorParam.ValidatorMinDeposit.ToInt64()
   499  	initStake := minVotingDeposit * 21
   500  	expectLinoStakeStat := votemodel.LinoStakeStat{
   501  		TotalConsumptionFriction: types.NewCoinFromInt64(0),
   502  		TotalLinoStake:           types.NewCoinFromInt64(initStake),
   503  		UnclaimedFriction:        types.NewCoinFromInt64(0),
   504  		UnclaimedLinoStake:       types.NewCoinFromInt64(initStake),
   505  	}
   506  	// user1 := linotypes.AccoutKey("user1")
   507  	// lb.accountManager.RegisterAccount(ctx, linotypes.NewAccOrAddrFromAcc(""))
   508  	for i := 1; i < types.MinutesPerMonth/10; i++ {
   509  		newStakein := types.MustLinoToCoin("1000")
   510  		// simulate add lino stake and friction at previous block
   511  		ctx := lb.BaseApp.NewContext(true, abci.Header{Time: time.Unix(int64((i-1)*60), 0)})
   512  		err := lb.voteManager.StakeIn(ctx, types.AccountKey(user1), newStakein)
   513  		if err != nil {
   514  			panic(err)
   515  		}
   516  		err = lb.voteManager.RecordFriction(ctx, types.NewCoinFromInt64(2))
   517  		if err != nil {
   518  			panic(err)
   519  		}
   520  		expectLinoStakeStat.TotalConsumptionFriction =
   521  			expectLinoStakeStat.TotalConsumptionFriction.Plus(types.NewCoinFromInt64(2))
   522  		expectLinoStakeStat.UnclaimedFriction =
   523  			expectLinoStakeStat.UnclaimedFriction.Plus(types.NewCoinFromInt64(2))
   524  		expectLinoStakeStat.TotalLinoStake =
   525  			expectLinoStakeStat.TotalLinoStake.Plus(newStakein)
   526  		expectLinoStakeStat.UnclaimedLinoStake =
   527  			expectLinoStakeStat.UnclaimedLinoStake.Plus(newStakein)
   528  
   529  		// increase minutes after previous block finished
   530  		ctx = lb.BaseApp.NewContext(true, abci.Header{Time: time.Unix(int64(i*60), 0)})
   531  		lb.globalManager.OnBeginBlock(ctx) // initialize genesis.
   532  		// fixhere: execute events
   533  		if i%(60*24) == 0 {
   534  			linoStakeStat, err := lb.voteManager.GetStakeStatsOfDay(ctx, int64(i/(60*24)))
   535  			assert.Nil(t, err)
   536  			assert.Equal(t, linoStakeStat.TotalConsumptionFriction, types.NewCoinFromInt64(0))
   537  			assert.Equal(t, linoStakeStat.UnclaimedFriction, types.NewCoinFromInt64(0))
   538  			assert.Equal(t, linoStakeStat.TotalLinoStake, expectLinoStakeStat.TotalLinoStake)
   539  			assert.Equal(t, linoStakeStat.UnclaimedLinoStake, expectLinoStakeStat.UnclaimedLinoStake)
   540  			linoStakeStat, err = lb.voteManager.GetStakeStatsOfDay(ctx, int64(i/(60*24)-1))
   541  			assert.Nil(t, err)
   542  			assert.Equal(t, linoStakeStat.TotalConsumptionFriction, expectLinoStakeStat.TotalConsumptionFriction)
   543  			assert.Equal(t, linoStakeStat.UnclaimedFriction, expectLinoStakeStat.UnclaimedFriction)
   544  			assert.Equal(t, linoStakeStat.TotalLinoStake, expectLinoStakeStat.TotalLinoStake)
   545  			assert.Equal(t, linoStakeStat.UnclaimedLinoStake, expectLinoStakeStat.UnclaimedLinoStake)
   546  			expectLinoStakeStat.TotalConsumptionFriction = types.NewCoinFromInt64(0)
   547  			expectLinoStakeStat.UnclaimedFriction = types.NewCoinFromInt64(0)
   548  
   549  		}
   550  	}
   551  }