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

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