github.com/ava-labs/avalanchego@v1.11.11/wallet/chain/p/builder/builder_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 builder
     5  
     6  import (
     7  	"math/rand"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/stretchr/testify/require"
    12  
    13  	"github.com/ava-labs/avalanchego/ids"
    14  	"github.com/ava-labs/avalanchego/utils"
    15  	"github.com/ava-labs/avalanchego/vms/components/avax"
    16  	"github.com/ava-labs/avalanchego/vms/components/verify"
    17  	"github.com/ava-labs/avalanchego/vms/platformvm/stakeable"
    18  	"github.com/ava-labs/avalanchego/vms/secp256k1fx"
    19  )
    20  
    21  func generateUTXOs(random *rand.Rand, assetID ids.ID, locktime uint64) []*avax.UTXO {
    22  	utxos := make([]*avax.UTXO, random.Intn(10))
    23  	for i := range utxos {
    24  		var output avax.TransferableOut = &secp256k1fx.TransferOutput{
    25  			Amt: random.Uint64(),
    26  			OutputOwners: secp256k1fx.OutputOwners{
    27  				Locktime:  random.Uint64(),
    28  				Threshold: 1,
    29  				Addrs:     []ids.ShortID{ids.GenerateTestShortID()},
    30  			},
    31  		}
    32  		if locktime != 0 {
    33  			output = &stakeable.LockOut{
    34  				Locktime:        locktime,
    35  				TransferableOut: output,
    36  			}
    37  		}
    38  		utxos[i] = &avax.UTXO{
    39  			UTXOID: avax.UTXOID{
    40  				TxID:        ids.GenerateTestID(),
    41  				OutputIndex: random.Uint32(),
    42  			},
    43  			Asset: avax.Asset{
    44  				ID: assetID,
    45  			},
    46  			Out: output,
    47  		}
    48  	}
    49  	return utxos
    50  }
    51  
    52  func TestSplitByLocktime(t *testing.T) {
    53  	seed := time.Now().UnixNano()
    54  	t.Logf("Seed: %d", seed)
    55  	random := rand.New(rand.NewSource(seed)) // #nosec G404
    56  
    57  	var (
    58  		require = require.New(t)
    59  
    60  		unlockedTime     uint64 = 100
    61  		expectedUnlocked        = utils.Join(
    62  			generateUTXOs(random, ids.GenerateTestID(), 0),
    63  			generateUTXOs(random, ids.GenerateTestID(), unlockedTime-1),
    64  			generateUTXOs(random, ids.GenerateTestID(), unlockedTime),
    65  		)
    66  		expectedLocked = utils.Join(
    67  			generateUTXOs(random, ids.GenerateTestID(), unlockedTime+100),
    68  			generateUTXOs(random, ids.GenerateTestID(), unlockedTime+1),
    69  		)
    70  		utxos = utils.Join(
    71  			expectedUnlocked,
    72  			expectedLocked,
    73  		)
    74  	)
    75  	random.Shuffle(len(utxos), func(i, j int) {
    76  		utxos[i], utxos[j] = utxos[j], utxos[i]
    77  	})
    78  
    79  	utxosByLocktime := splitByLocktime(utxos, unlockedTime)
    80  	require.ElementsMatch(expectedUnlocked, utxosByLocktime.unlocked)
    81  	require.ElementsMatch(expectedLocked, utxosByLocktime.locked)
    82  }
    83  
    84  func TestByAssetID(t *testing.T) {
    85  	seed := time.Now().UnixNano()
    86  	t.Logf("Seed: %d", seed)
    87  	random := rand.New(rand.NewSource(seed)) // #nosec G404
    88  
    89  	var (
    90  		require = require.New(t)
    91  
    92  		assetID           = ids.GenerateTestID()
    93  		expectedRequested = generateUTXOs(random, assetID, random.Uint64())
    94  		expectedOther     = generateUTXOs(random, ids.GenerateTestID(), random.Uint64())
    95  		utxos             = utils.Join(
    96  			expectedRequested,
    97  			expectedOther,
    98  		)
    99  	)
   100  	random.Shuffle(len(utxos), func(i, j int) {
   101  		utxos[i], utxos[j] = utxos[j], utxos[i]
   102  	})
   103  
   104  	utxosByAssetID := splitByAssetID(utxos, assetID)
   105  	require.ElementsMatch(expectedRequested, utxosByAssetID.requested)
   106  	require.ElementsMatch(expectedOther, utxosByAssetID.other)
   107  }
   108  
   109  func TestUnwrapOutput(t *testing.T) {
   110  	normalOutput := &secp256k1fx.TransferOutput{
   111  		Amt: 123,
   112  		OutputOwners: secp256k1fx.OutputOwners{
   113  			Locktime:  456,
   114  			Threshold: 1,
   115  			Addrs:     []ids.ShortID{ids.ShortEmpty},
   116  		},
   117  	}
   118  
   119  	tests := []struct {
   120  		name             string
   121  		output           verify.State
   122  		expectedOutput   *secp256k1fx.TransferOutput
   123  		expectedLocktime uint64
   124  		expectedErr      error
   125  	}{
   126  		{
   127  			name:             "normal output",
   128  			output:           normalOutput,
   129  			expectedOutput:   normalOutput,
   130  			expectedLocktime: 0,
   131  			expectedErr:      nil,
   132  		},
   133  		{
   134  			name: "locked output",
   135  			output: &stakeable.LockOut{
   136  				Locktime:        789,
   137  				TransferableOut: normalOutput,
   138  			},
   139  			expectedOutput:   normalOutput,
   140  			expectedLocktime: 789,
   141  			expectedErr:      nil,
   142  		},
   143  		{
   144  			name: "locked output with no locktime",
   145  			output: &stakeable.LockOut{
   146  				Locktime:        0,
   147  				TransferableOut: normalOutput,
   148  			},
   149  			expectedOutput:   normalOutput,
   150  			expectedLocktime: 0,
   151  			expectedErr:      nil,
   152  		},
   153  		{
   154  			name:             "invalid output",
   155  			output:           nil,
   156  			expectedOutput:   nil,
   157  			expectedLocktime: 0,
   158  			expectedErr:      ErrUnknownOutputType,
   159  		},
   160  	}
   161  
   162  	for _, test := range tests {
   163  		t.Run(test.name, func(t *testing.T) {
   164  			require := require.New(t)
   165  
   166  			output, locktime, err := unwrapOutput(test.output)
   167  			require.ErrorIs(err, test.expectedErr)
   168  			require.Equal(test.expectedOutput, output)
   169  			require.Equal(test.expectedLocktime, locktime)
   170  		})
   171  	}
   172  }