github.com/MetalBlockchain/metalgo@v1.11.9/vms/avm/txs/operation_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 txs
     5  
     6  import (
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/require"
    10  
    11  	"github.com/MetalBlockchain/metalgo/codec"
    12  	"github.com/MetalBlockchain/metalgo/codec/linearcodec"
    13  	"github.com/MetalBlockchain/metalgo/ids"
    14  	"github.com/MetalBlockchain/metalgo/snow"
    15  	"github.com/MetalBlockchain/metalgo/vms/components/avax"
    16  	"github.com/MetalBlockchain/metalgo/vms/components/verify"
    17  )
    18  
    19  type testOperable struct {
    20  	avax.TestTransferable `serialize:"true"`
    21  
    22  	Outputs []verify.State `serialize:"true"`
    23  }
    24  
    25  func (*testOperable) InitCtx(*snow.Context) {}
    26  
    27  func (o *testOperable) Outs() []verify.State {
    28  	return o.Outputs
    29  }
    30  
    31  func TestOperationVerifyNil(t *testing.T) {
    32  	op := (*Operation)(nil)
    33  	err := op.Verify()
    34  	require.ErrorIs(t, err, ErrNilOperation)
    35  }
    36  
    37  func TestOperationVerifyEmpty(t *testing.T) {
    38  	op := &Operation{
    39  		Asset: avax.Asset{ID: ids.Empty},
    40  	}
    41  	err := op.Verify()
    42  	require.ErrorIs(t, err, ErrNilFxOperation)
    43  }
    44  
    45  func TestOperationVerifyUTXOIDsNotSorted(t *testing.T) {
    46  	op := &Operation{
    47  		Asset: avax.Asset{ID: ids.Empty},
    48  		UTXOIDs: []*avax.UTXOID{
    49  			{
    50  				TxID:        ids.Empty,
    51  				OutputIndex: 1,
    52  			},
    53  			{
    54  				TxID:        ids.Empty,
    55  				OutputIndex: 0,
    56  			},
    57  		},
    58  		Op: &testOperable{},
    59  	}
    60  	err := op.Verify()
    61  	require.ErrorIs(t, err, ErrNotSortedAndUniqueUTXOIDs)
    62  }
    63  
    64  func TestOperationVerify(t *testing.T) {
    65  	assetID := ids.GenerateTestID()
    66  	op := &Operation{
    67  		Asset: avax.Asset{ID: assetID},
    68  		UTXOIDs: []*avax.UTXOID{
    69  			{
    70  				TxID:        assetID,
    71  				OutputIndex: 1,
    72  			},
    73  		},
    74  		Op: &testOperable{},
    75  	}
    76  	require.NoError(t, op.Verify())
    77  }
    78  
    79  func TestOperationSorting(t *testing.T) {
    80  	require := require.New(t)
    81  
    82  	c := linearcodec.NewDefault()
    83  	require.NoError(c.RegisterType(&testOperable{}))
    84  
    85  	m := codec.NewDefaultManager()
    86  	require.NoError(m.RegisterCodec(CodecVersion, c))
    87  
    88  	ops := []*Operation{
    89  		{
    90  			Asset: avax.Asset{ID: ids.Empty},
    91  			UTXOIDs: []*avax.UTXOID{
    92  				{
    93  					TxID:        ids.Empty,
    94  					OutputIndex: 1,
    95  				},
    96  			},
    97  			Op: &testOperable{},
    98  		},
    99  		{
   100  			Asset: avax.Asset{ID: ids.Empty},
   101  			UTXOIDs: []*avax.UTXOID{
   102  				{
   103  					TxID:        ids.Empty,
   104  					OutputIndex: 0,
   105  				},
   106  			},
   107  			Op: &testOperable{},
   108  		},
   109  	}
   110  	require.False(IsSortedAndUniqueOperations(ops, m))
   111  	SortOperations(ops, m)
   112  	require.True(IsSortedAndUniqueOperations(ops, m))
   113  	ops = append(ops, &Operation{
   114  		Asset: avax.Asset{ID: ids.Empty},
   115  		UTXOIDs: []*avax.UTXOID{
   116  			{
   117  				TxID:        ids.Empty,
   118  				OutputIndex: 1,
   119  			},
   120  		},
   121  		Op: &testOperable{},
   122  	})
   123  	require.False(IsSortedAndUniqueOperations(ops, m))
   124  }
   125  
   126  func TestOperationTxNotState(t *testing.T) {
   127  	intf := interface{}(&OperationTx{})
   128  	_, ok := intf.(verify.State)
   129  	require.False(t, ok)
   130  }