github.com/Finschia/finschia-sdk@v0.48.1/x/gov/abci_test.go (about)

     1  package gov_test
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/stretchr/testify/require"
     8  	tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
     9  
    10  	ocabci "github.com/Finschia/ostracon/abci/types"
    11  
    12  	"github.com/Finschia/finschia-sdk/simapp"
    13  	sdk "github.com/Finschia/finschia-sdk/types"
    14  	"github.com/Finschia/finschia-sdk/x/gov"
    15  	"github.com/Finschia/finschia-sdk/x/gov/types"
    16  	"github.com/Finschia/finschia-sdk/x/staking"
    17  	"github.com/golang/protobuf/proto"
    18  )
    19  
    20  func TestTickExpiredDepositPeriod(t *testing.T) {
    21  	app := simapp.Setup(false)
    22  	ctx := app.BaseApp.NewContext(false, tmproto.Header{})
    23  	addrs := simapp.AddTestAddrs(app, ctx, 10, valTokens)
    24  
    25  	header := tmproto.Header{Height: app.LastBlockHeight() + 1}
    26  	app.BeginBlock(ocabci.RequestBeginBlock{Header: header})
    27  
    28  	govHandler := gov.NewHandler(app.GovKeeper)
    29  
    30  	inactiveQueue := app.GovKeeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
    31  	require.False(t, inactiveQueue.Valid())
    32  	inactiveQueue.Close()
    33  
    34  	newProposalMsg, err := types.NewMsgSubmitProposal(
    35  		types.ContentFromProposalType("test", "test", types.ProposalTypeText),
    36  		sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 5)},
    37  		addrs[0],
    38  	)
    39  	require.NoError(t, err)
    40  
    41  	res, err := govHandler(ctx, newProposalMsg)
    42  	require.NoError(t, err)
    43  	require.NotNil(t, res)
    44  
    45  	inactiveQueue = app.GovKeeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
    46  	require.False(t, inactiveQueue.Valid())
    47  	inactiveQueue.Close()
    48  
    49  	newHeader := ctx.BlockHeader()
    50  	newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second)
    51  	ctx = ctx.WithBlockHeader(newHeader)
    52  
    53  	inactiveQueue = app.GovKeeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
    54  	require.False(t, inactiveQueue.Valid())
    55  	inactiveQueue.Close()
    56  
    57  	newHeader = ctx.BlockHeader()
    58  	newHeader.Time = ctx.BlockHeader().Time.Add(app.GovKeeper.GetDepositParams(ctx).MaxDepositPeriod)
    59  	ctx = ctx.WithBlockHeader(newHeader)
    60  
    61  	inactiveQueue = app.GovKeeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
    62  	require.True(t, inactiveQueue.Valid())
    63  	inactiveQueue.Close()
    64  
    65  	gov.EndBlocker(ctx, app.GovKeeper)
    66  
    67  	inactiveQueue = app.GovKeeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
    68  	require.False(t, inactiveQueue.Valid())
    69  	inactiveQueue.Close()
    70  }
    71  
    72  func TestTickMultipleExpiredDepositPeriod(t *testing.T) {
    73  	app := simapp.Setup(false)
    74  	ctx := app.BaseApp.NewContext(false, tmproto.Header{})
    75  	addrs := simapp.AddTestAddrs(app, ctx, 10, valTokens)
    76  
    77  	header := tmproto.Header{Height: app.LastBlockHeight() + 1}
    78  	app.BeginBlock(ocabci.RequestBeginBlock{Header: header})
    79  
    80  	govHandler := gov.NewHandler(app.GovKeeper)
    81  
    82  	inactiveQueue := app.GovKeeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
    83  	require.False(t, inactiveQueue.Valid())
    84  	inactiveQueue.Close()
    85  
    86  	newProposalMsg, err := types.NewMsgSubmitProposal(
    87  		types.ContentFromProposalType("test", "test", types.ProposalTypeText),
    88  		sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 5)},
    89  		addrs[0],
    90  	)
    91  	require.NoError(t, err)
    92  
    93  	res, err := govHandler(ctx, newProposalMsg)
    94  	require.NoError(t, err)
    95  	require.NotNil(t, res)
    96  
    97  	inactiveQueue = app.GovKeeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
    98  	require.False(t, inactiveQueue.Valid())
    99  	inactiveQueue.Close()
   100  
   101  	newHeader := ctx.BlockHeader()
   102  	newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(2) * time.Second)
   103  	ctx = ctx.WithBlockHeader(newHeader)
   104  
   105  	inactiveQueue = app.GovKeeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
   106  	require.False(t, inactiveQueue.Valid())
   107  	inactiveQueue.Close()
   108  
   109  	newProposalMsg2, err := types.NewMsgSubmitProposal(
   110  		types.ContentFromProposalType("test2", "test2", types.ProposalTypeText),
   111  		sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 5)},
   112  		addrs[0],
   113  	)
   114  	require.NoError(t, err)
   115  
   116  	res, err = govHandler(ctx, newProposalMsg2)
   117  	require.NoError(t, err)
   118  	require.NotNil(t, res)
   119  
   120  	newHeader = ctx.BlockHeader()
   121  	newHeader.Time = ctx.BlockHeader().Time.Add(app.GovKeeper.GetDepositParams(ctx).MaxDepositPeriod).Add(time.Duration(-1) * time.Second)
   122  	ctx = ctx.WithBlockHeader(newHeader)
   123  
   124  	inactiveQueue = app.GovKeeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
   125  	require.True(t, inactiveQueue.Valid())
   126  	inactiveQueue.Close()
   127  
   128  	gov.EndBlocker(ctx, app.GovKeeper)
   129  
   130  	inactiveQueue = app.GovKeeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
   131  	require.False(t, inactiveQueue.Valid())
   132  	inactiveQueue.Close()
   133  
   134  	newHeader = ctx.BlockHeader()
   135  	newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(5) * time.Second)
   136  	ctx = ctx.WithBlockHeader(newHeader)
   137  
   138  	inactiveQueue = app.GovKeeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
   139  	require.True(t, inactiveQueue.Valid())
   140  	inactiveQueue.Close()
   141  
   142  	gov.EndBlocker(ctx, app.GovKeeper)
   143  
   144  	inactiveQueue = app.GovKeeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
   145  	require.False(t, inactiveQueue.Valid())
   146  	inactiveQueue.Close()
   147  }
   148  
   149  func TestTickPassedDepositPeriod(t *testing.T) {
   150  	app := simapp.Setup(false)
   151  	ctx := app.BaseApp.NewContext(false, tmproto.Header{})
   152  	addrs := simapp.AddTestAddrs(app, ctx, 10, valTokens)
   153  
   154  	header := tmproto.Header{Height: app.LastBlockHeight() + 1}
   155  	app.BeginBlock(ocabci.RequestBeginBlock{Header: header})
   156  
   157  	govHandler := gov.NewHandler(app.GovKeeper)
   158  
   159  	inactiveQueue := app.GovKeeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
   160  	require.False(t, inactiveQueue.Valid())
   161  	inactiveQueue.Close()
   162  	activeQueue := app.GovKeeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
   163  	require.False(t, activeQueue.Valid())
   164  	activeQueue.Close()
   165  
   166  	newProposalMsg, err := types.NewMsgSubmitProposal(
   167  		types.ContentFromProposalType("test2", "test2", types.ProposalTypeText),
   168  		sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 5)},
   169  		addrs[0],
   170  	)
   171  	require.NoError(t, err)
   172  
   173  	res, err := govHandler(ctx, newProposalMsg)
   174  	require.NoError(t, err)
   175  	require.NotNil(t, res)
   176  
   177  	var proposalData types.MsgSubmitProposalResponse
   178  	err = proto.Unmarshal(res.Data, &proposalData)
   179  	require.NoError(t, err)
   180  
   181  	proposalID := proposalData.ProposalId
   182  
   183  	inactiveQueue = app.GovKeeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
   184  	require.False(t, inactiveQueue.Valid())
   185  	inactiveQueue.Close()
   186  
   187  	newHeader := ctx.BlockHeader()
   188  	newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second)
   189  	ctx = ctx.WithBlockHeader(newHeader)
   190  
   191  	inactiveQueue = app.GovKeeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
   192  	require.False(t, inactiveQueue.Valid())
   193  	inactiveQueue.Close()
   194  
   195  	newDepositMsg := types.NewMsgDeposit(addrs[1], proposalID, sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 5)})
   196  
   197  	res, err = govHandler(ctx, newDepositMsg)
   198  	require.NoError(t, err)
   199  	require.NotNil(t, res)
   200  
   201  	activeQueue = app.GovKeeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
   202  	require.False(t, activeQueue.Valid())
   203  	activeQueue.Close()
   204  }
   205  
   206  func TestTickPassedVotingPeriod(t *testing.T) {
   207  	app := simapp.Setup(false)
   208  	ctx := app.BaseApp.NewContext(false, tmproto.Header{})
   209  	addrs := simapp.AddTestAddrs(app, ctx, 10, valTokens)
   210  
   211  	SortAddresses(addrs)
   212  
   213  	header := tmproto.Header{Height: app.LastBlockHeight() + 1}
   214  	app.BeginBlock(ocabci.RequestBeginBlock{Header: header})
   215  
   216  	govHandler := gov.NewHandler(app.GovKeeper)
   217  
   218  	inactiveQueue := app.GovKeeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
   219  	require.False(t, inactiveQueue.Valid())
   220  	inactiveQueue.Close()
   221  	activeQueue := app.GovKeeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
   222  	require.False(t, activeQueue.Valid())
   223  	activeQueue.Close()
   224  
   225  	proposalCoins := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, app.StakingKeeper.TokensFromConsensusPower(ctx, 5))}
   226  	newProposalMsg, err := types.NewMsgSubmitProposal(TestProposal, proposalCoins, addrs[0])
   227  	require.NoError(t, err)
   228  
   229  	res, err := govHandler(ctx, newProposalMsg)
   230  	require.NoError(t, err)
   231  	require.NotNil(t, res)
   232  
   233  	var proposalData types.MsgSubmitProposalResponse
   234  	err = proto.Unmarshal(res.Data, &proposalData)
   235  	require.NoError(t, err)
   236  
   237  	proposalID := proposalData.ProposalId
   238  
   239  	newHeader := ctx.BlockHeader()
   240  	newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second)
   241  	ctx = ctx.WithBlockHeader(newHeader)
   242  
   243  	newDepositMsg := types.NewMsgDeposit(addrs[1], proposalID, proposalCoins)
   244  
   245  	res, err = govHandler(ctx, newDepositMsg)
   246  	require.NoError(t, err)
   247  	require.NotNil(t, res)
   248  
   249  	newHeader = ctx.BlockHeader()
   250  	newHeader.Time = ctx.BlockHeader().Time.Add(app.GovKeeper.GetDepositParams(ctx).MaxDepositPeriod).Add(app.GovKeeper.GetVotingParams(ctx).VotingPeriod)
   251  	ctx = ctx.WithBlockHeader(newHeader)
   252  
   253  	inactiveQueue = app.GovKeeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
   254  	require.False(t, inactiveQueue.Valid())
   255  	inactiveQueue.Close()
   256  
   257  	activeQueue = app.GovKeeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
   258  	require.True(t, activeQueue.Valid())
   259  
   260  	activeProposalID := types.GetProposalIDFromBytes(activeQueue.Value())
   261  	proposal, ok := app.GovKeeper.GetProposal(ctx, activeProposalID)
   262  	require.True(t, ok)
   263  	require.Equal(t, types.StatusVotingPeriod, proposal.Status)
   264  
   265  	activeQueue.Close()
   266  
   267  	gov.EndBlocker(ctx, app.GovKeeper)
   268  
   269  	activeQueue = app.GovKeeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
   270  	require.False(t, activeQueue.Valid())
   271  	activeQueue.Close()
   272  }
   273  
   274  func TestProposalPassedEndblocker(t *testing.T) {
   275  	app := simapp.Setup(false)
   276  	ctx := app.BaseApp.NewContext(false, tmproto.Header{})
   277  	addrs := simapp.AddTestAddrs(app, ctx, 10, valTokens)
   278  
   279  	SortAddresses(addrs)
   280  
   281  	handler := gov.NewHandler(app.GovKeeper)
   282  	stakingHandler := staking.NewHandler(app.StakingKeeper)
   283  
   284  	header := tmproto.Header{Height: app.LastBlockHeight() + 1}
   285  	app.BeginBlock(ocabci.RequestBeginBlock{Header: header})
   286  
   287  	valAddr := sdk.ValAddress(addrs[0])
   288  
   289  	createValidators(t, stakingHandler, ctx, []sdk.ValAddress{valAddr}, []int64{10})
   290  	staking.EndBlocker(ctx, app.StakingKeeper)
   291  
   292  	macc := app.GovKeeper.GetGovernanceAccount(ctx)
   293  	require.NotNil(t, macc)
   294  	initialModuleAccCoins := app.BankKeeper.GetAllBalances(ctx, macc.GetAddress())
   295  
   296  	proposal, err := app.GovKeeper.SubmitProposal(ctx, TestProposal)
   297  	require.NoError(t, err)
   298  
   299  	proposalCoins := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, app.StakingKeeper.TokensFromConsensusPower(ctx, 10))}
   300  	newDepositMsg := types.NewMsgDeposit(addrs[0], proposal.ProposalId, proposalCoins)
   301  
   302  	handleAndCheck(t, handler, ctx, newDepositMsg)
   303  
   304  	macc = app.GovKeeper.GetGovernanceAccount(ctx)
   305  	require.NotNil(t, macc)
   306  	moduleAccCoins := app.BankKeeper.GetAllBalances(ctx, macc.GetAddress())
   307  
   308  	deposits := initialModuleAccCoins.Add(proposal.TotalDeposit...).Add(proposalCoins...)
   309  	require.True(t, moduleAccCoins.IsEqual(deposits))
   310  
   311  	err = app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[0], types.NewNonSplitVoteOption(types.OptionYes))
   312  	require.NoError(t, err)
   313  
   314  	newHeader := ctx.BlockHeader()
   315  	newHeader.Time = ctx.BlockHeader().Time.Add(app.GovKeeper.GetDepositParams(ctx).MaxDepositPeriod).Add(app.GovKeeper.GetVotingParams(ctx).VotingPeriod)
   316  	ctx = ctx.WithBlockHeader(newHeader)
   317  
   318  	gov.EndBlocker(ctx, app.GovKeeper)
   319  
   320  	macc = app.GovKeeper.GetGovernanceAccount(ctx)
   321  	require.NotNil(t, macc)
   322  	require.True(t, app.BankKeeper.GetAllBalances(ctx, macc.GetAddress()).IsEqual(initialModuleAccCoins))
   323  }
   324  
   325  func TestEndBlockerProposalHandlerFailed(t *testing.T) {
   326  	app := simapp.Setup(false)
   327  	ctx := app.BaseApp.NewContext(false, tmproto.Header{})
   328  	addrs := simapp.AddTestAddrs(app, ctx, 1, valTokens)
   329  
   330  	SortAddresses(addrs)
   331  
   332  	stakingHandler := staking.NewHandler(app.StakingKeeper)
   333  	header := tmproto.Header{Height: app.LastBlockHeight() + 1}
   334  	app.BeginBlock(ocabci.RequestBeginBlock{Header: header})
   335  
   336  	valAddr := sdk.ValAddress(addrs[0])
   337  
   338  	createValidators(t, stakingHandler, ctx, []sdk.ValAddress{valAddr}, []int64{10})
   339  	staking.EndBlocker(ctx, app.StakingKeeper)
   340  
   341  	// Create a proposal where the handler will pass for the test proposal
   342  	// because the value of contextKeyBadProposal is true.
   343  	ctx = ctx.WithValue(contextKeyBadProposal, true)
   344  	proposal, err := app.GovKeeper.SubmitProposal(ctx, TestProposal)
   345  	require.NoError(t, err)
   346  
   347  	proposalCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, app.StakingKeeper.TokensFromConsensusPower(ctx, 10)))
   348  	newDepositMsg := types.NewMsgDeposit(addrs[0], proposal.ProposalId, proposalCoins)
   349  
   350  	handleAndCheck(t, gov.NewHandler(app.GovKeeper), ctx, newDepositMsg)
   351  
   352  	err = app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[0], types.NewNonSplitVoteOption(types.OptionYes))
   353  	require.NoError(t, err)
   354  
   355  	newHeader := ctx.BlockHeader()
   356  	newHeader.Time = ctx.BlockHeader().Time.Add(app.GovKeeper.GetDepositParams(ctx).MaxDepositPeriod).Add(app.GovKeeper.GetVotingParams(ctx).VotingPeriod)
   357  	ctx = ctx.WithBlockHeader(newHeader)
   358  
   359  	// Set the contextKeyBadProposal value to false so that the handler will fail
   360  	// during the processing of the proposal in the EndBlocker.
   361  	ctx = ctx.WithValue(contextKeyBadProposal, false)
   362  
   363  	// validate that the proposal fails/has been rejected
   364  	gov.EndBlocker(ctx, app.GovKeeper)
   365  }