github.com/ava-labs/avalanchego@v1.11.11/vms/platformvm/validators/manager_benchmark_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 validators
     5  
     6  import (
     7  	"context"
     8  	"math/rand"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/prometheus/client_golang/prometheus"
    13  	"github.com/stretchr/testify/require"
    14  
    15  	"github.com/ava-labs/avalanchego/database/leveldb"
    16  	"github.com/ava-labs/avalanchego/ids"
    17  	"github.com/ava-labs/avalanchego/snow/validators"
    18  	"github.com/ava-labs/avalanchego/utils/constants"
    19  	"github.com/ava-labs/avalanchego/utils/crypto/bls"
    20  	"github.com/ava-labs/avalanchego/utils/logging"
    21  	"github.com/ava-labs/avalanchego/utils/timer/mockable"
    22  	"github.com/ava-labs/avalanchego/utils/units"
    23  	"github.com/ava-labs/avalanchego/vms/platformvm/block"
    24  	"github.com/ava-labs/avalanchego/vms/platformvm/config"
    25  	"github.com/ava-labs/avalanchego/vms/platformvm/genesis/genesistest"
    26  	"github.com/ava-labs/avalanchego/vms/platformvm/metrics"
    27  	"github.com/ava-labs/avalanchego/vms/platformvm/state"
    28  	"github.com/ava-labs/avalanchego/vms/platformvm/state/statetest"
    29  	"github.com/ava-labs/avalanchego/vms/platformvm/txs"
    30  )
    31  
    32  // BenchmarkGetValidatorSet generates 10k diffs and calculates the time to
    33  // generate the genesis validator set by applying them.
    34  //
    35  // This generates a single diff for each height. In practice there could be
    36  // multiple or zero diffs at a given height.
    37  //
    38  // Note: BenchmarkGetValidatorSet gets the validator set of a subnet rather than
    39  // the primary network because the primary network performs caching that would
    40  // interfere with the benchmark.
    41  func BenchmarkGetValidatorSet(b *testing.B) {
    42  	require := require.New(b)
    43  
    44  	db, err := leveldb.New(
    45  		b.TempDir(),
    46  		nil,
    47  		logging.NoLog{},
    48  		prometheus.NewRegistry(),
    49  	)
    50  	require.NoError(err)
    51  	defer func() {
    52  		require.NoError(db.Close())
    53  	}()
    54  
    55  	vdrs := validators.NewManager()
    56  	s := statetest.New(b, statetest.Config{
    57  		DB:         db,
    58  		Validators: vdrs,
    59  	})
    60  
    61  	m := NewManager(
    62  		logging.NoLog{},
    63  		config.Config{
    64  			Validators: vdrs,
    65  		},
    66  		s,
    67  		metrics.Noop,
    68  		new(mockable.Clock),
    69  	)
    70  
    71  	var (
    72  		nodeIDs       []ids.NodeID
    73  		currentHeight uint64
    74  	)
    75  	for i := 0; i < 50; i++ {
    76  		currentHeight++
    77  		nodeID, err := addPrimaryValidator(s, genesistest.DefaultValidatorStartTime, genesistest.DefaultValidatorEndTime, currentHeight)
    78  		require.NoError(err)
    79  		nodeIDs = append(nodeIDs, nodeID)
    80  	}
    81  	subnetID := ids.GenerateTestID()
    82  	for _, nodeID := range nodeIDs {
    83  		currentHeight++
    84  		require.NoError(addSubnetValidator(s, subnetID, genesistest.DefaultValidatorStartTime, genesistest.DefaultValidatorEndTime, nodeID, currentHeight))
    85  	}
    86  	for i := 0; i < 9900; i++ {
    87  		currentHeight++
    88  		require.NoError(addSubnetDelegator(s, subnetID, genesistest.DefaultValidatorStartTime, genesistest.DefaultValidatorEndTime, nodeIDs, currentHeight))
    89  	}
    90  
    91  	ctx := context.Background()
    92  	height, err := m.GetCurrentHeight(ctx)
    93  	require.NoError(err)
    94  	require.Equal(currentHeight, height)
    95  
    96  	b.ResetTimer()
    97  
    98  	for i := 0; i < b.N; i++ {
    99  		_, err := m.GetValidatorSet(ctx, 0, subnetID)
   100  		require.NoError(err)
   101  	}
   102  
   103  	b.StopTimer()
   104  }
   105  
   106  func addPrimaryValidator(
   107  	s state.State,
   108  	startTime time.Time,
   109  	endTime time.Time,
   110  	height uint64,
   111  ) (ids.NodeID, error) {
   112  	sk, err := bls.NewSecretKey()
   113  	if err != nil {
   114  		return ids.EmptyNodeID, err
   115  	}
   116  
   117  	nodeID := ids.GenerateTestNodeID()
   118  	if err := s.PutCurrentValidator(&state.Staker{
   119  		TxID:            ids.GenerateTestID(),
   120  		NodeID:          nodeID,
   121  		PublicKey:       bls.PublicFromSecretKey(sk),
   122  		SubnetID:        constants.PrimaryNetworkID,
   123  		Weight:          2 * units.MegaAvax,
   124  		StartTime:       startTime,
   125  		EndTime:         endTime,
   126  		PotentialReward: 0,
   127  		NextTime:        endTime,
   128  		Priority:        txs.PrimaryNetworkValidatorCurrentPriority,
   129  	}); err != nil {
   130  		return ids.EmptyNodeID, err
   131  	}
   132  
   133  	blk, err := block.NewBanffStandardBlock(startTime, ids.GenerateTestID(), height, nil)
   134  	if err != nil {
   135  		return ids.EmptyNodeID, err
   136  	}
   137  
   138  	s.AddStatelessBlock(blk)
   139  	s.SetHeight(height)
   140  	return nodeID, s.Commit()
   141  }
   142  
   143  func addSubnetValidator(
   144  	s state.State,
   145  	subnetID ids.ID,
   146  	startTime time.Time,
   147  	endTime time.Time,
   148  	nodeID ids.NodeID,
   149  	height uint64,
   150  ) error {
   151  	if err := s.PutCurrentValidator(&state.Staker{
   152  		TxID:            ids.GenerateTestID(),
   153  		NodeID:          nodeID,
   154  		SubnetID:        subnetID,
   155  		Weight:          1 * units.Avax,
   156  		StartTime:       startTime,
   157  		EndTime:         endTime,
   158  		PotentialReward: 0,
   159  		NextTime:        endTime,
   160  		Priority:        txs.SubnetPermissionlessValidatorCurrentPriority,
   161  	}); err != nil {
   162  		return err
   163  	}
   164  
   165  	blk, err := block.NewBanffStandardBlock(startTime, ids.GenerateTestID(), height, nil)
   166  	if err != nil {
   167  		return err
   168  	}
   169  
   170  	s.AddStatelessBlock(blk)
   171  	s.SetHeight(height)
   172  	return s.Commit()
   173  }
   174  
   175  func addSubnetDelegator(
   176  	s state.State,
   177  	subnetID ids.ID,
   178  	startTime time.Time,
   179  	endTime time.Time,
   180  	nodeIDs []ids.NodeID,
   181  	height uint64,
   182  ) error {
   183  	i := rand.Intn(len(nodeIDs)) //#nosec G404
   184  	nodeID := nodeIDs[i]
   185  	s.PutCurrentDelegator(&state.Staker{
   186  		TxID:            ids.GenerateTestID(),
   187  		NodeID:          nodeID,
   188  		SubnetID:        subnetID,
   189  		Weight:          1 * units.Avax,
   190  		StartTime:       startTime,
   191  		EndTime:         endTime,
   192  		PotentialReward: 0,
   193  		NextTime:        endTime,
   194  		Priority:        txs.SubnetPermissionlessDelegatorCurrentPriority,
   195  	})
   196  
   197  	blk, err := block.NewBanffStandardBlock(startTime, ids.GenerateTestID(), height, nil)
   198  	if err != nil {
   199  		return err
   200  	}
   201  
   202  	s.AddStatelessBlock(blk)
   203  	s.SetLastAccepted(blk.ID())
   204  	s.SetHeight(height)
   205  	return s.Commit()
   206  }