github.com/ava-labs/avalanchego@v1.11.11/vms/components/avax/transferables_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 avax 5 6 import ( 7 "testing" 8 9 "github.com/stretchr/testify/require" 10 11 "github.com/ava-labs/avalanchego/codec" 12 "github.com/ava-labs/avalanchego/codec/linearcodec" 13 "github.com/ava-labs/avalanchego/ids" 14 "github.com/ava-labs/avalanchego/utils" 15 "github.com/ava-labs/avalanchego/vms/secp256k1fx" 16 ) 17 18 func TestTransferableOutputVerifyNil(t *testing.T) { 19 to := (*TransferableOutput)(nil) 20 err := to.Verify() 21 require.ErrorIs(t, err, ErrNilTransferableOutput) 22 } 23 24 func TestTransferableOutputVerifyNilFx(t *testing.T) { 25 to := &TransferableOutput{Asset: Asset{ID: ids.Empty}} 26 err := to.Verify() 27 require.ErrorIs(t, err, ErrNilTransferableFxOutput) 28 } 29 30 func TestTransferableOutputVerify(t *testing.T) { 31 require := require.New(t) 32 33 assetID := ids.GenerateTestID() 34 to := &TransferableOutput{ 35 Asset: Asset{ID: assetID}, 36 Out: &TestTransferable{Val: 1}, 37 } 38 require.NoError(to.Verify()) 39 require.Equal(to.Out, to.Output()) 40 } 41 42 func TestTransferableOutputSorting(t *testing.T) { 43 require := require.New(t) 44 45 c := linearcodec.NewDefault() 46 require.NoError(c.RegisterType(&TestTransferable{})) 47 manager := codec.NewDefaultManager() 48 require.NoError(manager.RegisterCodec(codecVersion, c)) 49 50 assetID1 := ids.ID{1} 51 outs := []*TransferableOutput{ 52 { 53 Asset: Asset{ID: assetID1}, 54 Out: &TestTransferable{Val: 1}, 55 }, 56 { 57 Asset: Asset{ID: ids.Empty}, 58 Out: &TestTransferable{Val: 1}, 59 }, 60 { 61 Asset: Asset{ID: assetID1}, 62 Out: &TestTransferable{Val: 0}, 63 }, 64 { 65 Asset: Asset{ID: ids.Empty}, 66 Out: &TestTransferable{Val: 0}, 67 }, 68 { 69 Asset: Asset{ID: ids.Empty}, 70 Out: &TestTransferable{Val: 0}, 71 }, 72 } 73 74 require.False(IsSortedTransferableOutputs(outs, manager)) 75 SortTransferableOutputs(outs, manager) 76 require.True(IsSortedTransferableOutputs(outs, manager)) 77 require.Zero(outs[0].Out.(*TestTransferable).Val) 78 require.Zero(outs[1].Out.(*TestTransferable).Val) 79 require.Equal(uint64(1), outs[2].Out.(*TestTransferable).Val) 80 require.Equal(assetID1, outs[3].AssetID()) 81 require.Equal(assetID1, outs[4].AssetID()) 82 } 83 84 func TestTransferableOutputSerialization(t *testing.T) { 85 require := require.New(t) 86 87 c := linearcodec.NewDefault() 88 require.NoError(c.RegisterType(&secp256k1fx.TransferOutput{})) 89 manager := codec.NewDefaultManager() 90 require.NoError(manager.RegisterCodec(codecVersion, c)) 91 92 expected := []byte{ 93 // Codec version 94 0x00, 0x00, 95 // assetID: 96 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 97 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 98 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 99 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 100 // output: 101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 102 0x00, 0x00, 0x30, 0x39, 0x00, 0x00, 0x00, 0x00, 103 0x00, 0x00, 0xd4, 0x31, 0x00, 0x00, 0x00, 0x01, 104 0x00, 0x00, 0x00, 0x02, 0x51, 0x02, 0x5c, 0x61, 105 0xfb, 0xcf, 0xc0, 0x78, 0xf6, 0x93, 0x34, 0xf8, 106 0x34, 0xbe, 0x6d, 0xd2, 0x6d, 0x55, 0xa9, 0x55, 107 0xc3, 0x34, 0x41, 0x28, 0xe0, 0x60, 0x12, 0x8e, 108 0xde, 0x35, 0x23, 0xa2, 0x4a, 0x46, 0x1c, 0x89, 109 0x43, 0xab, 0x08, 0x59, 110 } 111 112 out := &TransferableOutput{ 113 Asset: Asset{ 114 ID: ids.ID{ 115 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 116 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 117 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 118 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 119 }, 120 }, 121 Out: &secp256k1fx.TransferOutput{ 122 Amt: 12345, 123 OutputOwners: secp256k1fx.OutputOwners{ 124 Locktime: 54321, 125 Threshold: 1, 126 Addrs: []ids.ShortID{ 127 { 128 0x51, 0x02, 0x5c, 0x61, 0xfb, 0xcf, 0xc0, 0x78, 129 0xf6, 0x93, 0x34, 0xf8, 0x34, 0xbe, 0x6d, 0xd2, 130 0x6d, 0x55, 0xa9, 0x55, 131 }, 132 { 133 0xc3, 0x34, 0x41, 0x28, 0xe0, 0x60, 0x12, 0x8e, 134 0xde, 0x35, 0x23, 0xa2, 0x4a, 0x46, 0x1c, 0x89, 135 0x43, 0xab, 0x08, 0x59, 136 }, 137 }, 138 }, 139 }, 140 } 141 142 outBytes, err := manager.Marshal(codecVersion, out) 143 require.NoError(err) 144 require.Equal(expected, outBytes) 145 } 146 147 func TestTransferableInputVerifyNil(t *testing.T) { 148 ti := (*TransferableInput)(nil) 149 err := ti.Verify() 150 require.ErrorIs(t, err, ErrNilTransferableInput) 151 } 152 153 func TestTransferableInputVerifyNilFx(t *testing.T) { 154 ti := &TransferableInput{ 155 UTXOID: UTXOID{TxID: ids.Empty}, 156 Asset: Asset{ID: ids.Empty}, 157 } 158 err := ti.Verify() 159 require.ErrorIs(t, err, ErrNilTransferableFxInput) 160 } 161 162 func TestTransferableInputVerify(t *testing.T) { 163 require := require.New(t) 164 165 assetID := ids.GenerateTestID() 166 ti := &TransferableInput{ 167 UTXOID: UTXOID{TxID: assetID}, 168 Asset: Asset{ID: assetID}, 169 In: &TestTransferable{}, 170 } 171 require.NoError(ti.Verify()) 172 require.Equal(ti.In, ti.Input()) 173 } 174 175 func TestTransferableInputSorting(t *testing.T) { 176 require := require.New(t) 177 178 c := linearcodec.NewDefault() 179 require.NoError(c.RegisterType(&TestTransferable{})) 180 181 ins := []*TransferableInput{ 182 { 183 UTXOID: UTXOID{ 184 TxID: ids.ID{1}, 185 OutputIndex: 1, 186 }, 187 Asset: Asset{ID: ids.Empty}, 188 In: &TestTransferable{}, 189 }, 190 { 191 UTXOID: UTXOID{ 192 TxID: ids.ID{1}, 193 OutputIndex: 0, 194 }, 195 Asset: Asset{ID: ids.Empty}, 196 In: &TestTransferable{}, 197 }, 198 { 199 UTXOID: UTXOID{ 200 TxID: ids.Empty, 201 OutputIndex: 1, 202 }, 203 Asset: Asset{ID: ids.Empty}, 204 In: &TestTransferable{}, 205 }, 206 { 207 UTXOID: UTXOID{ 208 TxID: ids.Empty, 209 OutputIndex: 0, 210 }, 211 Asset: Asset{ID: ids.Empty}, 212 In: &TestTransferable{}, 213 }, 214 } 215 216 require.False(utils.IsSortedAndUnique(ins)) 217 utils.Sort(ins) 218 require.True(utils.IsSortedAndUnique(ins)) 219 220 ins = append(ins, &TransferableInput{ 221 UTXOID: UTXOID{ 222 TxID: ids.Empty, 223 OutputIndex: 1, 224 }, 225 Asset: Asset{ID: ids.Empty}, 226 In: &TestTransferable{}, 227 }) 228 229 require.False(utils.IsSortedAndUnique(ins)) 230 } 231 232 func TestTransferableInputSerialization(t *testing.T) { 233 require := require.New(t) 234 235 c := linearcodec.NewDefault() 236 require.NoError(c.RegisterType(&secp256k1fx.TransferInput{})) 237 manager := codec.NewDefaultManager() 238 require.NoError(manager.RegisterCodec(codecVersion, c)) 239 240 expected := []byte{ 241 // Codec version 242 0x00, 0x00, 243 // txID: 244 0xf1, 0xe1, 0xd1, 0xc1, 0xb1, 0xa1, 0x91, 0x81, 245 0x71, 0x61, 0x51, 0x41, 0x31, 0x21, 0x11, 0x01, 246 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80, 247 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00, 248 // utxoIndex: 249 0x00, 0x00, 0x00, 0x05, 250 // assetID: 251 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 252 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 253 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 254 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 255 // input: 256 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 257 0x07, 0x5b, 0xcd, 0x15, 0x00, 0x00, 0x00, 0x02, 258 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 259 } 260 261 in := &TransferableInput{ 262 UTXOID: UTXOID{ 263 TxID: ids.ID{ 264 0xf1, 0xe1, 0xd1, 0xc1, 0xb1, 0xa1, 0x91, 0x81, 265 0x71, 0x61, 0x51, 0x41, 0x31, 0x21, 0x11, 0x01, 266 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80, 267 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00, 268 }, 269 OutputIndex: 5, 270 }, 271 Asset: Asset{ 272 ID: ids.ID{ 273 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 274 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 275 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 276 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 277 }, 278 }, 279 In: &secp256k1fx.TransferInput{ 280 Amt: 123456789, 281 Input: secp256k1fx.Input{ 282 SigIndices: []uint32{3, 7}, 283 }, 284 }, 285 } 286 287 inBytes, err := manager.Marshal(codecVersion, in) 288 require.NoError(err) 289 require.Equal(expected, inBytes) 290 }