github.com/MetalBlockchain/metalgo@v1.11.9/vms/avm/txs/create_asset_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/units"
    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  func TestCreateAssetTxSerialization(t *testing.T) {
    21  	require := require.New(t)
    22  
    23  	expected := []byte{
    24  		// Codec version:
    25  		0x00, 0x00,
    26  		// txID:
    27  		0x00, 0x00, 0x00, 0x01,
    28  		// networkID:
    29  		0x00, 0x00, 0x00, 0x02,
    30  		// blockchainID:
    31  		0xff, 0xff, 0xff, 0xff, 0xee, 0xee, 0xee, 0xee,
    32  		0xdd, 0xdd, 0xdd, 0xdd, 0xcc, 0xcc, 0xcc, 0xcc,
    33  		0xbb, 0xbb, 0xbb, 0xbb, 0xaa, 0xaa, 0xaa, 0xaa,
    34  		0x99, 0x99, 0x99, 0x99, 0x88, 0x88, 0x88, 0x88,
    35  		// number of outs:
    36  		0x00, 0x00, 0x00, 0x01,
    37  		// output[0]:
    38  		// assetID:
    39  		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    40  		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    41  		0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
    42  		0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
    43  		// output:
    44  		0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
    45  		0x00, 0x00, 0x30, 0x39, 0x00, 0x00, 0x00, 0x00,
    46  		0x00, 0x00, 0xd4, 0x31, 0x00, 0x00, 0x00, 0x01,
    47  		0x00, 0x00, 0x00, 0x02, 0x51, 0x02, 0x5c, 0x61,
    48  		0xfb, 0xcf, 0xc0, 0x78, 0xf6, 0x93, 0x34, 0xf8,
    49  		0x34, 0xbe, 0x6d, 0xd2, 0x6d, 0x55, 0xa9, 0x55,
    50  		0xc3, 0x34, 0x41, 0x28, 0xe0, 0x60, 0x12, 0x8e,
    51  		0xde, 0x35, 0x23, 0xa2, 0x4a, 0x46, 0x1c, 0x89,
    52  		0x43, 0xab, 0x08, 0x59,
    53  		// number of inputs:
    54  		0x00, 0x00, 0x00, 0x01,
    55  		// txID:
    56  		0xf1, 0xe1, 0xd1, 0xc1, 0xb1, 0xa1, 0x91, 0x81,
    57  		0x71, 0x61, 0x51, 0x41, 0x31, 0x21, 0x11, 0x01,
    58  		0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80,
    59  		0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00,
    60  		// utxoIndex:
    61  		0x00, 0x00, 0x00, 0x05,
    62  		// assetID:
    63  		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    64  		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    65  		0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
    66  		0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
    67  		// input:
    68  		0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
    69  		0x07, 0x5b, 0xcd, 0x15, 0x00, 0x00, 0x00, 0x02,
    70  		0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07,
    71  		// Memo length:
    72  		0x00, 0x00, 0x00, 0x04,
    73  		// Memo:
    74  		0x00, 0x01, 0x02, 0x03,
    75  		// name:
    76  		0x00, 0x10, 0x56, 0x6f, 0x6c, 0x61, 0x74, 0x69,
    77  		0x6c, 0x69, 0x74, 0x79, 0x20, 0x49, 0x6e, 0x64,
    78  		0x65, 0x78,
    79  		// symbol:
    80  		0x00, 0x03, 0x56, 0x49, 0x58,
    81  		// denomination:
    82  		0x02,
    83  		// number of InitialStates:
    84  		0x00, 0x00, 0x00, 0x01,
    85  		// InitialStates[0]:
    86  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    87  		0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
    88  		0x00, 0x00, 0x30, 0x39, 0x00, 0x00, 0x00, 0x00,
    89  		0x00, 0x00, 0xd4, 0x31, 0x00, 0x00, 0x00, 0x01,
    90  		0x00, 0x00, 0x00, 0x02, 0x51, 0x02, 0x5c, 0x61,
    91  		0xfb, 0xcf, 0xc0, 0x78, 0xf6, 0x93, 0x34, 0xf8,
    92  		0x34, 0xbe, 0x6d, 0xd2, 0x6d, 0x55, 0xa9, 0x55,
    93  		0xc3, 0x34, 0x41, 0x28, 0xe0, 0x60, 0x12, 0x8e,
    94  		0xde, 0x35, 0x23, 0xa2, 0x4a, 0x46, 0x1c, 0x89,
    95  		0x43, 0xab, 0x08, 0x59,
    96  		// number of credentials:
    97  		0x00, 0x00, 0x00, 0x00,
    98  	}
    99  
   100  	tx := &Tx{Unsigned: &CreateAssetTx{
   101  		BaseTx: BaseTx{BaseTx: avax.BaseTx{
   102  			NetworkID: 2,
   103  			BlockchainID: ids.ID{
   104  				0xff, 0xff, 0xff, 0xff, 0xee, 0xee, 0xee, 0xee,
   105  				0xdd, 0xdd, 0xdd, 0xdd, 0xcc, 0xcc, 0xcc, 0xcc,
   106  				0xbb, 0xbb, 0xbb, 0xbb, 0xaa, 0xaa, 0xaa, 0xaa,
   107  				0x99, 0x99, 0x99, 0x99, 0x88, 0x88, 0x88, 0x88,
   108  			},
   109  			Memo: []byte{0x00, 0x01, 0x02, 0x03},
   110  			Outs: []*avax.TransferableOutput{{
   111  				Asset: avax.Asset{
   112  					ID: ids.ID{
   113  						0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
   114  						0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
   115  						0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
   116  						0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
   117  					},
   118  				},
   119  				Out: &secp256k1fx.TransferOutput{
   120  					Amt: 12345,
   121  					OutputOwners: secp256k1fx.OutputOwners{
   122  						Locktime:  54321,
   123  						Threshold: 1,
   124  						Addrs: []ids.ShortID{
   125  							{
   126  								0x51, 0x02, 0x5c, 0x61, 0xfb, 0xcf, 0xc0, 0x78,
   127  								0xf6, 0x93, 0x34, 0xf8, 0x34, 0xbe, 0x6d, 0xd2,
   128  								0x6d, 0x55, 0xa9, 0x55,
   129  							},
   130  							{
   131  								0xc3, 0x34, 0x41, 0x28, 0xe0, 0x60, 0x12, 0x8e,
   132  								0xde, 0x35, 0x23, 0xa2, 0x4a, 0x46, 0x1c, 0x89,
   133  								0x43, 0xab, 0x08, 0x59,
   134  							},
   135  						},
   136  					},
   137  				},
   138  			}},
   139  			Ins: []*avax.TransferableInput{{
   140  				UTXOID: avax.UTXOID{
   141  					TxID: ids.ID{
   142  						0xf1, 0xe1, 0xd1, 0xc1, 0xb1, 0xa1, 0x91, 0x81,
   143  						0x71, 0x61, 0x51, 0x41, 0x31, 0x21, 0x11, 0x01,
   144  						0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80,
   145  						0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00,
   146  					},
   147  					OutputIndex: 5,
   148  				},
   149  				Asset: avax.Asset{
   150  					ID: ids.ID{
   151  						0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
   152  						0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
   153  						0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
   154  						0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
   155  					},
   156  				},
   157  				In: &secp256k1fx.TransferInput{
   158  					Amt: 123456789,
   159  					Input: secp256k1fx.Input{
   160  						SigIndices: []uint32{3, 7},
   161  					},
   162  				},
   163  			}},
   164  		}},
   165  		Name:         "Volatility Index",
   166  		Symbol:       "VIX",
   167  		Denomination: 2,
   168  		States: []*InitialState{
   169  			{
   170  				FxIndex: 0,
   171  				Outs: []verify.State{
   172  					&secp256k1fx.TransferOutput{
   173  						Amt: 12345,
   174  						OutputOwners: secp256k1fx.OutputOwners{
   175  							Locktime:  54321,
   176  							Threshold: 1,
   177  							Addrs: []ids.ShortID{
   178  								{
   179  									0x51, 0x02, 0x5c, 0x61, 0xfb, 0xcf, 0xc0, 0x78,
   180  									0xf6, 0x93, 0x34, 0xf8, 0x34, 0xbe, 0x6d, 0xd2,
   181  									0x6d, 0x55, 0xa9, 0x55,
   182  								},
   183  								{
   184  									0xc3, 0x34, 0x41, 0x28, 0xe0, 0x60, 0x12, 0x8e,
   185  									0xde, 0x35, 0x23, 0xa2, 0x4a, 0x46, 0x1c, 0x89,
   186  									0x43, 0xab, 0x08, 0x59,
   187  								},
   188  							},
   189  						},
   190  					},
   191  				},
   192  			},
   193  		},
   194  	}}
   195  
   196  	parser, err := NewParser(
   197  		[]fxs.Fx{
   198  			&secp256k1fx.Fx{},
   199  		},
   200  	)
   201  	require.NoError(err)
   202  
   203  	require.NoError(tx.Initialize(parser.Codec()))
   204  
   205  	result := tx.Bytes()
   206  	require.Equal(expected, result)
   207  }
   208  
   209  func TestCreateAssetTxSerializationAgain(t *testing.T) {
   210  	require := require.New(t)
   211  
   212  	expected := []byte{
   213  		// Codec version:
   214  		0x00, 0x00,
   215  		// txID:
   216  		0x00, 0x00, 0x00, 0x01,
   217  		// networkID:
   218  		0x00, 0x00, 0x00, 0x0a,
   219  		// chainID:
   220  		0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00,
   221  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   222  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   223  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   224  		// number of outs:
   225  		0x00, 0x00, 0x00, 0x03,
   226  		// output[0]:
   227  		// assetID:
   228  		0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
   229  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   230  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   231  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   232  		// fxID:
   233  		0x00, 0x00, 0x00, 0x07,
   234  		// secp256k1 Transferable Output:
   235  		// amount:
   236  		0x00, 0x00, 0x12, 0x30, 0x9c, 0xe5, 0x40, 0x00,
   237  		// locktime:
   238  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   239  		// threshold:
   240  		0x00, 0x00, 0x00, 0x01,
   241  		// number of addresses
   242  		0x00, 0x00, 0x00, 0x01,
   243  		// address[0]
   244  		0xfc, 0xed, 0xa8, 0xf9, 0x0f, 0xcb, 0x5d, 0x30,
   245  		0x61, 0x4b, 0x99, 0xd7, 0x9f, 0xc4, 0xba, 0xa2,
   246  		0x93, 0x07, 0x76, 0x26,
   247  		// output[1]:
   248  		// assetID:
   249  		0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
   250  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   251  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   252  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   253  		// fxID:
   254  		0x00, 0x00, 0x00, 0x07,
   255  		// secp256k1 Transferable Output:
   256  		// amount:
   257  		0x00, 0x00, 0x12, 0x30, 0x9c, 0xe5, 0x40, 0x00,
   258  		// locktime:
   259  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   260  		// threshold:
   261  		0x00, 0x00, 0x00, 0x01,
   262  		// number of addresses:
   263  		0x00, 0x00, 0x00, 0x01,
   264  		// address[0]:
   265  		0x6e, 0xad, 0x69, 0x3c, 0x17, 0xab, 0xb1, 0xbe,
   266  		0x42, 0x2b, 0xb5, 0x0b, 0x30, 0xb9, 0x71, 0x1f,
   267  		0xf9, 0x8d, 0x66, 0x7e,
   268  		// output[2]:
   269  		// assetID:
   270  		0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
   271  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   272  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   273  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   274  		// fxID:
   275  		0x00, 0x00, 0x00, 0x07,
   276  		// secp256k1 Transferable Output:
   277  		// amount:
   278  		0x00, 0x00, 0x12, 0x30, 0x9c, 0xe5, 0x40, 0x00,
   279  		// locktime:
   280  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   281  		// threshold:
   282  		0x00, 0x00, 0x00, 0x01,
   283  		// number of addresses:
   284  		0x00, 0x00, 0x00, 0x01,
   285  		// address[0]:
   286  		0xf2, 0x42, 0x08, 0x46, 0x87, 0x6e, 0x69, 0xf4,
   287  		0x73, 0xdd, 0xa2, 0x56, 0x17, 0x29, 0x67, 0xe9,
   288  		0x92, 0xf0, 0xee, 0x31,
   289  		// number of inputs:
   290  		0x00, 0x00, 0x00, 0x00,
   291  		// Memo length:
   292  		0x00, 0x00, 0x00, 0x04,
   293  		// Memo:
   294  		0x00, 0x01, 0x02, 0x03,
   295  		// name length:
   296  		0x00, 0x04,
   297  		// name:
   298  		'n', 'a', 'm', 'e',
   299  		// symbol length:
   300  		0x00, 0x04,
   301  		// symbol:
   302  		's', 'y', 'm', 'b',
   303  		// denomination
   304  		0x00,
   305  		// number of initial states:
   306  		0x00, 0x00, 0x00, 0x01,
   307  		// fx index:
   308  		0x00, 0x00, 0x00, 0x00,
   309  		// number of outputs:
   310  		0x00, 0x00, 0x00, 0x01,
   311  		// fxID:
   312  		0x00, 0x00, 0x00, 0x06,
   313  		// secp256k1 Mint Output:
   314  		// locktime:
   315  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   316  		// threshold:
   317  		0x00, 0x00, 0x00, 0x01,
   318  		// number of addresses:
   319  		0x00, 0x00, 0x00, 0x01,
   320  		// address[0]:
   321  		0xfc, 0xed, 0xa8, 0xf9, 0x0f, 0xcb, 0x5d, 0x30,
   322  		0x61, 0x4b, 0x99, 0xd7, 0x9f, 0xc4, 0xba, 0xa2,
   323  		0x93, 0x07, 0x76, 0x26,
   324  		// number of credentials:
   325  		0x00, 0x00, 0x00, 0x00,
   326  	}
   327  
   328  	unsignedTx := &CreateAssetTx{
   329  		BaseTx: BaseTx{BaseTx: avax.BaseTx{
   330  			NetworkID:    constants.UnitTestID,
   331  			BlockchainID: chainID,
   332  			Memo:         []byte{0x00, 0x01, 0x02, 0x03},
   333  		}},
   334  		Name:         "name",
   335  		Symbol:       "symb",
   336  		Denomination: 0,
   337  		States: []*InitialState{
   338  			{
   339  				FxIndex: 0,
   340  				Outs: []verify.State{
   341  					&secp256k1fx.MintOutput{
   342  						OutputOwners: secp256k1fx.OutputOwners{
   343  							Threshold: 1,
   344  							Addrs:     []ids.ShortID{keys[0].PublicKey().Address()},
   345  						},
   346  					},
   347  				},
   348  			},
   349  		},
   350  	}
   351  	tx := &Tx{Unsigned: unsignedTx}
   352  	for _, key := range keys[:3] {
   353  		addr := key.PublicKey().Address()
   354  
   355  		unsignedTx.Outs = append(unsignedTx.Outs, &avax.TransferableOutput{
   356  			Asset: avax.Asset{ID: assetID},
   357  			Out: &secp256k1fx.TransferOutput{
   358  				Amt: 20 * units.KiloAvax,
   359  				OutputOwners: secp256k1fx.OutputOwners{
   360  					Threshold: 1,
   361  					Addrs:     []ids.ShortID{addr},
   362  				},
   363  			},
   364  		})
   365  	}
   366  
   367  	parser, err := NewParser(
   368  		[]fxs.Fx{
   369  			&secp256k1fx.Fx{},
   370  		},
   371  	)
   372  	require.NoError(err)
   373  	require.NoError(tx.Initialize(parser.Codec()))
   374  
   375  	result := tx.Bytes()
   376  	require.Equal(expected, result)
   377  }
   378  
   379  func TestCreateAssetTxNotState(t *testing.T) {
   380  	require := require.New(t)
   381  
   382  	intf := interface{}(&CreateAssetTx{})
   383  	_, ok := intf.(verify.State)
   384  	require.False(ok, "should not be marked as state")
   385  }