github.com/MetalBlockchain/metalgo@v1.11.9/vms/platformvm/state/state_test.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package state
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"math"
    10  	"sync"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/prometheus/client_golang/prometheus"
    15  	"github.com/stretchr/testify/require"
    16  	"go.uber.org/mock/gomock"
    17  
    18  	"github.com/MetalBlockchain/metalgo/database"
    19  	"github.com/MetalBlockchain/metalgo/database/memdb"
    20  	"github.com/MetalBlockchain/metalgo/ids"
    21  	"github.com/MetalBlockchain/metalgo/snow"
    22  	"github.com/MetalBlockchain/metalgo/snow/choices"
    23  	"github.com/MetalBlockchain/metalgo/snow/validators"
    24  	"github.com/MetalBlockchain/metalgo/utils/constants"
    25  	"github.com/MetalBlockchain/metalgo/utils/crypto/bls"
    26  	"github.com/MetalBlockchain/metalgo/utils/logging"
    27  	"github.com/MetalBlockchain/metalgo/utils/units"
    28  	"github.com/MetalBlockchain/metalgo/utils/wrappers"
    29  	"github.com/MetalBlockchain/metalgo/vms/components/avax"
    30  	"github.com/MetalBlockchain/metalgo/vms/platformvm/block"
    31  	"github.com/MetalBlockchain/metalgo/vms/platformvm/config"
    32  	"github.com/MetalBlockchain/metalgo/vms/platformvm/fx"
    33  	"github.com/MetalBlockchain/metalgo/vms/platformvm/genesis"
    34  	"github.com/MetalBlockchain/metalgo/vms/platformvm/metrics"
    35  	"github.com/MetalBlockchain/metalgo/vms/platformvm/reward"
    36  	"github.com/MetalBlockchain/metalgo/vms/platformvm/signer"
    37  	"github.com/MetalBlockchain/metalgo/vms/platformvm/status"
    38  	"github.com/MetalBlockchain/metalgo/vms/platformvm/txs"
    39  	"github.com/MetalBlockchain/metalgo/vms/secp256k1fx"
    40  	"github.com/MetalBlockchain/metalgo/vms/types"
    41  
    42  	safemath "github.com/MetalBlockchain/metalgo/utils/math"
    43  )
    44  
    45  var (
    46  	initialTxID             = ids.GenerateTestID()
    47  	initialNodeID           = ids.GenerateTestNodeID()
    48  	initialTime             = time.Now().Round(time.Second)
    49  	initialValidatorEndTime = initialTime.Add(28 * 24 * time.Hour)
    50  )
    51  
    52  func TestStateInitialization(t *testing.T) {
    53  	require := require.New(t)
    54  	s, db := newUninitializedState(require)
    55  
    56  	shouldInit, err := s.shouldInit()
    57  	require.NoError(err)
    58  	require.True(shouldInit)
    59  
    60  	require.NoError(s.doneInit())
    61  	require.NoError(s.Commit())
    62  
    63  	s = newStateFromDB(require, db)
    64  
    65  	shouldInit, err = s.shouldInit()
    66  	require.NoError(err)
    67  	require.False(shouldInit)
    68  }
    69  
    70  func TestStateSyncGenesis(t *testing.T) {
    71  	require := require.New(t)
    72  	state := newInitializedState(require)
    73  
    74  	staker, err := state.GetCurrentValidator(constants.PrimaryNetworkID, initialNodeID)
    75  	require.NoError(err)
    76  	require.NotNil(staker)
    77  	require.Equal(initialNodeID, staker.NodeID)
    78  
    79  	delegatorIterator, err := state.GetCurrentDelegatorIterator(constants.PrimaryNetworkID, initialNodeID)
    80  	require.NoError(err)
    81  	assertIteratorsEqual(t, EmptyIterator, delegatorIterator)
    82  
    83  	stakerIterator, err := state.GetCurrentStakerIterator()
    84  	require.NoError(err)
    85  	assertIteratorsEqual(t, NewSliceIterator(staker), stakerIterator)
    86  
    87  	_, err = state.GetPendingValidator(constants.PrimaryNetworkID, initialNodeID)
    88  	require.ErrorIs(err, database.ErrNotFound)
    89  
    90  	delegatorIterator, err = state.GetPendingDelegatorIterator(constants.PrimaryNetworkID, initialNodeID)
    91  	require.NoError(err)
    92  	assertIteratorsEqual(t, EmptyIterator, delegatorIterator)
    93  }
    94  
    95  // Whenever we store a staker, a whole bunch a data structures are updated
    96  // This test is meant to capture which updates are carried out
    97  func TestPersistStakers(t *testing.T) {
    98  	tests := map[string]struct {
    99  		// Insert or delete a staker to state and store it
   100  		storeStaker func(*require.Assertions, ids.ID /*=subnetID*/, *state) *Staker
   101  
   102  		// Check that the staker is duly stored/removed in P-chain state
   103  		checkStakerInState func(*require.Assertions, *state, *Staker)
   104  
   105  		// Check whether validators are duly reported in the validator set,
   106  		// with the right weight and showing the BLS key
   107  		checkValidatorsSet func(*require.Assertions, *state, *Staker)
   108  
   109  		// Check that node duly track stakers uptimes
   110  		checkValidatorUptimes func(*require.Assertions, *state, *Staker)
   111  
   112  		// Check whether weight/bls keys diffs are duly stored
   113  		checkDiffs func(*require.Assertions, *state, *Staker, uint64)
   114  	}{
   115  		"add current validator": {
   116  			storeStaker: func(r *require.Assertions, subnetID ids.ID, s *state) *Staker {
   117  				var (
   118  					startTime = time.Now().Unix()
   119  					endTime   = time.Now().Add(14 * 24 * time.Hour).Unix()
   120  
   121  					validatorsData = txs.Validator{
   122  						NodeID: ids.GenerateTestNodeID(),
   123  						End:    uint64(endTime),
   124  						Wght:   1234,
   125  					}
   126  					validatorReward uint64 = 5678
   127  				)
   128  
   129  				utx := createPermissionlessValidatorTx(r, subnetID, validatorsData)
   130  				addPermValTx := &txs.Tx{Unsigned: utx}
   131  				r.NoError(addPermValTx.Initialize(txs.Codec))
   132  
   133  				staker, err := NewCurrentStaker(
   134  					addPermValTx.ID(),
   135  					utx,
   136  					time.Unix(startTime, 0),
   137  					validatorReward,
   138  				)
   139  				r.NoError(err)
   140  
   141  				s.PutCurrentValidator(staker)
   142  				s.AddTx(addPermValTx, status.Committed) // this is currently needed to reload the staker
   143  				r.NoError(s.Commit())
   144  				return staker
   145  			},
   146  			checkStakerInState: func(r *require.Assertions, s *state, staker *Staker) {
   147  				retrievedStaker, err := s.GetCurrentValidator(staker.SubnetID, staker.NodeID)
   148  				r.NoError(err)
   149  				r.Equal(staker, retrievedStaker)
   150  			},
   151  			checkValidatorsSet: func(r *require.Assertions, s *state, staker *Staker) {
   152  				valsMap := s.cfg.Validators.GetMap(staker.SubnetID)
   153  				r.Len(valsMap, 1)
   154  				valOut, found := valsMap[staker.NodeID]
   155  				r.True(found)
   156  				r.Equal(&validators.GetValidatorOutput{
   157  					NodeID:    staker.NodeID,
   158  					PublicKey: staker.PublicKey,
   159  					Weight:    staker.Weight,
   160  				}, valOut)
   161  			},
   162  			checkValidatorUptimes: func(r *require.Assertions, s *state, staker *Staker) {
   163  				upDuration, lastUpdated, err := s.GetUptime(staker.NodeID, staker.SubnetID)
   164  				r.NoError(err)
   165  				r.Equal(upDuration, time.Duration(0))
   166  				r.Equal(lastUpdated, staker.StartTime)
   167  			},
   168  			checkDiffs: func(r *require.Assertions, s *state, staker *Staker, height uint64) {
   169  				weightDiffBytes, err := s.validatorWeightDiffsDB.Get(marshalDiffKey(staker.SubnetID, height, staker.NodeID))
   170  				r.NoError(err)
   171  				weightDiff, err := unmarshalWeightDiff(weightDiffBytes)
   172  				r.NoError(err)
   173  				r.Equal(&ValidatorWeightDiff{
   174  					Decrease: false,
   175  					Amount:   staker.Weight,
   176  				}, weightDiff)
   177  
   178  				blsDiffBytes, err := s.validatorPublicKeyDiffsDB.Get(marshalDiffKey(staker.SubnetID, height, staker.NodeID))
   179  				if staker.SubnetID == constants.PrimaryNetworkID {
   180  					r.NoError(err)
   181  					r.Nil(blsDiffBytes)
   182  				} else {
   183  					r.ErrorIs(err, database.ErrNotFound)
   184  				}
   185  			},
   186  		},
   187  		"add current delegator": {
   188  			storeStaker: func(r *require.Assertions, subnetID ids.ID, s *state) *Staker {
   189  				// insert the delegator and its validator
   190  				var (
   191  					valStartTime = time.Now().Truncate(time.Second).Unix()
   192  					delStartTime = time.Unix(valStartTime, 0).Add(time.Hour).Unix()
   193  					delEndTime   = time.Unix(delStartTime, 0).Add(30 * 24 * time.Hour).Unix()
   194  					valEndTime   = time.Unix(valStartTime, 0).Add(365 * 24 * time.Hour).Unix()
   195  
   196  					validatorsData = txs.Validator{
   197  						NodeID: ids.GenerateTestNodeID(),
   198  						End:    uint64(valEndTime),
   199  						Wght:   1234,
   200  					}
   201  					validatorReward uint64 = 5678
   202  
   203  					delegatorData = txs.Validator{
   204  						NodeID: validatorsData.NodeID,
   205  						End:    uint64(delEndTime),
   206  						Wght:   validatorsData.Wght / 2,
   207  					}
   208  					delegatorReward uint64 = 5432
   209  				)
   210  
   211  				utxVal := createPermissionlessValidatorTx(r, subnetID, validatorsData)
   212  				addPermValTx := &txs.Tx{Unsigned: utxVal}
   213  				r.NoError(addPermValTx.Initialize(txs.Codec))
   214  
   215  				val, err := NewCurrentStaker(
   216  					addPermValTx.ID(),
   217  					utxVal,
   218  					time.Unix(valStartTime, 0),
   219  					validatorReward,
   220  				)
   221  				r.NoError(err)
   222  
   223  				utxDel := createPermissionlessDelegatorTx(subnetID, delegatorData)
   224  				addPermDelTx := &txs.Tx{Unsigned: utxDel}
   225  				r.NoError(addPermDelTx.Initialize(txs.Codec))
   226  
   227  				del, err := NewCurrentStaker(
   228  					addPermDelTx.ID(),
   229  					utxDel,
   230  					time.Unix(delStartTime, 0),
   231  					delegatorReward,
   232  				)
   233  				r.NoError(err)
   234  
   235  				s.PutCurrentValidator(val)
   236  				s.AddTx(addPermValTx, status.Committed) // this is currently needed to reload the staker
   237  				r.NoError(s.Commit())
   238  
   239  				s.PutCurrentDelegator(del)
   240  				s.AddTx(addPermDelTx, status.Committed) // this is currently needed to reload the staker
   241  				r.NoError(s.Commit())
   242  				return del
   243  			},
   244  			checkStakerInState: func(r *require.Assertions, s *state, staker *Staker) {
   245  				delIt, err := s.GetCurrentDelegatorIterator(staker.SubnetID, staker.NodeID)
   246  				r.NoError(err)
   247  				r.True(delIt.Next())
   248  				retrievedDelegator := delIt.Value()
   249  				r.False(delIt.Next())
   250  				delIt.Release()
   251  				r.Equal(staker, retrievedDelegator)
   252  			},
   253  			checkValidatorsSet: func(r *require.Assertions, s *state, staker *Staker) {
   254  				val, err := s.GetCurrentValidator(staker.SubnetID, staker.NodeID)
   255  				r.NoError(err)
   256  
   257  				valsMap := s.cfg.Validators.GetMap(staker.SubnetID)
   258  				r.Len(valsMap, 1)
   259  				valOut, found := valsMap[staker.NodeID]
   260  				r.True(found)
   261  				r.Equal(valOut.NodeID, staker.NodeID)
   262  				r.Equal(valOut.Weight, val.Weight+staker.Weight)
   263  			},
   264  			checkValidatorUptimes: func(*require.Assertions, *state, *Staker) {},
   265  			checkDiffs: func(r *require.Assertions, s *state, staker *Staker, height uint64) {
   266  				// validator's weight must increase of delegator's weight amount
   267  				weightDiffBytes, err := s.validatorWeightDiffsDB.Get(marshalDiffKey(staker.SubnetID, height, staker.NodeID))
   268  				r.NoError(err)
   269  				weightDiff, err := unmarshalWeightDiff(weightDiffBytes)
   270  				r.NoError(err)
   271  				r.Equal(&ValidatorWeightDiff{
   272  					Decrease: false,
   273  					Amount:   staker.Weight,
   274  				}, weightDiff)
   275  			},
   276  		},
   277  		"add pending validator": {
   278  			storeStaker: func(r *require.Assertions, subnetID ids.ID, s *state) *Staker {
   279  				var (
   280  					startTime = time.Now().Unix()
   281  					endTime   = time.Now().Add(14 * 24 * time.Hour).Unix()
   282  
   283  					validatorsData = txs.Validator{
   284  						NodeID: ids.GenerateTestNodeID(),
   285  						Start:  uint64(startTime),
   286  						End:    uint64(endTime),
   287  						Wght:   1234,
   288  					}
   289  				)
   290  
   291  				utx := createPermissionlessValidatorTx(r, subnetID, validatorsData)
   292  				addPermValTx := &txs.Tx{Unsigned: utx}
   293  				r.NoError(addPermValTx.Initialize(txs.Codec))
   294  
   295  				staker, err := NewPendingStaker(
   296  					addPermValTx.ID(),
   297  					utx,
   298  				)
   299  				r.NoError(err)
   300  
   301  				s.PutPendingValidator(staker)
   302  				s.AddTx(addPermValTx, status.Committed) // this is currently needed to reload the staker
   303  				r.NoError(s.Commit())
   304  				return staker
   305  			},
   306  			checkStakerInState: func(r *require.Assertions, s *state, staker *Staker) {
   307  				retrievedStaker, err := s.GetPendingValidator(staker.SubnetID, staker.NodeID)
   308  				r.NoError(err)
   309  				r.Equal(staker, retrievedStaker)
   310  			},
   311  			checkValidatorsSet: func(r *require.Assertions, s *state, staker *Staker) {
   312  				// pending validators are not showed in validators set
   313  				valsMap := s.cfg.Validators.GetMap(staker.SubnetID)
   314  				r.Empty(valsMap)
   315  			},
   316  			checkValidatorUptimes: func(r *require.Assertions, s *state, staker *Staker) {
   317  				// pending validators uptime is not tracked
   318  				_, _, err := s.GetUptime(staker.NodeID, staker.SubnetID)
   319  				r.ErrorIs(err, database.ErrNotFound)
   320  			},
   321  			checkDiffs: func(r *require.Assertions, s *state, staker *Staker, height uint64) {
   322  				// pending validators weight diff and bls diffs are not stored
   323  				_, err := s.validatorWeightDiffsDB.Get(marshalDiffKey(staker.SubnetID, height, staker.NodeID))
   324  				r.ErrorIs(err, database.ErrNotFound)
   325  
   326  				_, err = s.validatorPublicKeyDiffsDB.Get(marshalDiffKey(staker.SubnetID, height, staker.NodeID))
   327  				r.ErrorIs(err, database.ErrNotFound)
   328  			},
   329  		},
   330  		"add pending delegator": {
   331  			storeStaker: func(r *require.Assertions, subnetID ids.ID, s *state) *Staker {
   332  				// insert the delegator and its validator
   333  				var (
   334  					valStartTime = time.Now().Truncate(time.Second).Unix()
   335  					delStartTime = time.Unix(valStartTime, 0).Add(time.Hour).Unix()
   336  					delEndTime   = time.Unix(delStartTime, 0).Add(30 * 24 * time.Hour).Unix()
   337  					valEndTime   = time.Unix(valStartTime, 0).Add(365 * 24 * time.Hour).Unix()
   338  
   339  					validatorsData = txs.Validator{
   340  						NodeID: ids.GenerateTestNodeID(),
   341  						Start:  uint64(valStartTime),
   342  						End:    uint64(valEndTime),
   343  						Wght:   1234,
   344  					}
   345  
   346  					delegatorData = txs.Validator{
   347  						NodeID: validatorsData.NodeID,
   348  						Start:  uint64(delStartTime),
   349  						End:    uint64(delEndTime),
   350  						Wght:   validatorsData.Wght / 2,
   351  					}
   352  				)
   353  
   354  				utxVal := createPermissionlessValidatorTx(r, subnetID, validatorsData)
   355  				addPermValTx := &txs.Tx{Unsigned: utxVal}
   356  				r.NoError(addPermValTx.Initialize(txs.Codec))
   357  
   358  				val, err := NewPendingStaker(addPermValTx.ID(), utxVal)
   359  				r.NoError(err)
   360  
   361  				utxDel := createPermissionlessDelegatorTx(subnetID, delegatorData)
   362  				addPermDelTx := &txs.Tx{Unsigned: utxDel}
   363  				r.NoError(addPermDelTx.Initialize(txs.Codec))
   364  
   365  				del, err := NewPendingStaker(addPermDelTx.ID(), utxDel)
   366  				r.NoError(err)
   367  
   368  				s.PutPendingValidator(val)
   369  				s.AddTx(addPermValTx, status.Committed) // this is currently needed to reload the staker
   370  				r.NoError(s.Commit())
   371  
   372  				s.PutPendingDelegator(del)
   373  				s.AddTx(addPermDelTx, status.Committed) // this is currently needed to reload the staker
   374  				r.NoError(s.Commit())
   375  
   376  				return del
   377  			},
   378  			checkStakerInState: func(r *require.Assertions, s *state, staker *Staker) {
   379  				delIt, err := s.GetPendingDelegatorIterator(staker.SubnetID, staker.NodeID)
   380  				r.NoError(err)
   381  				r.True(delIt.Next())
   382  				retrievedDelegator := delIt.Value()
   383  				r.False(delIt.Next())
   384  				delIt.Release()
   385  				r.Equal(staker, retrievedDelegator)
   386  			},
   387  			checkValidatorsSet: func(r *require.Assertions, s *state, staker *Staker) {
   388  				valsMap := s.cfg.Validators.GetMap(staker.SubnetID)
   389  				r.Empty(valsMap)
   390  			},
   391  			checkValidatorUptimes: func(*require.Assertions, *state, *Staker) {},
   392  			checkDiffs:            func(*require.Assertions, *state, *Staker, uint64) {},
   393  		},
   394  		"delete current validator": {
   395  			storeStaker: func(r *require.Assertions, subnetID ids.ID, s *state) *Staker {
   396  				// add them remove the validator
   397  				var (
   398  					startTime = time.Now().Unix()
   399  					endTime   = time.Now().Add(14 * 24 * time.Hour).Unix()
   400  
   401  					validatorsData = txs.Validator{
   402  						NodeID: ids.GenerateTestNodeID(),
   403  						End:    uint64(endTime),
   404  						Wght:   1234,
   405  					}
   406  					validatorReward uint64 = 5678
   407  				)
   408  
   409  				utx := createPermissionlessValidatorTx(r, subnetID, validatorsData)
   410  				addPermValTx := &txs.Tx{Unsigned: utx}
   411  				r.NoError(addPermValTx.Initialize(txs.Codec))
   412  
   413  				staker, err := NewCurrentStaker(
   414  					addPermValTx.ID(),
   415  					utx,
   416  					time.Unix(startTime, 0),
   417  					validatorReward,
   418  				)
   419  				r.NoError(err)
   420  
   421  				s.PutCurrentValidator(staker)
   422  				s.AddTx(addPermValTx, status.Committed) // this is currently needed to reload the staker
   423  				r.NoError(s.Commit())
   424  
   425  				s.DeleteCurrentValidator(staker)
   426  				r.NoError(s.Commit())
   427  				return staker
   428  			},
   429  			checkStakerInState: func(r *require.Assertions, s *state, staker *Staker) {
   430  				_, err := s.GetCurrentValidator(staker.SubnetID, staker.NodeID)
   431  				r.ErrorIs(err, database.ErrNotFound)
   432  			},
   433  			checkValidatorsSet: func(r *require.Assertions, s *state, staker *Staker) {
   434  				// deleted validators are not showed in the validators set anymore
   435  				valsMap := s.cfg.Validators.GetMap(staker.SubnetID)
   436  				r.Empty(valsMap)
   437  			},
   438  			checkValidatorUptimes: func(r *require.Assertions, s *state, staker *Staker) {
   439  				// uptimes of delete validators are dropped
   440  				_, _, err := s.GetUptime(staker.NodeID, staker.SubnetID)
   441  				r.ErrorIs(err, database.ErrNotFound)
   442  			},
   443  			checkDiffs: func(r *require.Assertions, s *state, staker *Staker, height uint64) {
   444  				weightDiffBytes, err := s.validatorWeightDiffsDB.Get(marshalDiffKey(staker.SubnetID, height, staker.NodeID))
   445  				r.NoError(err)
   446  				weightDiff, err := unmarshalWeightDiff(weightDiffBytes)
   447  				r.NoError(err)
   448  				r.Equal(&ValidatorWeightDiff{
   449  					Decrease: true,
   450  					Amount:   staker.Weight,
   451  				}, weightDiff)
   452  
   453  				blsDiffBytes, err := s.validatorPublicKeyDiffsDB.Get(marshalDiffKey(staker.SubnetID, height, staker.NodeID))
   454  				if staker.SubnetID == constants.PrimaryNetworkID {
   455  					r.NoError(err)
   456  					r.Equal(bls.PublicKeyFromValidUncompressedBytes(blsDiffBytes), staker.PublicKey)
   457  				} else {
   458  					r.ErrorIs(err, database.ErrNotFound)
   459  				}
   460  			},
   461  		},
   462  		"delete current delegator": {
   463  			storeStaker: func(r *require.Assertions, subnetID ids.ID, s *state) *Staker {
   464  				// insert validator and delegator, then remove the delegator
   465  				var (
   466  					valStartTime = time.Now().Truncate(time.Second).Unix()
   467  					delStartTime = time.Unix(valStartTime, 0).Add(time.Hour).Unix()
   468  					delEndTime   = time.Unix(delStartTime, 0).Add(30 * 24 * time.Hour).Unix()
   469  					valEndTime   = time.Unix(valStartTime, 0).Add(365 * 24 * time.Hour).Unix()
   470  
   471  					validatorsData = txs.Validator{
   472  						NodeID: ids.GenerateTestNodeID(),
   473  						End:    uint64(valEndTime),
   474  						Wght:   1234,
   475  					}
   476  					validatorReward uint64 = 5678
   477  
   478  					delegatorData = txs.Validator{
   479  						NodeID: validatorsData.NodeID,
   480  						End:    uint64(delEndTime),
   481  						Wght:   validatorsData.Wght / 2,
   482  					}
   483  					delegatorReward uint64 = 5432
   484  				)
   485  
   486  				utxVal := createPermissionlessValidatorTx(r, subnetID, validatorsData)
   487  				addPermValTx := &txs.Tx{Unsigned: utxVal}
   488  				r.NoError(addPermValTx.Initialize(txs.Codec))
   489  
   490  				val, err := NewCurrentStaker(
   491  					addPermValTx.ID(),
   492  					utxVal,
   493  					time.Unix(valStartTime, 0),
   494  					validatorReward,
   495  				)
   496  				r.NoError(err)
   497  
   498  				utxDel := createPermissionlessDelegatorTx(subnetID, delegatorData)
   499  				addPermDelTx := &txs.Tx{Unsigned: utxDel}
   500  				r.NoError(addPermDelTx.Initialize(txs.Codec))
   501  
   502  				del, err := NewCurrentStaker(
   503  					addPermDelTx.ID(),
   504  					utxDel,
   505  					time.Unix(delStartTime, 0),
   506  					delegatorReward,
   507  				)
   508  				r.NoError(err)
   509  
   510  				s.PutCurrentValidator(val)
   511  				s.AddTx(addPermValTx, status.Committed) // this is currently needed to reload the staker
   512  
   513  				s.PutCurrentDelegator(del)
   514  				s.AddTx(addPermDelTx, status.Committed) // this is currently needed to reload the staker
   515  				r.NoError(s.Commit())
   516  
   517  				s.DeleteCurrentDelegator(del)
   518  				r.NoError(s.Commit())
   519  
   520  				return del
   521  			},
   522  			checkStakerInState: func(r *require.Assertions, s *state, staker *Staker) {
   523  				delIt, err := s.GetCurrentDelegatorIterator(staker.SubnetID, staker.NodeID)
   524  				r.NoError(err)
   525  				r.False(delIt.Next())
   526  				delIt.Release()
   527  			},
   528  			checkValidatorsSet: func(r *require.Assertions, s *state, staker *Staker) {
   529  				val, err := s.GetCurrentValidator(staker.SubnetID, staker.NodeID)
   530  				r.NoError(err)
   531  
   532  				valsMap := s.cfg.Validators.GetMap(staker.SubnetID)
   533  				r.Len(valsMap, 1)
   534  				valOut, found := valsMap[staker.NodeID]
   535  				r.True(found)
   536  				r.Equal(valOut.NodeID, staker.NodeID)
   537  				r.Equal(valOut.Weight, val.Weight)
   538  			},
   539  			checkValidatorUptimes: func(*require.Assertions, *state, *Staker) {},
   540  			checkDiffs: func(r *require.Assertions, s *state, staker *Staker, height uint64) {
   541  				// validator's weight must decrease of delegator's weight amount
   542  				weightDiffBytes, err := s.validatorWeightDiffsDB.Get(marshalDiffKey(staker.SubnetID, height, staker.NodeID))
   543  				r.NoError(err)
   544  				weightDiff, err := unmarshalWeightDiff(weightDiffBytes)
   545  				r.NoError(err)
   546  				r.Equal(&ValidatorWeightDiff{
   547  					Decrease: true,
   548  					Amount:   staker.Weight,
   549  				}, weightDiff)
   550  			},
   551  		},
   552  		"delete pending validator": {
   553  			storeStaker: func(r *require.Assertions, subnetID ids.ID, s *state) *Staker {
   554  				var (
   555  					startTime = time.Now().Unix()
   556  					endTime   = time.Now().Add(14 * 24 * time.Hour).Unix()
   557  
   558  					validatorsData = txs.Validator{
   559  						NodeID: ids.GenerateTestNodeID(),
   560  						Start:  uint64(startTime),
   561  						End:    uint64(endTime),
   562  						Wght:   1234,
   563  					}
   564  				)
   565  
   566  				utx := createPermissionlessValidatorTx(r, subnetID, validatorsData)
   567  				addPermValTx := &txs.Tx{Unsigned: utx}
   568  				r.NoError(addPermValTx.Initialize(txs.Codec))
   569  
   570  				staker, err := NewPendingStaker(
   571  					addPermValTx.ID(),
   572  					utx,
   573  				)
   574  				r.NoError(err)
   575  
   576  				s.PutPendingValidator(staker)
   577  				s.AddTx(addPermValTx, status.Committed) // this is currently needed to reload the staker
   578  				r.NoError(s.Commit())
   579  
   580  				s.DeletePendingValidator(staker)
   581  				r.NoError(s.Commit())
   582  
   583  				return staker
   584  			},
   585  			checkStakerInState: func(r *require.Assertions, s *state, staker *Staker) {
   586  				_, err := s.GetPendingValidator(staker.SubnetID, staker.NodeID)
   587  				r.ErrorIs(err, database.ErrNotFound)
   588  			},
   589  			checkValidatorsSet: func(r *require.Assertions, s *state, staker *Staker) {
   590  				valsMap := s.cfg.Validators.GetMap(staker.SubnetID)
   591  				r.Empty(valsMap)
   592  			},
   593  			checkValidatorUptimes: func(r *require.Assertions, s *state, staker *Staker) {
   594  				_, _, err := s.GetUptime(staker.NodeID, staker.SubnetID)
   595  				r.ErrorIs(err, database.ErrNotFound)
   596  			},
   597  			checkDiffs: func(r *require.Assertions, s *state, staker *Staker, height uint64) {
   598  				_, err := s.validatorWeightDiffsDB.Get(marshalDiffKey(staker.SubnetID, height, staker.NodeID))
   599  				r.ErrorIs(err, database.ErrNotFound)
   600  
   601  				_, err = s.validatorPublicKeyDiffsDB.Get(marshalDiffKey(staker.SubnetID, height, staker.NodeID))
   602  				r.ErrorIs(err, database.ErrNotFound)
   603  			},
   604  		},
   605  		"delete pending delegator": {
   606  			storeStaker: func(r *require.Assertions, subnetID ids.ID, s *state) *Staker {
   607  				// insert validator and delegator the remove the validator
   608  				var (
   609  					valStartTime = time.Now().Truncate(time.Second).Unix()
   610  					delStartTime = time.Unix(valStartTime, 0).Add(time.Hour).Unix()
   611  					delEndTime   = time.Unix(delStartTime, 0).Add(30 * 24 * time.Hour).Unix()
   612  					valEndTime   = time.Unix(valStartTime, 0).Add(365 * 24 * time.Hour).Unix()
   613  
   614  					validatorsData = txs.Validator{
   615  						NodeID: ids.GenerateTestNodeID(),
   616  						Start:  uint64(valStartTime),
   617  						End:    uint64(valEndTime),
   618  						Wght:   1234,
   619  					}
   620  
   621  					delegatorData = txs.Validator{
   622  						NodeID: validatorsData.NodeID,
   623  						Start:  uint64(delStartTime),
   624  						End:    uint64(delEndTime),
   625  						Wght:   validatorsData.Wght / 2,
   626  					}
   627  				)
   628  
   629  				utxVal := createPermissionlessValidatorTx(r, subnetID, validatorsData)
   630  				addPermValTx := &txs.Tx{Unsigned: utxVal}
   631  				r.NoError(addPermValTx.Initialize(txs.Codec))
   632  
   633  				val, err := NewPendingStaker(addPermValTx.ID(), utxVal)
   634  				r.NoError(err)
   635  
   636  				utxDel := createPermissionlessDelegatorTx(subnetID, delegatorData)
   637  				addPermDelTx := &txs.Tx{Unsigned: utxDel}
   638  				r.NoError(addPermDelTx.Initialize(txs.Codec))
   639  
   640  				del, err := NewPendingStaker(addPermDelTx.ID(), utxDel)
   641  				r.NoError(err)
   642  
   643  				s.PutPendingValidator(val)
   644  				s.AddTx(addPermValTx, status.Committed) // this is currently needed to reload the staker
   645  
   646  				s.PutPendingDelegator(del)
   647  				s.AddTx(addPermDelTx, status.Committed) // this is currently needed to reload the staker
   648  				r.NoError(s.Commit())
   649  
   650  				s.DeletePendingDelegator(del)
   651  				r.NoError(s.Commit())
   652  				return del
   653  			},
   654  			checkStakerInState: func(r *require.Assertions, s *state, staker *Staker) {
   655  				delIt, err := s.GetPendingDelegatorIterator(staker.SubnetID, staker.NodeID)
   656  				r.NoError(err)
   657  				r.False(delIt.Next())
   658  				delIt.Release()
   659  			},
   660  			checkValidatorsSet: func(r *require.Assertions, s *state, staker *Staker) {
   661  				valsMap := s.cfg.Validators.GetMap(staker.SubnetID)
   662  				r.Empty(valsMap)
   663  			},
   664  			checkValidatorUptimes: func(*require.Assertions, *state, *Staker) {},
   665  			checkDiffs:            func(*require.Assertions, *state, *Staker, uint64) {},
   666  		},
   667  	}
   668  
   669  	subnetIDs := []ids.ID{constants.PrimaryNetworkID, ids.GenerateTestID()}
   670  	for _, subnetID := range subnetIDs {
   671  		for name, test := range tests {
   672  			t.Run(fmt.Sprintf("%s - subnetID %s", name, subnetID), func(t *testing.T) {
   673  				require := require.New(t)
   674  
   675  				state, db := newUninitializedState(require)
   676  
   677  				// create and store the staker
   678  				staker := test.storeStaker(require, subnetID, state)
   679  
   680  				// check all relevant data are stored
   681  				test.checkStakerInState(require, state, staker)
   682  				test.checkValidatorsSet(require, state, staker)
   683  				test.checkValidatorUptimes(require, state, staker)
   684  				test.checkDiffs(require, state, staker, 0 /*height*/)
   685  
   686  				// rebuild the state
   687  				rebuiltState := newStateFromDB(require, db)
   688  
   689  				// load relevant quantities
   690  				require.NoError(rebuiltState.loadCurrentValidators())
   691  				require.NoError(rebuiltState.loadPendingValidators())
   692  				require.NoError(rebuiltState.initValidatorSets())
   693  
   694  				// check again that all relevant data are still available in rebuilt state
   695  				test.checkStakerInState(require, state, staker)
   696  				test.checkValidatorsSet(require, state, staker)
   697  				test.checkValidatorUptimes(require, state, staker)
   698  				test.checkDiffs(require, state, staker, 0 /*height*/)
   699  			})
   700  		}
   701  	}
   702  }
   703  
   704  func newInitializedState(require *require.Assertions) State {
   705  	s, _ := newUninitializedState(require)
   706  
   707  	initialValidator := &txs.AddValidatorTx{
   708  		Validator: txs.Validator{
   709  			NodeID: initialNodeID,
   710  			Start:  uint64(initialTime.Unix()),
   711  			End:    uint64(initialValidatorEndTime.Unix()),
   712  			Wght:   units.Avax,
   713  		},
   714  		StakeOuts: []*avax.TransferableOutput{
   715  			{
   716  				Asset: avax.Asset{ID: initialTxID},
   717  				Out: &secp256k1fx.TransferOutput{
   718  					Amt: units.Avax,
   719  				},
   720  			},
   721  		},
   722  		RewardsOwner:     &secp256k1fx.OutputOwners{},
   723  		DelegationShares: reward.PercentDenominator,
   724  	}
   725  	initialValidatorTx := &txs.Tx{Unsigned: initialValidator}
   726  	require.NoError(initialValidatorTx.Initialize(txs.Codec))
   727  
   728  	initialChain := &txs.CreateChainTx{
   729  		SubnetID:   constants.PrimaryNetworkID,
   730  		ChainName:  "x",
   731  		VMID:       constants.AVMID,
   732  		SubnetAuth: &secp256k1fx.Input{},
   733  	}
   734  	initialChainTx := &txs.Tx{Unsigned: initialChain}
   735  	require.NoError(initialChainTx.Initialize(txs.Codec))
   736  
   737  	genesisBlkID := ids.GenerateTestID()
   738  	genesisState := &genesis.Genesis{
   739  		UTXOs: []*genesis.UTXO{
   740  			{
   741  				UTXO: avax.UTXO{
   742  					UTXOID: avax.UTXOID{
   743  						TxID:        initialTxID,
   744  						OutputIndex: 0,
   745  					},
   746  					Asset: avax.Asset{ID: initialTxID},
   747  					Out: &secp256k1fx.TransferOutput{
   748  						Amt: units.Schmeckle,
   749  					},
   750  				},
   751  				Message: nil,
   752  			},
   753  		},
   754  		Validators: []*txs.Tx{
   755  			initialValidatorTx,
   756  		},
   757  		Chains: []*txs.Tx{
   758  			initialChainTx,
   759  		},
   760  		Timestamp:     uint64(initialTime.Unix()),
   761  		InitialSupply: units.Schmeckle + units.Avax,
   762  	}
   763  
   764  	genesisBlk, err := block.NewApricotCommitBlock(genesisBlkID, 0)
   765  	require.NoError(err)
   766  	require.NoError(s.syncGenesis(genesisBlk, genesisState))
   767  
   768  	return s
   769  }
   770  
   771  func newUninitializedState(require *require.Assertions) (*state, database.Database) {
   772  	db := memdb.New()
   773  	return newStateFromDB(require, db), db
   774  }
   775  
   776  func newStateFromDB(require *require.Assertions, db database.Database) *state {
   777  	execCfg, _ := config.GetExecutionConfig(nil)
   778  	state, err := newState(
   779  		db,
   780  		metrics.Noop,
   781  		&config.Config{
   782  			Validators: validators.NewManager(),
   783  		},
   784  		execCfg,
   785  		&snow.Context{},
   786  		prometheus.NewRegistry(),
   787  		reward.NewCalculator(reward.Config{
   788  			MaxConsumptionRate: .12 * reward.PercentDenominator,
   789  			MinConsumptionRate: .1 * reward.PercentDenominator,
   790  			MintingPeriod:      365 * 24 * time.Hour,
   791  			SupplyCap:          720 * units.MegaAvax,
   792  		}),
   793  	)
   794  	require.NoError(err)
   795  	require.NotNil(state)
   796  	return state
   797  }
   798  
   799  func createPermissionlessValidatorTx(r *require.Assertions, subnetID ids.ID, validatorsData txs.Validator) *txs.AddPermissionlessValidatorTx {
   800  	var sig signer.Signer = &signer.Empty{}
   801  	if subnetID == constants.PrimaryNetworkID {
   802  		sk, err := bls.NewSecretKey()
   803  		r.NoError(err)
   804  		sig = signer.NewProofOfPossession(sk)
   805  	}
   806  
   807  	return &txs.AddPermissionlessValidatorTx{
   808  		BaseTx: txs.BaseTx{
   809  			BaseTx: avax.BaseTx{
   810  				NetworkID:    constants.MainnetID,
   811  				BlockchainID: constants.PlatformChainID,
   812  				Outs:         []*avax.TransferableOutput{},
   813  				Ins: []*avax.TransferableInput{
   814  					{
   815  						UTXOID: avax.UTXOID{
   816  							TxID:        ids.GenerateTestID(),
   817  							OutputIndex: 1,
   818  						},
   819  						Asset: avax.Asset{
   820  							ID: ids.GenerateTestID(),
   821  						},
   822  						In: &secp256k1fx.TransferInput{
   823  							Amt: 2 * units.KiloAvax,
   824  							Input: secp256k1fx.Input{
   825  								SigIndices: []uint32{1},
   826  							},
   827  						},
   828  					},
   829  				},
   830  				Memo: types.JSONByteSlice{},
   831  			},
   832  		},
   833  		Validator: validatorsData,
   834  		Subnet:    subnetID,
   835  		Signer:    sig,
   836  
   837  		StakeOuts: []*avax.TransferableOutput{
   838  			{
   839  				Asset: avax.Asset{
   840  					ID: ids.GenerateTestID(),
   841  				},
   842  				Out: &secp256k1fx.TransferOutput{
   843  					Amt: 2 * units.KiloAvax,
   844  					OutputOwners: secp256k1fx.OutputOwners{
   845  						Locktime:  0,
   846  						Threshold: 1,
   847  						Addrs: []ids.ShortID{
   848  							ids.GenerateTestShortID(),
   849  						},
   850  					},
   851  				},
   852  			},
   853  		},
   854  		ValidatorRewardsOwner: &secp256k1fx.OutputOwners{
   855  			Locktime:  0,
   856  			Threshold: 1,
   857  			Addrs: []ids.ShortID{
   858  				ids.GenerateTestShortID(),
   859  			},
   860  		},
   861  		DelegatorRewardsOwner: &secp256k1fx.OutputOwners{
   862  			Locktime:  0,
   863  			Threshold: 1,
   864  			Addrs: []ids.ShortID{
   865  				ids.GenerateTestShortID(),
   866  			},
   867  		},
   868  		DelegationShares: reward.PercentDenominator,
   869  	}
   870  }
   871  
   872  func createPermissionlessDelegatorTx(subnetID ids.ID, delegatorData txs.Validator) *txs.AddPermissionlessDelegatorTx {
   873  	return &txs.AddPermissionlessDelegatorTx{
   874  		BaseTx: txs.BaseTx{
   875  			BaseTx: avax.BaseTx{
   876  				NetworkID:    constants.MainnetID,
   877  				BlockchainID: constants.PlatformChainID,
   878  				Outs:         []*avax.TransferableOutput{},
   879  				Ins: []*avax.TransferableInput{
   880  					{
   881  						UTXOID: avax.UTXOID{
   882  							TxID:        ids.GenerateTestID(),
   883  							OutputIndex: 1,
   884  						},
   885  						Asset: avax.Asset{
   886  							ID: ids.GenerateTestID(),
   887  						},
   888  						In: &secp256k1fx.TransferInput{
   889  							Amt: 2 * units.KiloAvax,
   890  							Input: secp256k1fx.Input{
   891  								SigIndices: []uint32{1},
   892  							},
   893  						},
   894  					},
   895  				},
   896  				Memo: types.JSONByteSlice{},
   897  			},
   898  		},
   899  		Validator: delegatorData,
   900  		Subnet:    subnetID,
   901  
   902  		StakeOuts: []*avax.TransferableOutput{
   903  			{
   904  				Asset: avax.Asset{
   905  					ID: ids.GenerateTestID(),
   906  				},
   907  				Out: &secp256k1fx.TransferOutput{
   908  					Amt: 2 * units.KiloAvax,
   909  					OutputOwners: secp256k1fx.OutputOwners{
   910  						Locktime:  0,
   911  						Threshold: 1,
   912  						Addrs: []ids.ShortID{
   913  							ids.GenerateTestShortID(),
   914  						},
   915  					},
   916  				},
   917  			},
   918  		},
   919  		DelegationRewardsOwner: &secp256k1fx.OutputOwners{
   920  			Locktime:  0,
   921  			Threshold: 1,
   922  			Addrs: []ids.ShortID{
   923  				ids.GenerateTestShortID(),
   924  			},
   925  		},
   926  	}
   927  }
   928  
   929  func TestValidatorWeightDiff(t *testing.T) {
   930  	type test struct {
   931  		name        string
   932  		ops         []func(*ValidatorWeightDiff) error
   933  		expected    *ValidatorWeightDiff
   934  		expectedErr error
   935  	}
   936  
   937  	tests := []test{
   938  		{
   939  			name:        "no ops",
   940  			ops:         []func(*ValidatorWeightDiff) error{},
   941  			expected:    &ValidatorWeightDiff{},
   942  			expectedErr: nil,
   943  		},
   944  		{
   945  			name: "simple decrease",
   946  			ops: []func(*ValidatorWeightDiff) error{
   947  				func(d *ValidatorWeightDiff) error {
   948  					return d.Add(true, 1)
   949  				},
   950  				func(d *ValidatorWeightDiff) error {
   951  					return d.Add(true, 1)
   952  				},
   953  			},
   954  			expected: &ValidatorWeightDiff{
   955  				Decrease: true,
   956  				Amount:   2,
   957  			},
   958  			expectedErr: nil,
   959  		},
   960  		{
   961  			name: "decrease overflow",
   962  			ops: []func(*ValidatorWeightDiff) error{
   963  				func(d *ValidatorWeightDiff) error {
   964  					return d.Add(true, math.MaxUint64)
   965  				},
   966  				func(d *ValidatorWeightDiff) error {
   967  					return d.Add(true, 1)
   968  				},
   969  			},
   970  			expected:    &ValidatorWeightDiff{},
   971  			expectedErr: safemath.ErrOverflow,
   972  		},
   973  		{
   974  			name: "simple increase",
   975  			ops: []func(*ValidatorWeightDiff) error{
   976  				func(d *ValidatorWeightDiff) error {
   977  					return d.Add(false, 1)
   978  				},
   979  				func(d *ValidatorWeightDiff) error {
   980  					return d.Add(false, 1)
   981  				},
   982  			},
   983  			expected: &ValidatorWeightDiff{
   984  				Decrease: false,
   985  				Amount:   2,
   986  			},
   987  			expectedErr: nil,
   988  		},
   989  		{
   990  			name: "increase overflow",
   991  			ops: []func(*ValidatorWeightDiff) error{
   992  				func(d *ValidatorWeightDiff) error {
   993  					return d.Add(false, math.MaxUint64)
   994  				},
   995  				func(d *ValidatorWeightDiff) error {
   996  					return d.Add(false, 1)
   997  				},
   998  			},
   999  			expected:    &ValidatorWeightDiff{},
  1000  			expectedErr: safemath.ErrOverflow,
  1001  		},
  1002  		{
  1003  			name: "varied use",
  1004  			ops: []func(*ValidatorWeightDiff) error{
  1005  				// Add to 0
  1006  				func(d *ValidatorWeightDiff) error {
  1007  					return d.Add(false, 2) // Value 2
  1008  				},
  1009  				// Subtract from positive number
  1010  				func(d *ValidatorWeightDiff) error {
  1011  					return d.Add(true, 1) // Value 1
  1012  				},
  1013  				// Subtract from positive number
  1014  				// to make it negative
  1015  				func(d *ValidatorWeightDiff) error {
  1016  					return d.Add(true, 3) // Value -2
  1017  				},
  1018  				// Subtract from a negative number
  1019  				func(d *ValidatorWeightDiff) error {
  1020  					return d.Add(true, 3) // Value -5
  1021  				},
  1022  				// Add to a negative number
  1023  				func(d *ValidatorWeightDiff) error {
  1024  					return d.Add(false, 1) // Value -4
  1025  				},
  1026  				// Add to a negative number
  1027  				// to make it positive
  1028  				func(d *ValidatorWeightDiff) error {
  1029  					return d.Add(false, 5) // Value 1
  1030  				},
  1031  				// Add to a positive number
  1032  				func(d *ValidatorWeightDiff) error {
  1033  					return d.Add(false, 1) // Value 2
  1034  				},
  1035  				// Get to zero
  1036  				func(d *ValidatorWeightDiff) error {
  1037  					return d.Add(true, 2) // Value 0
  1038  				},
  1039  				// Subtract from zero
  1040  				func(d *ValidatorWeightDiff) error {
  1041  					return d.Add(true, 2) // Value -2
  1042  				},
  1043  			},
  1044  			expected: &ValidatorWeightDiff{
  1045  				Decrease: true,
  1046  				Amount:   2,
  1047  			},
  1048  			expectedErr: nil,
  1049  		},
  1050  	}
  1051  
  1052  	for _, tt := range tests {
  1053  		t.Run(tt.name, func(t *testing.T) {
  1054  			require := require.New(t)
  1055  			diff := &ValidatorWeightDiff{}
  1056  			errs := wrappers.Errs{}
  1057  			for _, op := range tt.ops {
  1058  				errs.Add(op(diff))
  1059  			}
  1060  			require.ErrorIs(errs.Err, tt.expectedErr)
  1061  			if tt.expectedErr != nil {
  1062  				return
  1063  			}
  1064  			require.Equal(tt.expected, diff)
  1065  		})
  1066  	}
  1067  }
  1068  
  1069  // Tests PutCurrentValidator, DeleteCurrentValidator, GetCurrentValidator,
  1070  // ApplyValidatorWeightDiffs, ApplyValidatorPublicKeyDiffs
  1071  func TestStateAddRemoveValidator(t *testing.T) {
  1072  	require := require.New(t)
  1073  
  1074  	state := newInitializedState(require)
  1075  
  1076  	var (
  1077  		numNodes  = 3
  1078  		subnetID  = ids.GenerateTestID()
  1079  		startTime = time.Now()
  1080  		endTime   = startTime.Add(24 * time.Hour)
  1081  		stakers   = make([]Staker, numNodes)
  1082  	)
  1083  	for i := 0; i < numNodes; i++ {
  1084  		stakers[i] = Staker{
  1085  			TxID:            ids.GenerateTestID(),
  1086  			NodeID:          ids.GenerateTestNodeID(),
  1087  			Weight:          uint64(i + 1),
  1088  			StartTime:       startTime.Add(time.Duration(i) * time.Second),
  1089  			EndTime:         endTime.Add(time.Duration(i) * time.Second),
  1090  			PotentialReward: uint64(i + 1),
  1091  		}
  1092  		if i%2 == 0 {
  1093  			stakers[i].SubnetID = subnetID
  1094  		} else {
  1095  			sk, err := bls.NewSecretKey()
  1096  			require.NoError(err)
  1097  			stakers[i].PublicKey = bls.PublicFromSecretKey(sk)
  1098  			stakers[i].SubnetID = constants.PrimaryNetworkID
  1099  		}
  1100  	}
  1101  
  1102  	type diff struct {
  1103  		addedValidators   []Staker
  1104  		addedDelegators   []Staker
  1105  		removedDelegators []Staker
  1106  		removedValidators []Staker
  1107  
  1108  		expectedPrimaryValidatorSet map[ids.NodeID]*validators.GetValidatorOutput
  1109  		expectedSubnetValidatorSet  map[ids.NodeID]*validators.GetValidatorOutput
  1110  	}
  1111  	diffs := []diff{
  1112  		{
  1113  			// Do nothing
  1114  			expectedPrimaryValidatorSet: map[ids.NodeID]*validators.GetValidatorOutput{},
  1115  			expectedSubnetValidatorSet:  map[ids.NodeID]*validators.GetValidatorOutput{},
  1116  		},
  1117  		{
  1118  			// Add a subnet validator
  1119  			addedValidators:             []Staker{stakers[0]},
  1120  			expectedPrimaryValidatorSet: map[ids.NodeID]*validators.GetValidatorOutput{},
  1121  			expectedSubnetValidatorSet: map[ids.NodeID]*validators.GetValidatorOutput{
  1122  				stakers[0].NodeID: {
  1123  					NodeID: stakers[0].NodeID,
  1124  					Weight: stakers[0].Weight,
  1125  				},
  1126  			},
  1127  		},
  1128  		{
  1129  			// Remove a subnet validator
  1130  			removedValidators:           []Staker{stakers[0]},
  1131  			expectedPrimaryValidatorSet: map[ids.NodeID]*validators.GetValidatorOutput{},
  1132  			expectedSubnetValidatorSet:  map[ids.NodeID]*validators.GetValidatorOutput{},
  1133  		},
  1134  		{ // Add a primary network validator
  1135  			addedValidators: []Staker{stakers[1]},
  1136  			expectedPrimaryValidatorSet: map[ids.NodeID]*validators.GetValidatorOutput{
  1137  				stakers[1].NodeID: {
  1138  					NodeID:    stakers[1].NodeID,
  1139  					PublicKey: stakers[1].PublicKey,
  1140  					Weight:    stakers[1].Weight,
  1141  				},
  1142  			},
  1143  			expectedSubnetValidatorSet: map[ids.NodeID]*validators.GetValidatorOutput{},
  1144  		},
  1145  		{
  1146  			// Do nothing
  1147  			expectedPrimaryValidatorSet: map[ids.NodeID]*validators.GetValidatorOutput{
  1148  				stakers[1].NodeID: {
  1149  					NodeID:    stakers[1].NodeID,
  1150  					PublicKey: stakers[1].PublicKey,
  1151  					Weight:    stakers[1].Weight,
  1152  				},
  1153  			},
  1154  			expectedSubnetValidatorSet: map[ids.NodeID]*validators.GetValidatorOutput{},
  1155  		},
  1156  		{ // Remove a primary network validator
  1157  			removedValidators:           []Staker{stakers[1]},
  1158  			expectedPrimaryValidatorSet: map[ids.NodeID]*validators.GetValidatorOutput{},
  1159  			expectedSubnetValidatorSet:  map[ids.NodeID]*validators.GetValidatorOutput{},
  1160  		},
  1161  		{
  1162  			// Add 2 subnet validators and a primary network validator
  1163  			addedValidators: []Staker{stakers[0], stakers[1], stakers[2]},
  1164  			expectedPrimaryValidatorSet: map[ids.NodeID]*validators.GetValidatorOutput{
  1165  				stakers[1].NodeID: {
  1166  					NodeID:    stakers[1].NodeID,
  1167  					PublicKey: stakers[1].PublicKey,
  1168  					Weight:    stakers[1].Weight,
  1169  				},
  1170  			},
  1171  			expectedSubnetValidatorSet: map[ids.NodeID]*validators.GetValidatorOutput{
  1172  				stakers[0].NodeID: {
  1173  					NodeID: stakers[0].NodeID,
  1174  					Weight: stakers[0].Weight,
  1175  				},
  1176  				stakers[2].NodeID: {
  1177  					NodeID: stakers[2].NodeID,
  1178  					Weight: stakers[2].Weight,
  1179  				},
  1180  			},
  1181  		},
  1182  		{
  1183  			// Remove 2 subnet validators and a primary network validator.
  1184  			removedValidators:           []Staker{stakers[0], stakers[1], stakers[2]},
  1185  			expectedPrimaryValidatorSet: map[ids.NodeID]*validators.GetValidatorOutput{},
  1186  			expectedSubnetValidatorSet:  map[ids.NodeID]*validators.GetValidatorOutput{},
  1187  		},
  1188  	}
  1189  	for currentIndex, diff := range diffs {
  1190  		for _, added := range diff.addedValidators {
  1191  			added := added
  1192  			state.PutCurrentValidator(&added)
  1193  		}
  1194  		for _, added := range diff.addedDelegators {
  1195  			added := added
  1196  			state.PutCurrentDelegator(&added)
  1197  		}
  1198  		for _, removed := range diff.removedDelegators {
  1199  			removed := removed
  1200  			state.DeleteCurrentDelegator(&removed)
  1201  		}
  1202  		for _, removed := range diff.removedValidators {
  1203  			removed := removed
  1204  			state.DeleteCurrentValidator(&removed)
  1205  		}
  1206  
  1207  		currentHeight := uint64(currentIndex + 1)
  1208  		state.SetHeight(currentHeight)
  1209  
  1210  		require.NoError(state.Commit())
  1211  
  1212  		for _, added := range diff.addedValidators {
  1213  			gotValidator, err := state.GetCurrentValidator(added.SubnetID, added.NodeID)
  1214  			require.NoError(err)
  1215  			require.Equal(added, *gotValidator)
  1216  		}
  1217  
  1218  		for _, removed := range diff.removedValidators {
  1219  			_, err := state.GetCurrentValidator(removed.SubnetID, removed.NodeID)
  1220  			require.ErrorIs(err, database.ErrNotFound)
  1221  		}
  1222  
  1223  		for i := 0; i < currentIndex; i++ {
  1224  			prevDiff := diffs[i]
  1225  			prevHeight := uint64(i + 1)
  1226  
  1227  			primaryValidatorSet := copyValidatorSet(diff.expectedPrimaryValidatorSet)
  1228  			require.NoError(state.ApplyValidatorWeightDiffs(
  1229  				context.Background(),
  1230  				primaryValidatorSet,
  1231  				currentHeight,
  1232  				prevHeight+1,
  1233  				constants.PrimaryNetworkID,
  1234  			))
  1235  			requireEqualWeightsValidatorSet(require, prevDiff.expectedPrimaryValidatorSet, primaryValidatorSet)
  1236  
  1237  			require.NoError(state.ApplyValidatorPublicKeyDiffs(
  1238  				context.Background(),
  1239  				primaryValidatorSet,
  1240  				currentHeight,
  1241  				prevHeight+1,
  1242  			))
  1243  			requireEqualPublicKeysValidatorSet(require, prevDiff.expectedPrimaryValidatorSet, primaryValidatorSet)
  1244  
  1245  			subnetValidatorSet := copyValidatorSet(diff.expectedSubnetValidatorSet)
  1246  			require.NoError(state.ApplyValidatorWeightDiffs(
  1247  				context.Background(),
  1248  				subnetValidatorSet,
  1249  				currentHeight,
  1250  				prevHeight+1,
  1251  				subnetID,
  1252  			))
  1253  			requireEqualWeightsValidatorSet(require, prevDiff.expectedSubnetValidatorSet, subnetValidatorSet)
  1254  		}
  1255  	}
  1256  }
  1257  
  1258  func copyValidatorSet(
  1259  	input map[ids.NodeID]*validators.GetValidatorOutput,
  1260  ) map[ids.NodeID]*validators.GetValidatorOutput {
  1261  	result := make(map[ids.NodeID]*validators.GetValidatorOutput, len(input))
  1262  	for nodeID, vdr := range input {
  1263  		vdrCopy := *vdr
  1264  		result[nodeID] = &vdrCopy
  1265  	}
  1266  	return result
  1267  }
  1268  
  1269  func requireEqualWeightsValidatorSet(
  1270  	require *require.Assertions,
  1271  	expected map[ids.NodeID]*validators.GetValidatorOutput,
  1272  	actual map[ids.NodeID]*validators.GetValidatorOutput,
  1273  ) {
  1274  	require.Len(actual, len(expected))
  1275  	for nodeID, expectedVdr := range expected {
  1276  		require.Contains(actual, nodeID)
  1277  
  1278  		actualVdr := actual[nodeID]
  1279  		require.Equal(expectedVdr.NodeID, actualVdr.NodeID)
  1280  		require.Equal(expectedVdr.Weight, actualVdr.Weight)
  1281  	}
  1282  }
  1283  
  1284  func requireEqualPublicKeysValidatorSet(
  1285  	require *require.Assertions,
  1286  	expected map[ids.NodeID]*validators.GetValidatorOutput,
  1287  	actual map[ids.NodeID]*validators.GetValidatorOutput,
  1288  ) {
  1289  	require.Len(actual, len(expected))
  1290  	for nodeID, expectedVdr := range expected {
  1291  		require.Contains(actual, nodeID)
  1292  
  1293  		actualVdr := actual[nodeID]
  1294  		require.Equal(expectedVdr.NodeID, actualVdr.NodeID)
  1295  		require.Equal(expectedVdr.PublicKey, actualVdr.PublicKey)
  1296  	}
  1297  }
  1298  
  1299  func TestParsedStateBlock(t *testing.T) {
  1300  	var (
  1301  		require = require.New(t)
  1302  		blks    = makeBlocks(require)
  1303  	)
  1304  
  1305  	for _, blk := range blks {
  1306  		stBlk := stateBlk{
  1307  			Bytes:  blk.Bytes(),
  1308  			Status: choices.Accepted,
  1309  		}
  1310  
  1311  		stBlkBytes, err := block.GenesisCodec.Marshal(block.CodecVersion, &stBlk)
  1312  		require.NoError(err)
  1313  
  1314  		gotBlk, isStateBlk, err := parseStoredBlock(stBlkBytes)
  1315  		require.NoError(err)
  1316  		require.True(isStateBlk)
  1317  		require.Equal(blk.ID(), gotBlk.ID())
  1318  
  1319  		gotBlk, isStateBlk, err = parseStoredBlock(blk.Bytes())
  1320  		require.NoError(err)
  1321  		require.False(isStateBlk)
  1322  		require.Equal(blk.ID(), gotBlk.ID())
  1323  	}
  1324  }
  1325  
  1326  func TestReindexBlocks(t *testing.T) {
  1327  	var (
  1328  		require = require.New(t)
  1329  		s       = newInitializedState(require).(*state)
  1330  		blks    = makeBlocks(require)
  1331  	)
  1332  
  1333  	// Populate the blocks using the legacy format.
  1334  	for _, blk := range blks {
  1335  		stBlk := stateBlk{
  1336  			Bytes:  blk.Bytes(),
  1337  			Status: choices.Accepted,
  1338  		}
  1339  		stBlkBytes, err := block.GenesisCodec.Marshal(block.CodecVersion, &stBlk)
  1340  		require.NoError(err)
  1341  
  1342  		blkID := blk.ID()
  1343  		require.NoError(s.blockDB.Put(blkID[:], stBlkBytes))
  1344  	}
  1345  
  1346  	// Convert the indices to the new format.
  1347  	require.NoError(s.ReindexBlocks(&sync.Mutex{}, logging.NoLog{}))
  1348  
  1349  	// Verify that the blocks are stored in the new format.
  1350  	for _, blk := range blks {
  1351  		blkID := blk.ID()
  1352  		blkBytes, err := s.blockDB.Get(blkID[:])
  1353  		require.NoError(err)
  1354  
  1355  		parsedBlk, err := block.Parse(block.GenesisCodec, blkBytes)
  1356  		require.NoError(err)
  1357  		require.Equal(blkID, parsedBlk.ID())
  1358  	}
  1359  
  1360  	// Verify that the flag has been written to disk to allow skipping future
  1361  	// reindexings.
  1362  	reindexed, err := s.singletonDB.Has(BlocksReindexedKey)
  1363  	require.NoError(err)
  1364  	require.True(reindexed)
  1365  }
  1366  
  1367  func TestStateSubnetOwner(t *testing.T) {
  1368  	require := require.New(t)
  1369  
  1370  	state := newInitializedState(require)
  1371  	ctrl := gomock.NewController(t)
  1372  
  1373  	var (
  1374  		owner1 = fx.NewMockOwner(ctrl)
  1375  		owner2 = fx.NewMockOwner(ctrl)
  1376  
  1377  		createSubnetTx = &txs.Tx{
  1378  			Unsigned: &txs.CreateSubnetTx{
  1379  				BaseTx: txs.BaseTx{},
  1380  				Owner:  owner1,
  1381  			},
  1382  		}
  1383  
  1384  		subnetID = createSubnetTx.ID()
  1385  	)
  1386  
  1387  	owner, err := state.GetSubnetOwner(subnetID)
  1388  	require.ErrorIs(err, database.ErrNotFound)
  1389  	require.Nil(owner)
  1390  
  1391  	state.AddSubnet(subnetID)
  1392  	state.SetSubnetOwner(subnetID, owner1)
  1393  
  1394  	owner, err = state.GetSubnetOwner(subnetID)
  1395  	require.NoError(err)
  1396  	require.Equal(owner1, owner)
  1397  
  1398  	state.SetSubnetOwner(subnetID, owner2)
  1399  	owner, err = state.GetSubnetOwner(subnetID)
  1400  	require.NoError(err)
  1401  	require.Equal(owner2, owner)
  1402  }
  1403  
  1404  func makeBlocks(require *require.Assertions) []block.Block {
  1405  	var blks []block.Block
  1406  	{
  1407  		blk, err := block.NewApricotAbortBlock(ids.GenerateTestID(), 1000)
  1408  		require.NoError(err)
  1409  		blks = append(blks, blk)
  1410  	}
  1411  
  1412  	{
  1413  		blk, err := block.NewApricotAtomicBlock(ids.GenerateTestID(), 1000, &txs.Tx{
  1414  			Unsigned: &txs.AdvanceTimeTx{
  1415  				Time: 1000,
  1416  			},
  1417  		})
  1418  		require.NoError(err)
  1419  		blks = append(blks, blk)
  1420  	}
  1421  
  1422  	{
  1423  		blk, err := block.NewApricotCommitBlock(ids.GenerateTestID(), 1000)
  1424  		require.NoError(err)
  1425  		blks = append(blks, blk)
  1426  	}
  1427  
  1428  	{
  1429  		tx := &txs.Tx{
  1430  			Unsigned: &txs.RewardValidatorTx{
  1431  				TxID: ids.GenerateTestID(),
  1432  			},
  1433  		}
  1434  		require.NoError(tx.Initialize(txs.Codec))
  1435  		blk, err := block.NewApricotProposalBlock(ids.GenerateTestID(), 1000, tx)
  1436  		require.NoError(err)
  1437  		blks = append(blks, blk)
  1438  	}
  1439  
  1440  	{
  1441  		tx := &txs.Tx{
  1442  			Unsigned: &txs.RewardValidatorTx{
  1443  				TxID: ids.GenerateTestID(),
  1444  			},
  1445  		}
  1446  		require.NoError(tx.Initialize(txs.Codec))
  1447  		blk, err := block.NewApricotStandardBlock(ids.GenerateTestID(), 1000, []*txs.Tx{tx})
  1448  		require.NoError(err)
  1449  		blks = append(blks, blk)
  1450  	}
  1451  
  1452  	{
  1453  		blk, err := block.NewBanffAbortBlock(time.Now(), ids.GenerateTestID(), 1000)
  1454  		require.NoError(err)
  1455  		blks = append(blks, blk)
  1456  	}
  1457  
  1458  	{
  1459  		blk, err := block.NewBanffCommitBlock(time.Now(), ids.GenerateTestID(), 1000)
  1460  		require.NoError(err)
  1461  		blks = append(blks, blk)
  1462  	}
  1463  
  1464  	{
  1465  		tx := &txs.Tx{
  1466  			Unsigned: &txs.RewardValidatorTx{
  1467  				TxID: ids.GenerateTestID(),
  1468  			},
  1469  		}
  1470  		require.NoError(tx.Initialize(txs.Codec))
  1471  
  1472  		blk, err := block.NewBanffProposalBlock(time.Now(), ids.GenerateTestID(), 1000, tx, []*txs.Tx{})
  1473  		require.NoError(err)
  1474  		blks = append(blks, blk)
  1475  	}
  1476  
  1477  	{
  1478  		tx := &txs.Tx{
  1479  			Unsigned: &txs.RewardValidatorTx{
  1480  				TxID: ids.GenerateTestID(),
  1481  			},
  1482  		}
  1483  		require.NoError(tx.Initialize(txs.Codec))
  1484  
  1485  		blk, err := block.NewBanffStandardBlock(time.Now(), ids.GenerateTestID(), 1000, []*txs.Tx{tx})
  1486  		require.NoError(err)
  1487  		blks = append(blks, blk)
  1488  	}
  1489  	return blks
  1490  }