code.vegaprotocol.io/vega@v0.79.0/core/snapshot/helpers_for_test.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package snapshot_test
    17  
    18  import (
    19  	"testing"
    20  	"time"
    21  
    22  	"code.vegaprotocol.io/vega/core/types"
    23  	typemocks "code.vegaprotocol.io/vega/core/types/mocks"
    24  	"code.vegaprotocol.io/vega/libs/num"
    25  	"code.vegaprotocol.io/vega/libs/proto"
    26  	vgrand "code.vegaprotocol.io/vega/libs/rand"
    27  
    28  	cometbftdb "github.com/cometbft/cometbft-db"
    29  	"github.com/cosmos/iavl"
    30  	"github.com/golang/mock/gomock"
    31  	"github.com/stretchr/testify/require"
    32  )
    33  
    34  type snapshotForTest struct {
    35  	snapshot   *types.Snapshot
    36  	appState   *types.AppState
    37  	byteChunks [][]byte
    38  	rawChunks  []*types.RawChunk
    39  	payloads   []*types.Payload
    40  }
    41  
    42  func (s *snapshotForTest) PayloadGovernanceActive() *types.Payload {
    43  	for _, payload := range s.payloads {
    44  		switch payload.Data.(type) {
    45  		case *types.PayloadGovernanceActive:
    46  			return payload
    47  		}
    48  	}
    49  
    50  	return nil
    51  }
    52  
    53  func (s *snapshotForTest) PayloadGovernanceEnacted() *types.Payload {
    54  	for _, payload := range s.payloads {
    55  		switch payload.Data.(type) {
    56  		case *types.PayloadGovernanceEnacted:
    57  			return payload
    58  		}
    59  	}
    60  
    61  	return nil
    62  }
    63  
    64  func (s *snapshotForTest) PayloadDelegationActive() *types.Payload {
    65  	for _, payload := range s.payloads {
    66  		switch payload.Data.(type) {
    67  		case *types.PayloadDelegationActive:
    68  			return payload
    69  		}
    70  	}
    71  
    72  	return nil
    73  }
    74  
    75  func (s *snapshotForTest) PayloadEpoch() *types.Payload {
    76  	for _, payload := range s.payloads {
    77  		switch payload.Data.(type) {
    78  		case *types.PayloadEpoch:
    79  			return payload
    80  		}
    81  	}
    82  
    83  	return nil
    84  }
    85  
    86  func newEpochProvider(t *testing.T, ctrl *gomock.Controller) *typemocks.MockStateProvider {
    87  	t.Helper()
    88  
    89  	epochProvider := typemocks.NewMockStateProvider(ctrl)
    90  	epochProvider.EXPECT().Namespace().Return(types.SnapshotNamespace("epoch")).AnyTimes()
    91  	epochProvider.EXPECT().Keys().Return([]string{"all"}).AnyTimes()
    92  	epochProvider.EXPECT().Stopped().Return(false).AnyTimes()
    93  	return epochProvider
    94  }
    95  
    96  func newDelegationProvider(t *testing.T, ctrl *gomock.Controller) *typemocks.MockStateProvider {
    97  	t.Helper()
    98  
    99  	delegationProvider := typemocks.NewMockStateProvider(ctrl)
   100  	delegationProvider.EXPECT().Namespace().Return(types.SnapshotNamespace("delegation")).AnyTimes()
   101  	delegationProvider.EXPECT().Keys().Return([]string{"active"}).AnyTimes()
   102  	delegationProvider.EXPECT().Stopped().Return(false).AnyTimes()
   103  	return delegationProvider
   104  }
   105  
   106  func newGovernanceProvider(t *testing.T, ctrl *gomock.Controller) *typemocks.MockStateProvider {
   107  	t.Helper()
   108  
   109  	governanceProvider := typemocks.NewMockStateProvider(ctrl)
   110  	governanceProvider.EXPECT().Namespace().Return(types.SnapshotNamespace("governance")).AnyTimes()
   111  	governanceProvider.EXPECT().Keys().Return([]string{"active", "enacted"}).AnyTimes()
   112  	governanceProvider.EXPECT().Stopped().Return(false).AnyTimes()
   113  	return governanceProvider
   114  }
   115  
   116  func firstSnapshot(t *testing.T) *snapshotForTest {
   117  	t.Helper()
   118  
   119  	appState, payloads := firstState(t)
   120  
   121  	return toSnapshotTest(t, payloads, appState)
   122  }
   123  
   124  func secondSnapshot(t *testing.T) *snapshotForTest {
   125  	t.Helper()
   126  
   127  	appState, payloads := secondState(t)
   128  
   129  	return toSnapshotTest(t, payloads, appState)
   130  }
   131  
   132  func toSnapshotTest(t *testing.T, payloads []*types.Payload, appState *types.AppState) *snapshotForTest {
   133  	t.Helper()
   134  
   135  	tree, err := iavl.NewMutableTree(cometbftdb.NewMemDB(), 0, false)
   136  	require.NoError(t, err)
   137  
   138  	_, err = tree.Load()
   139  	require.NoError(t, err)
   140  
   141  	for _, p := range payloads {
   142  		payload, err := proto.Marshal(p.IntoProto())
   143  		require.NoError(t, err)
   144  		_, err = tree.Set([]byte(p.TreeKey()), payload)
   145  		require.NoError(t, err)
   146  	}
   147  
   148  	_, _, err = tree.SaveVersion()
   149  	require.NoError(t, err)
   150  
   151  	s, err := types.SnapshotFromTree(tree.ImmutableTree)
   152  	require.NoError(t, err)
   153  
   154  	rawChunks := make([]*types.RawChunk, 0, s.Chunks)
   155  	for i := uint32(0); i < s.Chunks; i++ {
   156  		rawChunks = append(rawChunks, &types.RawChunk{
   157  			Nr:     i,
   158  			Data:   s.ByteChunks[int(i)],
   159  			Height: s.Height,
   160  			Format: s.Format,
   161  		})
   162  	}
   163  
   164  	return &snapshotForTest{
   165  		snapshot: &types.Snapshot{
   166  			Format: s.Format,
   167  			Height: s.Height,
   168  			Hash:   s.Hash,
   169  			Meta: &types.Metadata{
   170  				Version:         s.Meta.Version,
   171  				NodeHashes:      s.Meta.NodeHashes,
   172  				ChunkHashes:     s.Meta.ChunkHashes,
   173  				ProtocolVersion: s.Meta.ProtocolVersion,
   174  				ProtocolUpgrade: s.Meta.ProtocolUpgrade,
   175  			},
   176  			Chunks: s.Chunks,
   177  		},
   178  		byteChunks: s.ByteChunks,
   179  		rawChunks:  rawChunks,
   180  		payloads:   payloads,
   181  		appState:   appState,
   182  	}
   183  }
   184  
   185  func firstState(t *testing.T) (*types.AppState, []*types.Payload) {
   186  	t.Helper()
   187  
   188  	chainTime, err := time.Parse("2006-01-02 15:04", "2022-12-12 04:35")
   189  	require.NoError(t, err)
   190  
   191  	appState := &types.AppState{
   192  		Height:          64,
   193  		Block:           "qwertyuiop1234567890",
   194  		Time:            chainTime.UnixNano(),
   195  		ChainID:         "testnet-1",
   196  		ProtocolUpdgade: true,
   197  		ProtocolVersion: "v0.72.1",
   198  	}
   199  
   200  	// Random data for active governance.
   201  	activeProposalID := vgrand.RandomStr(5)
   202  	activeProposalTime, err := time.Parse("2006-01-02 15:04", "2022-12-15 06:30")
   203  	require.NoError(t, err)
   204  
   205  	// Random data for enacted governance.
   206  	enactedProposalID := vgrand.RandomStr(5)
   207  	enactedProposalTime, err := time.Parse("2006-01-02 15:04", "2022-12-10 06:30")
   208  	require.NoError(t, err)
   209  
   210  	payloads := []*types.Payload{
   211  		{
   212  			Data: &types.PayloadAppState{
   213  				AppState: appState,
   214  			},
   215  		},
   216  		{
   217  			Data: &types.PayloadGovernanceActive{
   218  				GovernanceActive: &types.GovernanceActive{
   219  					Proposals: []*types.ProposalData{
   220  						{
   221  							Proposal: &types.Proposal{
   222  								ID:        activeProposalID,
   223  								Reference: vgrand.RandomStr(5),
   224  								Party:     vgrand.RandomStr(5),
   225  								State:     types.ProposalStatePassed,
   226  								Timestamp: activeProposalTime.UnixNano(),
   227  								Terms: &types.ProposalTerms{
   228  									ClosingTimestamp:    activeProposalTime.Add(1 * time.Hour).UnixNano(),
   229  									EnactmentTimestamp:  activeProposalTime.Add(2 * time.Hour).UnixNano(),
   230  									ValidationTimestamp: 0,
   231  									Change: &types.ProposalTermsUpdateNetworkParameter{
   232  										UpdateNetworkParameter: &types.UpdateNetworkParameter{
   233  											Changes: &types.NetworkParameter{
   234  												Key:   vgrand.RandomStr(10),
   235  												Value: vgrand.RandomStr(10),
   236  											},
   237  										},
   238  									},
   239  								},
   240  								Rationale: &types.ProposalRationale{
   241  									Description: vgrand.RandomStr(10),
   242  									Title:       vgrand.RandomStr(10),
   243  								},
   244  								Reason:                  0,
   245  								ErrorDetails:            "",
   246  								RequiredMajority:        num.DecimalFromInt64(100),
   247  								RequiredParticipation:   num.DecimalFromInt64(50),
   248  								RequiredLPMajority:      num.DecimalFromInt64(100),
   249  								RequiredLPParticipation: num.DecimalFromInt64(50),
   250  							},
   251  							Yes: []*types.Vote{
   252  								{
   253  									PartyID:                     vgrand.RandomStr(5),
   254  									ProposalID:                  activeProposalID,
   255  									Value:                       types.VoteValueYes,
   256  									Timestamp:                   activeProposalTime.Add(30 * time.Minute).UnixNano(),
   257  									TotalGovernanceTokenBalance: toUint("100"),
   258  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   259  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   260  								},
   261  								{
   262  									PartyID:                     vgrand.RandomStr(5),
   263  									ProposalID:                  activeProposalID,
   264  									Value:                       types.VoteValueYes,
   265  									Timestamp:                   activeProposalTime.Add(30 * time.Minute).UnixNano(),
   266  									TotalGovernanceTokenBalance: toUint("100"),
   267  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   268  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   269  								},
   270  								{
   271  									PartyID:                     vgrand.RandomStr(5),
   272  									ProposalID:                  activeProposalID,
   273  									Value:                       types.VoteValueYes,
   274  									Timestamp:                   activeProposalTime.Add(30 * time.Minute).UnixNano(),
   275  									TotalGovernanceTokenBalance: toUint("100"),
   276  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   277  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   278  								},
   279  								{
   280  									PartyID:                     vgrand.RandomStr(5),
   281  									ProposalID:                  activeProposalID,
   282  									Value:                       types.VoteValueYes,
   283  									Timestamp:                   activeProposalTime.Add(31 * time.Minute).UnixNano(),
   284  									TotalGovernanceTokenBalance: toUint("100"),
   285  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   286  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   287  								},
   288  							},
   289  							No: []*types.Vote{
   290  								{
   291  									PartyID:                     vgrand.RandomStr(5),
   292  									ProposalID:                  activeProposalID,
   293  									Value:                       types.VoteValueNo,
   294  									Timestamp:                   activeProposalTime.Add(32 * time.Minute).UnixNano(),
   295  									TotalGovernanceTokenBalance: toUint("100"),
   296  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   297  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   298  								}, {
   299  									PartyID:                     vgrand.RandomStr(5),
   300  									ProposalID:                  activeProposalID,
   301  									Value:                       types.VoteValueNo,
   302  									Timestamp:                   activeProposalTime.Add(33 * time.Minute).UnixNano(),
   303  									TotalGovernanceTokenBalance: toUint("100"),
   304  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   305  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   306  								}, {
   307  									PartyID:                     vgrand.RandomStr(5),
   308  									ProposalID:                  activeProposalID,
   309  									Value:                       types.VoteValueNo,
   310  									Timestamp:                   activeProposalTime.Add(34 * time.Minute).UnixNano(),
   311  									TotalGovernanceTokenBalance: toUint("100"),
   312  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   313  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   314  								},
   315  							},
   316  							Invalid: []*types.Vote{
   317  								{
   318  									PartyID:                     vgrand.RandomStr(5),
   319  									ProposalID:                  activeProposalID,
   320  									Value:                       types.VoteValueYes,
   321  									Timestamp:                   activeProposalTime.Add(35 * time.Minute).UnixNano(),
   322  									TotalGovernanceTokenBalance: toUint("100"),
   323  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   324  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   325  								}, {
   326  									PartyID:                     vgrand.RandomStr(5),
   327  									ProposalID:                  activeProposalID,
   328  									Value:                       types.VoteValueNo,
   329  									Timestamp:                   activeProposalTime.Add(36 * time.Minute).UnixNano(),
   330  									TotalGovernanceTokenBalance: toUint("100"),
   331  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   332  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   333  								},
   334  							},
   335  						},
   336  					},
   337  				},
   338  			},
   339  		},
   340  		{
   341  			Data: &types.PayloadGovernanceEnacted{
   342  				GovernanceEnacted: &types.GovernanceEnacted{
   343  					Proposals: []*types.ProposalData{
   344  						{
   345  							Proposal: &types.Proposal{
   346  								ID:        enactedProposalID,
   347  								Reference: vgrand.RandomStr(5),
   348  								Party:     vgrand.RandomStr(5),
   349  								State:     types.ProposalStatePassed,
   350  								Timestamp: enactedProposalTime.UnixNano(),
   351  								Terms: &types.ProposalTerms{
   352  									ClosingTimestamp:    enactedProposalTime.Add(1 * time.Hour).UnixNano(),
   353  									EnactmentTimestamp:  enactedProposalTime.Add(2 * time.Hour).UnixNano(),
   354  									ValidationTimestamp: 0,
   355  									Change: &types.ProposalTermsUpdateNetworkParameter{
   356  										UpdateNetworkParameter: &types.UpdateNetworkParameter{
   357  											Changes: &types.NetworkParameter{
   358  												Key:   vgrand.RandomStr(10),
   359  												Value: vgrand.RandomStr(10),
   360  											},
   361  										},
   362  									},
   363  								},
   364  								Rationale: &types.ProposalRationale{
   365  									Description: vgrand.RandomStr(10),
   366  									Title:       vgrand.RandomStr(10),
   367  								},
   368  								Reason:                  0,
   369  								ErrorDetails:            "",
   370  								RequiredMajority:        num.DecimalFromInt64(100),
   371  								RequiredParticipation:   num.DecimalFromInt64(50),
   372  								RequiredLPMajority:      num.DecimalFromInt64(100),
   373  								RequiredLPParticipation: num.DecimalFromInt64(50),
   374  							},
   375  							Yes: []*types.Vote{
   376  								{
   377  									PartyID:                     vgrand.RandomStr(5),
   378  									ProposalID:                  enactedProposalID,
   379  									Value:                       types.VoteValueYes,
   380  									Timestamp:                   enactedProposalTime.Add(30 * time.Minute).UnixNano(),
   381  									TotalGovernanceTokenBalance: toUint("100"),
   382  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   383  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   384  								},
   385  								{
   386  									PartyID:                     vgrand.RandomStr(5),
   387  									ProposalID:                  enactedProposalID,
   388  									Value:                       types.VoteValueYes,
   389  									Timestamp:                   enactedProposalTime.Add(30 * time.Minute).UnixNano(),
   390  									TotalGovernanceTokenBalance: toUint("100"),
   391  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   392  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   393  								},
   394  								{
   395  									PartyID:                     vgrand.RandomStr(5),
   396  									ProposalID:                  enactedProposalID,
   397  									Value:                       types.VoteValueYes,
   398  									Timestamp:                   enactedProposalTime.Add(30 * time.Minute).UnixNano(),
   399  									TotalGovernanceTokenBalance: toUint("100"),
   400  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   401  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   402  								},
   403  								{
   404  									PartyID:                     vgrand.RandomStr(5),
   405  									ProposalID:                  enactedProposalID,
   406  									Value:                       types.VoteValueYes,
   407  									Timestamp:                   enactedProposalTime.Add(31 * time.Minute).UnixNano(),
   408  									TotalGovernanceTokenBalance: toUint("100"),
   409  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   410  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   411  								},
   412  							},
   413  							No: []*types.Vote{
   414  								{
   415  									PartyID:                     vgrand.RandomStr(5),
   416  									ProposalID:                  enactedProposalID,
   417  									Value:                       types.VoteValueNo,
   418  									Timestamp:                   enactedProposalTime.Add(32 * time.Minute).UnixNano(),
   419  									TotalGovernanceTokenBalance: toUint("100"),
   420  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   421  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   422  								}, {
   423  									PartyID:                     vgrand.RandomStr(5),
   424  									ProposalID:                  enactedProposalID,
   425  									Value:                       types.VoteValueNo,
   426  									Timestamp:                   enactedProposalTime.Add(33 * time.Minute).UnixNano(),
   427  									TotalGovernanceTokenBalance: toUint("100"),
   428  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   429  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   430  								}, {
   431  									PartyID:                     vgrand.RandomStr(5),
   432  									ProposalID:                  enactedProposalID,
   433  									Value:                       types.VoteValueNo,
   434  									Timestamp:                   enactedProposalTime.Add(34 * time.Minute).UnixNano(),
   435  									TotalGovernanceTokenBalance: toUint("100"),
   436  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   437  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   438  								},
   439  							},
   440  							Invalid: []*types.Vote{
   441  								{
   442  									PartyID:                     vgrand.RandomStr(5),
   443  									ProposalID:                  enactedProposalID,
   444  									Value:                       types.VoteValueYes,
   445  									Timestamp:                   enactedProposalTime.Add(35 * time.Minute).UnixNano(),
   446  									TotalGovernanceTokenBalance: toUint("100"),
   447  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   448  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   449  								}, {
   450  									PartyID:                     vgrand.RandomStr(5),
   451  									ProposalID:                  enactedProposalID,
   452  									Value:                       types.VoteValueNo,
   453  									Timestamp:                   enactedProposalTime.Add(36 * time.Minute).UnixNano(),
   454  									TotalGovernanceTokenBalance: toUint("100"),
   455  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   456  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   457  								},
   458  							},
   459  						},
   460  					},
   461  				},
   462  			},
   463  		},
   464  		{
   465  			Data: &types.PayloadDelegationActive{
   466  				DelegationActive: &types.DelegationActive{
   467  					Delegations: []*types.Delegation{
   468  						{
   469  							Party:    vgrand.RandomStr(5),
   470  							NodeID:   vgrand.RandomStr(5),
   471  							Amount:   toUint("1000"),
   472  							EpochSeq: "10",
   473  						}, {
   474  							Party:    vgrand.RandomStr(5),
   475  							NodeID:   vgrand.RandomStr(5),
   476  							Amount:   toUint("2000"),
   477  							EpochSeq: "20",
   478  						}, {
   479  							Party:    vgrand.RandomStr(5),
   480  							NodeID:   vgrand.RandomStr(5),
   481  							Amount:   toUint("3000"),
   482  							EpochSeq: "30",
   483  						},
   484  					},
   485  				},
   486  			},
   487  		},
   488  		{
   489  			Data: &types.PayloadEpoch{
   490  				EpochState: &types.EpochState{
   491  					Seq:                  7,
   492  					StartTime:            time.Now().In(time.UTC),
   493  					ExpireTime:           time.Now().Add(1 * time.Hour).In(time.UTC),
   494  					ReadyToStartNewEpoch: true,
   495  					ReadyToEndEpoch:      false,
   496  				},
   497  			},
   498  		},
   499  	}
   500  	return appState, payloads
   501  }
   502  
   503  func secondState(t *testing.T) (*types.AppState, []*types.Payload) {
   504  	t.Helper()
   505  
   506  	chainTime, err := time.Parse("2006-01-02 15:04", "2022-12-24 04:35")
   507  	require.NoError(t, err)
   508  
   509  	appState := &types.AppState{
   510  		Height:          164,
   511  		Block:           "1234567890qwertyuiop",
   512  		Time:            chainTime.UnixNano(),
   513  		ChainID:         "testnet-1",
   514  		ProtocolUpdgade: true,
   515  		ProtocolVersion: "v0.74.1",
   516  	}
   517  
   518  	// Random data for active governance.
   519  	activeProposalID := vgrand.RandomStr(5)
   520  	activeProposalTime, err := time.Parse("2006-01-02 15:04", "2022-12-25 06:30")
   521  	require.NoError(t, err)
   522  
   523  	payloads := []*types.Payload{
   524  		{
   525  			Data: &types.PayloadAppState{
   526  				AppState: appState,
   527  			},
   528  		},
   529  		{
   530  			Data: &types.PayloadGovernanceActive{
   531  				GovernanceActive: &types.GovernanceActive{
   532  					Proposals: []*types.ProposalData{
   533  						{
   534  							Proposal: &types.Proposal{
   535  								ID:        activeProposalID,
   536  								Reference: vgrand.RandomStr(5),
   537  								Party:     vgrand.RandomStr(5),
   538  								State:     types.ProposalStatePassed,
   539  								Timestamp: activeProposalTime.UnixNano(),
   540  								Terms: &types.ProposalTerms{
   541  									ClosingTimestamp:    activeProposalTime.Add(1 * time.Hour).UnixNano(),
   542  									EnactmentTimestamp:  activeProposalTime.Add(2 * time.Hour).UnixNano(),
   543  									ValidationTimestamp: 0,
   544  									Change: &types.ProposalTermsUpdateNetworkParameter{
   545  										UpdateNetworkParameter: &types.UpdateNetworkParameter{
   546  											Changes: &types.NetworkParameter{
   547  												Key:   vgrand.RandomStr(10),
   548  												Value: vgrand.RandomStr(10),
   549  											},
   550  										},
   551  									},
   552  								},
   553  								Rationale: &types.ProposalRationale{
   554  									Description: vgrand.RandomStr(10),
   555  									Title:       vgrand.RandomStr(10),
   556  								},
   557  								Reason:                  0,
   558  								ErrorDetails:            "",
   559  								RequiredMajority:        num.DecimalFromInt64(100),
   560  								RequiredParticipation:   num.DecimalFromInt64(50),
   561  								RequiredLPMajority:      num.DecimalFromInt64(100),
   562  								RequiredLPParticipation: num.DecimalFromInt64(50),
   563  							},
   564  							Yes: []*types.Vote{
   565  								{
   566  									PartyID:                     vgrand.RandomStr(5),
   567  									ProposalID:                  activeProposalID,
   568  									Value:                       types.VoteValueYes,
   569  									Timestamp:                   activeProposalTime.Add(30 * time.Minute).UnixNano(),
   570  									TotalGovernanceTokenBalance: toUint("100"),
   571  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   572  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   573  								},
   574  								{
   575  									PartyID:                     vgrand.RandomStr(5),
   576  									ProposalID:                  activeProposalID,
   577  									Value:                       types.VoteValueYes,
   578  									Timestamp:                   activeProposalTime.Add(30 * time.Minute).UnixNano(),
   579  									TotalGovernanceTokenBalance: toUint("100"),
   580  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   581  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   582  								},
   583  								{
   584  									PartyID:                     vgrand.RandomStr(5),
   585  									ProposalID:                  activeProposalID,
   586  									Value:                       types.VoteValueYes,
   587  									Timestamp:                   activeProposalTime.Add(30 * time.Minute).UnixNano(),
   588  									TotalGovernanceTokenBalance: toUint("100"),
   589  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   590  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   591  								},
   592  								{
   593  									PartyID:                     vgrand.RandomStr(5),
   594  									ProposalID:                  activeProposalID,
   595  									Value:                       types.VoteValueYes,
   596  									Timestamp:                   activeProposalTime.Add(31 * time.Minute).UnixNano(),
   597  									TotalGovernanceTokenBalance: toUint("100"),
   598  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   599  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   600  								},
   601  							},
   602  							No: []*types.Vote{
   603  								{
   604  									PartyID:                     vgrand.RandomStr(5),
   605  									ProposalID:                  activeProposalID,
   606  									Value:                       types.VoteValueNo,
   607  									Timestamp:                   activeProposalTime.Add(32 * time.Minute).UnixNano(),
   608  									TotalGovernanceTokenBalance: toUint("100"),
   609  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   610  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   611  								}, {
   612  									PartyID:                     vgrand.RandomStr(5),
   613  									ProposalID:                  activeProposalID,
   614  									Value:                       types.VoteValueNo,
   615  									Timestamp:                   activeProposalTime.Add(33 * time.Minute).UnixNano(),
   616  									TotalGovernanceTokenBalance: toUint("100"),
   617  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   618  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   619  								}, {
   620  									PartyID:                     vgrand.RandomStr(5),
   621  									ProposalID:                  activeProposalID,
   622  									Value:                       types.VoteValueNo,
   623  									Timestamp:                   activeProposalTime.Add(34 * time.Minute).UnixNano(),
   624  									TotalGovernanceTokenBalance: toUint("100"),
   625  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   626  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   627  								},
   628  							},
   629  							Invalid: []*types.Vote{
   630  								{
   631  									PartyID:                     vgrand.RandomStr(5),
   632  									ProposalID:                  activeProposalID,
   633  									Value:                       types.VoteValueYes,
   634  									Timestamp:                   activeProposalTime.Add(35 * time.Minute).UnixNano(),
   635  									TotalGovernanceTokenBalance: toUint("100"),
   636  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   637  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   638  								}, {
   639  									PartyID:                     vgrand.RandomStr(5),
   640  									ProposalID:                  activeProposalID,
   641  									Value:                       types.VoteValueNo,
   642  									Timestamp:                   activeProposalTime.Add(36 * time.Minute).UnixNano(),
   643  									TotalGovernanceTokenBalance: toUint("100"),
   644  									TotalGovernanceTokenWeight:  num.DecimalFromInt64(100),
   645  									TotalEquityLikeShareWeight:  num.DecimalFromInt64(100),
   646  								},
   647  							},
   648  						},
   649  					},
   650  				},
   651  			},
   652  		},
   653  		{
   654  			// Nothing set on purpose, to see if the snapshot behaves properly
   655  			// when a key becomes empty.
   656  			Data: &types.PayloadGovernanceEnacted{
   657  				GovernanceEnacted: &types.GovernanceEnacted{},
   658  			},
   659  		},
   660  		{
   661  			Data: &types.PayloadDelegationActive{
   662  				DelegationActive: &types.DelegationActive{
   663  					Delegations: []*types.Delegation{
   664  						{
   665  							Party:    vgrand.RandomStr(5),
   666  							NodeID:   vgrand.RandomStr(5),
   667  							Amount:   toUint("1000"),
   668  							EpochSeq: "10",
   669  						}, {
   670  							Party:    vgrand.RandomStr(5),
   671  							NodeID:   vgrand.RandomStr(5),
   672  							Amount:   toUint("2000"),
   673  							EpochSeq: "20",
   674  						}, {
   675  							Party:    vgrand.RandomStr(5),
   676  							NodeID:   vgrand.RandomStr(5),
   677  							Amount:   toUint("3000"),
   678  							EpochSeq: "30",
   679  						},
   680  					},
   681  				},
   682  			},
   683  		},
   684  		{
   685  			Data: &types.PayloadEpoch{
   686  				EpochState: &types.EpochState{
   687  					Seq:                  7,
   688  					StartTime:            time.Now().In(time.UTC),
   689  					ExpireTime:           time.Now().Add(1 * time.Hour).In(time.UTC),
   690  					ReadyToStartNewEpoch: true,
   691  					ReadyToEndEpoch:      false,
   692  				},
   693  			},
   694  		},
   695  	}
   696  	return appState, payloads
   697  }
   698  
   699  func toUint(n string) *num.Uint {
   700  	uintNum, _ := num.UintFromString(n, 10)
   701  	return uintNum
   702  }
   703  
   704  func serialize(t *testing.T, payload *types.Payload) []byte {
   705  	t.Helper()
   706  
   707  	serializedPayload, err := proto.Marshal(payload.IntoProto())
   708  	require.NoError(t, err)
   709  	return serializedPayload
   710  }