github.com/MetalBlockchain/metalgo@v1.11.9/vms/avm/txs/base_tx_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/ids"
    12  	"github.com/MetalBlockchain/metalgo/utils/constants"
    13  	"github.com/MetalBlockchain/metalgo/utils/crypto/secp256k1"
    14  	"github.com/MetalBlockchain/metalgo/vms/avm/fxs"
    15  	"github.com/MetalBlockchain/metalgo/vms/components/avax"
    16  	"github.com/MetalBlockchain/metalgo/vms/components/verify"
    17  	"github.com/MetalBlockchain/metalgo/vms/secp256k1fx"
    18  )
    19  
    20  var (
    21  	chainID = ids.ID{5, 4, 3, 2, 1}
    22  	assetID = ids.ID{1, 2, 3}
    23  	keys    = secp256k1.TestKeys()
    24  )
    25  
    26  func TestBaseTxSerialization(t *testing.T) {
    27  	require := require.New(t)
    28  
    29  	expected := []byte{
    30  		// Codec version:
    31  		0x00, 0x00,
    32  		// txID:
    33  		0x00, 0x00, 0x00, 0x00,
    34  		// networkID:
    35  		0x00, 0x00, 0x00, 0x0a,
    36  		// blockchainID:
    37  		0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00,
    38  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    39  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    40  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    41  		// number of outs:
    42  		0x00, 0x00, 0x00, 0x01,
    43  		// output[0]:
    44  		// assetID:
    45  		0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
    46  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    47  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    48  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    49  		// fxID:
    50  		0x00, 0x00, 0x00, 0x07,
    51  		// secp256k1 Transferable Output:
    52  		// amount:
    53  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39,
    54  		// locktime:
    55  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    56  		// threshold:
    57  		0x00, 0x00, 0x00, 0x01,
    58  		// number of addresses
    59  		0x00, 0x00, 0x00, 0x01,
    60  		// address[0]
    61  		0xfc, 0xed, 0xa8, 0xf9, 0x0f, 0xcb, 0x5d, 0x30,
    62  		0x61, 0x4b, 0x99, 0xd7, 0x9f, 0xc4, 0xba, 0xa2,
    63  		0x93, 0x07, 0x76, 0x26,
    64  		// number of inputs:
    65  		0x00, 0x00, 0x00, 0x01,
    66  		// txID:
    67  		0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
    68  		0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
    69  		0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8,
    70  		0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0,
    71  		// utxo index:
    72  		0x00, 0x00, 0x00, 0x01,
    73  		// assetID:
    74  		0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
    75  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    76  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    77  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    78  		// fxID:
    79  		0x00, 0x00, 0x00, 0x05,
    80  		// amount:
    81  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x31,
    82  		// number of signatures:
    83  		0x00, 0x00, 0x00, 0x01,
    84  		// signature index[0]:
    85  		0x00, 0x00, 0x00, 0x02,
    86  		// Memo length:
    87  		0x00, 0x00, 0x00, 0x04,
    88  		// Memo:
    89  		0x00, 0x01, 0x02, 0x03,
    90  		// Number of credentials
    91  		0x00, 0x00, 0x00, 0x00,
    92  	}
    93  
    94  	tx := &Tx{Unsigned: &BaseTx{BaseTx: avax.BaseTx{
    95  		NetworkID:    constants.UnitTestID,
    96  		BlockchainID: chainID,
    97  		Outs: []*avax.TransferableOutput{{
    98  			Asset: avax.Asset{ID: assetID},
    99  			Out: &secp256k1fx.TransferOutput{
   100  				Amt: 12345,
   101  				OutputOwners: secp256k1fx.OutputOwners{
   102  					Threshold: 1,
   103  					Addrs:     []ids.ShortID{keys[0].PublicKey().Address()},
   104  				},
   105  			},
   106  		}},
   107  		Ins: []*avax.TransferableInput{{
   108  			UTXOID: avax.UTXOID{
   109  				TxID: ids.ID{
   110  					0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
   111  					0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
   112  					0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8,
   113  					0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0,
   114  				},
   115  				OutputIndex: 1,
   116  			},
   117  			Asset: avax.Asset{ID: assetID},
   118  			In: &secp256k1fx.TransferInput{
   119  				Amt: 54321,
   120  				Input: secp256k1fx.Input{
   121  					SigIndices: []uint32{2},
   122  				},
   123  			},
   124  		}},
   125  		Memo: []byte{0x00, 0x01, 0x02, 0x03},
   126  	}}}
   127  
   128  	parser, err := NewParser(
   129  		[]fxs.Fx{
   130  			&secp256k1fx.Fx{},
   131  		},
   132  	)
   133  	require.NoError(err)
   134  
   135  	require.NoError(tx.Initialize(parser.Codec()))
   136  	require.Equal("zeqT8FTnRAxes7QQQYkaWhNkHavd9d6aCdH8TQu2Mx5KEydEz", tx.ID().String())
   137  
   138  	result := tx.Bytes()
   139  	require.Equal(expected, result)
   140  
   141  	credBytes := []byte{
   142  		// type id
   143  		0x00, 0x00, 0x00, 0x09,
   144  
   145  		// there are two signers (thus two signatures)
   146  		0x00, 0x00, 0x00, 0x02,
   147  
   148  		// 65 bytes
   149  		0x7d, 0x89, 0x8e, 0xe9, 0x8a, 0xf8, 0x33, 0x5d, 0x37, 0xe6,
   150  		0xfa, 0xda, 0x0c, 0xbb, 0x44, 0xa1, 0x44, 0x05, 0xd3, 0xbb,
   151  		0x94, 0x0d, 0xfc, 0x0d, 0x99, 0xa6, 0xd3, 0xff, 0x5c, 0x71,
   152  		0x5a, 0xff, 0x26, 0xd1, 0x84, 0x84, 0xf2, 0x9b, 0x28, 0x96,
   153  		0x44, 0x96, 0x8f, 0xed, 0xff, 0xeb, 0x23, 0xe0, 0x30, 0x66,
   154  		0x5d, 0x73, 0x6d, 0x94, 0xfc, 0x80, 0xbc, 0x73, 0x5f, 0x51,
   155  		0xc8, 0x06, 0xd7, 0x43, 0x00,
   156  
   157  		// 65 bytes
   158  		0x7d, 0x89, 0x8e, 0xe9, 0x8a, 0xf8, 0x33, 0x5d, 0x37, 0xe6,
   159  		0xfa, 0xda, 0x0c, 0xbb, 0x44, 0xa1, 0x44, 0x05, 0xd3, 0xbb,
   160  		0x94, 0x0d, 0xfc, 0x0d, 0x99, 0xa6, 0xd3, 0xff, 0x5c, 0x71,
   161  		0x5a, 0xff, 0x26, 0xd1, 0x84, 0x84, 0xf2, 0x9b, 0x28, 0x96,
   162  		0x44, 0x96, 0x8f, 0xed, 0xff, 0xeb, 0x23, 0xe0, 0x30, 0x66,
   163  		0x5d, 0x73, 0x6d, 0x94, 0xfc, 0x80, 0xbc, 0x73, 0x5f, 0x51,
   164  		0xc8, 0x06, 0xd7, 0x43, 0x00,
   165  
   166  		// type id
   167  		0x00, 0x00, 0x00, 0x09,
   168  
   169  		// there are two signers (thus two signatures)
   170  		0x00, 0x00, 0x00, 0x02,
   171  
   172  		// 65 bytes
   173  		0x7d, 0x89, 0x8e, 0xe9, 0x8a, 0xf8, 0x33, 0x5d, 0x37, 0xe6,
   174  		0xfa, 0xda, 0x0c, 0xbb, 0x44, 0xa1, 0x44, 0x05, 0xd3, 0xbb,
   175  		0x94, 0x0d, 0xfc, 0x0d, 0x99, 0xa6, 0xd3, 0xff, 0x5c, 0x71,
   176  		0x5a, 0xff, 0x26, 0xd1, 0x84, 0x84, 0xf2, 0x9b, 0x28, 0x96,
   177  		0x44, 0x96, 0x8f, 0xed, 0xff, 0xeb, 0x23, 0xe0, 0x30, 0x66,
   178  		0x5d, 0x73, 0x6d, 0x94, 0xfc, 0x80, 0xbc, 0x73, 0x5f, 0x51,
   179  		0xc8, 0x06, 0xd7, 0x43, 0x00,
   180  
   181  		// 65 bytes
   182  		0x7d, 0x89, 0x8e, 0xe9, 0x8a, 0xf8, 0x33, 0x5d, 0x37, 0xe6,
   183  		0xfa, 0xda, 0x0c, 0xbb, 0x44, 0xa1, 0x44, 0x05, 0xd3, 0xbb,
   184  		0x94, 0x0d, 0xfc, 0x0d, 0x99, 0xa6, 0xd3, 0xff, 0x5c, 0x71,
   185  		0x5a, 0xff, 0x26, 0xd1, 0x84, 0x84, 0xf2, 0x9b, 0x28, 0x96,
   186  		0x44, 0x96, 0x8f, 0xed, 0xff, 0xeb, 0x23, 0xe0, 0x30, 0x66,
   187  		0x5d, 0x73, 0x6d, 0x94, 0xfc, 0x80, 0xbc, 0x73, 0x5f, 0x51,
   188  		0xc8, 0x06, 0xd7, 0x43, 0x00,
   189  	}
   190  
   191  	require.NoError(tx.SignSECP256K1Fx(
   192  		parser.Codec(),
   193  		[][]*secp256k1.PrivateKey{
   194  			{keys[0], keys[0]},
   195  			{keys[0], keys[0]},
   196  		},
   197  	))
   198  	require.Equal("QnTUuie2qe6BKyYrC2jqd73bJ828QNhYnZbdA2HWsnVRPjBfV", tx.ID().String())
   199  
   200  	// there are two credentials
   201  	expected[len(expected)-1] = 0x02
   202  	expected = append(expected, credBytes...)
   203  
   204  	result = tx.Bytes()
   205  	require.Equal(expected, result)
   206  }
   207  
   208  func TestBaseTxNotState(t *testing.T) {
   209  	require := require.New(t)
   210  
   211  	intf := interface{}(&BaseTx{})
   212  	_, ok := intf.(verify.State)
   213  	require.False(ok, "should not be marked as state")
   214  }