github.com/MetalBlockchain/metalgo@v1.11.9/vms/platformvm/api/static_service_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 api
     5  
     6  import (
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/require"
    10  
    11  	"github.com/MetalBlockchain/metalgo/ids"
    12  	"github.com/MetalBlockchain/metalgo/utils/constants"
    13  	"github.com/MetalBlockchain/metalgo/utils/formatting"
    14  	"github.com/MetalBlockchain/metalgo/utils/formatting/address"
    15  	"github.com/MetalBlockchain/metalgo/utils/json"
    16  	"github.com/MetalBlockchain/metalgo/vms/platformvm/genesis"
    17  )
    18  
    19  func TestBuildGenesisInvalidUTXOBalance(t *testing.T) {
    20  	require := require.New(t)
    21  	nodeID := ids.BuildTestNodeID([]byte{1, 2, 3})
    22  	addr, err := address.FormatBech32(constants.UnitTestHRP, nodeID.Bytes())
    23  	require.NoError(err)
    24  
    25  	utxo := UTXO{
    26  		Address: addr,
    27  		Amount:  0,
    28  	}
    29  	weight := json.Uint64(987654321)
    30  	validator := GenesisPermissionlessValidator{
    31  		GenesisValidator: GenesisValidator{
    32  			EndTime: 15,
    33  			Weight:  weight,
    34  			NodeID:  nodeID,
    35  		},
    36  		RewardOwner: &Owner{
    37  			Threshold: 1,
    38  			Addresses: []string{addr},
    39  		},
    40  		Staked: []UTXO{{
    41  			Amount:  weight,
    42  			Address: addr,
    43  		}},
    44  	}
    45  
    46  	args := BuildGenesisArgs{
    47  		UTXOs: []UTXO{
    48  			utxo,
    49  		},
    50  		Validators: []GenesisPermissionlessValidator{
    51  			validator,
    52  		},
    53  		Time:     5,
    54  		Encoding: formatting.Hex,
    55  	}
    56  	reply := BuildGenesisReply{}
    57  
    58  	ss := StaticService{}
    59  	err = ss.BuildGenesis(nil, &args, &reply)
    60  	require.ErrorIs(err, errUTXOHasNoValue)
    61  }
    62  
    63  func TestBuildGenesisInvalidStakeWeight(t *testing.T) {
    64  	require := require.New(t)
    65  	nodeID := ids.BuildTestNodeID([]byte{1, 2, 3})
    66  	addr, err := address.FormatBech32(constants.UnitTestHRP, nodeID.Bytes())
    67  	require.NoError(err)
    68  
    69  	utxo := UTXO{
    70  		Address: addr,
    71  		Amount:  123456789,
    72  	}
    73  	weight := json.Uint64(0)
    74  	validator := GenesisPermissionlessValidator{
    75  		GenesisValidator: GenesisValidator{
    76  			StartTime: 0,
    77  			EndTime:   15,
    78  			NodeID:    nodeID,
    79  		},
    80  		RewardOwner: &Owner{
    81  			Threshold: 1,
    82  			Addresses: []string{addr},
    83  		},
    84  		Staked: []UTXO{{
    85  			Amount:  weight,
    86  			Address: addr,
    87  		}},
    88  	}
    89  
    90  	args := BuildGenesisArgs{
    91  		UTXOs: []UTXO{
    92  			utxo,
    93  		},
    94  		Validators: []GenesisPermissionlessValidator{
    95  			validator,
    96  		},
    97  		Time:     5,
    98  		Encoding: formatting.Hex,
    99  	}
   100  	reply := BuildGenesisReply{}
   101  
   102  	ss := StaticService{}
   103  	err = ss.BuildGenesis(nil, &args, &reply)
   104  	require.ErrorIs(err, errValidatorHasNoWeight)
   105  }
   106  
   107  func TestBuildGenesisInvalidEndtime(t *testing.T) {
   108  	require := require.New(t)
   109  	nodeID := ids.BuildTestNodeID([]byte{1, 2, 3})
   110  	addr, err := address.FormatBech32(constants.UnitTestHRP, nodeID.Bytes())
   111  	require.NoError(err)
   112  
   113  	utxo := UTXO{
   114  		Address: addr,
   115  		Amount:  123456789,
   116  	}
   117  
   118  	weight := json.Uint64(987654321)
   119  	validator := GenesisPermissionlessValidator{
   120  		GenesisValidator: GenesisValidator{
   121  			StartTime: 0,
   122  			EndTime:   5,
   123  			NodeID:    nodeID,
   124  		},
   125  		RewardOwner: &Owner{
   126  			Threshold: 1,
   127  			Addresses: []string{addr},
   128  		},
   129  		Staked: []UTXO{{
   130  			Amount:  weight,
   131  			Address: addr,
   132  		}},
   133  	}
   134  
   135  	args := BuildGenesisArgs{
   136  		UTXOs: []UTXO{
   137  			utxo,
   138  		},
   139  		Validators: []GenesisPermissionlessValidator{
   140  			validator,
   141  		},
   142  		Time:     5,
   143  		Encoding: formatting.Hex,
   144  	}
   145  	reply := BuildGenesisReply{}
   146  
   147  	ss := StaticService{}
   148  	err = ss.BuildGenesis(nil, &args, &reply)
   149  	require.ErrorIs(err, errValidatorAlreadyExited)
   150  }
   151  
   152  func TestBuildGenesisReturnsSortedValidators(t *testing.T) {
   153  	require := require.New(t)
   154  	nodeID := ids.BuildTestNodeID([]byte{1})
   155  	addr, err := address.FormatBech32(constants.UnitTestHRP, nodeID.Bytes())
   156  	require.NoError(err)
   157  
   158  	utxo := UTXO{
   159  		Address: addr,
   160  		Amount:  123456789,
   161  	}
   162  
   163  	weight := json.Uint64(987654321)
   164  	validator1 := GenesisPermissionlessValidator{
   165  		GenesisValidator: GenesisValidator{
   166  			StartTime: 0,
   167  			EndTime:   20,
   168  			NodeID:    nodeID,
   169  		},
   170  		RewardOwner: &Owner{
   171  			Threshold: 1,
   172  			Addresses: []string{addr},
   173  		},
   174  		Staked: []UTXO{{
   175  			Amount:  weight,
   176  			Address: addr,
   177  		}},
   178  	}
   179  
   180  	validator2 := GenesisPermissionlessValidator{
   181  		GenesisValidator: GenesisValidator{
   182  			StartTime: 3,
   183  			EndTime:   15,
   184  			NodeID:    nodeID,
   185  		},
   186  		RewardOwner: &Owner{
   187  			Threshold: 1,
   188  			Addresses: []string{addr},
   189  		},
   190  		Staked: []UTXO{{
   191  			Amount:  weight,
   192  			Address: addr,
   193  		}},
   194  	}
   195  
   196  	validator3 := GenesisPermissionlessValidator{
   197  		GenesisValidator: GenesisValidator{
   198  			StartTime: 1,
   199  			EndTime:   10,
   200  			NodeID:    nodeID,
   201  		},
   202  		RewardOwner: &Owner{
   203  			Threshold: 1,
   204  			Addresses: []string{addr},
   205  		},
   206  		Staked: []UTXO{{
   207  			Amount:  weight,
   208  			Address: addr,
   209  		}},
   210  	}
   211  
   212  	args := BuildGenesisArgs{
   213  		AvaxAssetID: ids.ID{'d', 'u', 'm', 'm', 'y', ' ', 'I', 'D'},
   214  		UTXOs: []UTXO{
   215  			utxo,
   216  		},
   217  		Validators: []GenesisPermissionlessValidator{
   218  			validator1,
   219  			validator2,
   220  			validator3,
   221  		},
   222  		Time:     5,
   223  		Encoding: formatting.Hex,
   224  	}
   225  	reply := BuildGenesisReply{}
   226  
   227  	ss := StaticService{}
   228  	require.NoError(ss.BuildGenesis(nil, &args, &reply))
   229  
   230  	genesisBytes, err := formatting.Decode(reply.Encoding, reply.Bytes)
   231  	require.NoError(err)
   232  
   233  	genesis, err := genesis.Parse(genesisBytes)
   234  	require.NoError(err)
   235  
   236  	validators := genesis.Validators
   237  	require.Len(validators, 3)
   238  }
   239  
   240  func TestUTXOCompare(t *testing.T) {
   241  	var (
   242  		smallerAddr = ids.ShortID{}
   243  		largerAddr  = ids.ShortID{1}
   244  	)
   245  	smallerAddrStr, err := address.FormatBech32("avax", smallerAddr[:])
   246  	require.NoError(t, err)
   247  	largerAddrStr, err := address.FormatBech32("avax", largerAddr[:])
   248  	require.NoError(t, err)
   249  
   250  	type test struct {
   251  		name     string
   252  		utxo1    UTXO
   253  		utxo2    UTXO
   254  		expected int
   255  	}
   256  	tests := []test{
   257  		{
   258  			name:     "both empty",
   259  			utxo1:    UTXO{},
   260  			utxo2:    UTXO{},
   261  			expected: 0,
   262  		},
   263  		{
   264  			name:  "locktime smaller",
   265  			utxo1: UTXO{},
   266  			utxo2: UTXO{
   267  				Locktime: 1,
   268  			},
   269  			expected: -1,
   270  		},
   271  		{
   272  			name:  "amount smaller",
   273  			utxo1: UTXO{},
   274  			utxo2: UTXO{
   275  				Amount: 1,
   276  			},
   277  			expected: -1,
   278  		},
   279  		{
   280  			name: "address smaller",
   281  			utxo1: UTXO{
   282  				Address: smallerAddrStr,
   283  			},
   284  			utxo2: UTXO{
   285  				Address: largerAddrStr,
   286  			},
   287  			expected: -1,
   288  		},
   289  	}
   290  
   291  	for _, tt := range tests {
   292  		t.Run(tt.name, func(t *testing.T) {
   293  			require := require.New(t)
   294  
   295  			require.Equal(tt.expected, tt.utxo1.Compare(tt.utxo2))
   296  			require.Equal(-tt.expected, tt.utxo2.Compare(tt.utxo1))
   297  		})
   298  	}
   299  }