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 }