github.com/ava-labs/avalanchego@v1.11.11/vms/platformvm/txs/add_permissionless_validator_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 "encoding/hex" 8 "math" 9 "testing" 10 11 "github.com/stretchr/testify/require" 12 "go.uber.org/mock/gomock" 13 14 "github.com/ava-labs/avalanchego/ids" 15 "github.com/ava-labs/avalanchego/snow" 16 "github.com/ava-labs/avalanchego/utils" 17 "github.com/ava-labs/avalanchego/utils/constants" 18 "github.com/ava-labs/avalanchego/utils/crypto/bls" 19 "github.com/ava-labs/avalanchego/utils/units" 20 "github.com/ava-labs/avalanchego/vms/components/avax" 21 "github.com/ava-labs/avalanchego/vms/components/avax/avaxmock" 22 "github.com/ava-labs/avalanchego/vms/platformvm/fx/fxmock" 23 "github.com/ava-labs/avalanchego/vms/platformvm/reward" 24 "github.com/ava-labs/avalanchego/vms/platformvm/signer" 25 "github.com/ava-labs/avalanchego/vms/platformvm/stakeable" 26 "github.com/ava-labs/avalanchego/vms/secp256k1fx" 27 "github.com/ava-labs/avalanchego/vms/types" 28 29 safemath "github.com/ava-labs/avalanchego/utils/math" 30 ) 31 32 func TestAddPermissionlessPrimaryValidator(t *testing.T) { 33 require := require.New(t) 34 35 addr := ids.ShortID{ 36 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 37 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 38 0x44, 0x55, 0x66, 0x77, 39 } 40 41 skBytes, err := hex.DecodeString("6668fecd4595b81e4d568398c820bbf3f073cb222902279fa55ebb84764ed2e3") 42 require.NoError(err) 43 44 sk, err := bls.SecretKeyFromBytes(skBytes) 45 require.NoError(err) 46 47 avaxAssetID, err := ids.FromString("FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z") 48 require.NoError(err) 49 50 customAssetID := ids.ID{ 51 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 52 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 53 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 54 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 55 } 56 57 txID := ids.ID{ 58 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 59 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 60 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 61 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 62 } 63 nodeID := ids.BuildTestNodeID([]byte{ 64 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 65 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 66 0x11, 0x22, 0x33, 0x44, 67 }) 68 69 simpleAddPrimaryTx := &AddPermissionlessValidatorTx{ 70 BaseTx: BaseTx{ 71 BaseTx: avax.BaseTx{ 72 NetworkID: constants.MainnetID, 73 BlockchainID: constants.PlatformChainID, 74 Outs: []*avax.TransferableOutput{}, 75 Ins: []*avax.TransferableInput{ 76 { 77 UTXOID: avax.UTXOID{ 78 TxID: txID, 79 OutputIndex: 1, 80 }, 81 Asset: avax.Asset{ 82 ID: avaxAssetID, 83 }, 84 In: &secp256k1fx.TransferInput{ 85 Amt: 2 * units.KiloAvax, 86 Input: secp256k1fx.Input{ 87 SigIndices: []uint32{1}, 88 }, 89 }, 90 }, 91 }, 92 Memo: types.JSONByteSlice{}, 93 }, 94 }, 95 Validator: Validator{ 96 NodeID: nodeID, 97 Start: 12345, 98 End: 12345 + 200*24*60*60, 99 Wght: 2 * units.KiloAvax, 100 }, 101 Subnet: constants.PrimaryNetworkID, 102 Signer: signer.NewProofOfPossession(sk), 103 StakeOuts: []*avax.TransferableOutput{ 104 { 105 Asset: avax.Asset{ 106 ID: avaxAssetID, 107 }, 108 Out: &secp256k1fx.TransferOutput{ 109 Amt: 2 * units.KiloAvax, 110 OutputOwners: secp256k1fx.OutputOwners{ 111 Locktime: 0, 112 Threshold: 1, 113 Addrs: []ids.ShortID{ 114 addr, 115 }, 116 }, 117 }, 118 }, 119 }, 120 ValidatorRewardsOwner: &secp256k1fx.OutputOwners{ 121 Locktime: 0, 122 Threshold: 1, 123 Addrs: []ids.ShortID{ 124 addr, 125 }, 126 }, 127 DelegatorRewardsOwner: &secp256k1fx.OutputOwners{ 128 Locktime: 0, 129 Threshold: 1, 130 Addrs: []ids.ShortID{ 131 addr, 132 }, 133 }, 134 DelegationShares: reward.PercentDenominator, 135 } 136 avax.SortTransferableOutputs(simpleAddPrimaryTx.Outs, Codec) 137 avax.SortTransferableOutputs(simpleAddPrimaryTx.StakeOuts, Codec) 138 utils.Sort(simpleAddPrimaryTx.Ins) 139 require.NoError(simpleAddPrimaryTx.SyntacticVerify(&snow.Context{ 140 NetworkID: 1, 141 ChainID: constants.PlatformChainID, 142 AVAXAssetID: avaxAssetID, 143 })) 144 145 expectedUnsignedSimpleAddPrimaryTxBytes := []byte{ 146 // Codec version 147 0x00, 0x00, 148 // AddPermissionlessValidatorTx type ID 149 0x00, 0x00, 0x00, 0x19, 150 // Mainnet network ID 151 0x00, 0x00, 0x00, 0x01, 152 // P-chain blockchain ID 153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 157 // Number of immediate outputs 158 0x00, 0x00, 0x00, 0x00, 159 // Number of inputs 160 0x00, 0x00, 0x00, 0x01, 161 // inputs[0] 162 // TxID 163 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 164 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 165 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 166 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 167 // Tx output index 168 0x00, 0x00, 0x00, 0x01, 169 // Mainnet AVAX asset ID 170 0x21, 0xe6, 0x73, 0x17, 0xcb, 0xc4, 0xbe, 0x2a, 171 0xeb, 0x00, 0x67, 0x7a, 0xd6, 0x46, 0x27, 0x78, 172 0xa8, 0xf5, 0x22, 0x74, 0xb9, 0xd6, 0x05, 0xdf, 173 0x25, 0x91, 0xb2, 0x30, 0x27, 0xa8, 0x7d, 0xff, 174 // secp256k1fx transfer input type ID 175 0x00, 0x00, 0x00, 0x05, 176 // Amount = 2k AVAX 177 0x00, 0x00, 0x01, 0xd1, 0xa9, 0x4a, 0x20, 0x00, 178 // Number of input signature indices 179 0x00, 0x00, 0x00, 0x01, 180 // signature index 181 0x00, 0x00, 0x00, 0x01, 182 // memo length 183 0x00, 0x00, 0x00, 0x00, 184 // NodeID 185 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 186 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 187 0x11, 0x22, 0x33, 0x44, 188 // Start time 189 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39, 190 // End time 191 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0xdc, 0x39, 192 // Stake weight 193 0x00, 0x00, 0x01, 0xd1, 0xa9, 0x4a, 0x20, 0x00, 194 // Primary network subnetID 195 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 196 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 197 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 199 // BLS PoP type ID 200 0x00, 0x00, 0x00, 0x1c, 201 // BLS compressed public key 202 0xaf, 0xf4, 0xac, 0xb4, 0xc5, 0x43, 0x9b, 0x5d, 203 0x42, 0x6c, 0xad, 0xf9, 0xe9, 0x46, 0xd3, 0xa4, 204 0x52, 0xf7, 0xde, 0x34, 0x14, 0xd1, 0xad, 0x27, 205 0x33, 0x61, 0x33, 0x21, 0x1d, 0x8b, 0x90, 0xcf, 206 0x49, 0xfb, 0x97, 0xee, 0xbc, 0xde, 0xee, 0xf7, 207 0x14, 0xdc, 0x20, 0xf5, 0x4e, 0xd0, 0xd4, 0xd1, 208 // BLS compressed signature length 209 0x8c, 0xfd, 0x79, 0x09, 0xd1, 0x53, 0xb9, 0x60, 210 0x4b, 0x62, 0xb1, 0x43, 0xba, 0x36, 0x20, 0x7b, 211 0xb7, 0xe6, 0x48, 0x67, 0x42, 0x44, 0x80, 0x20, 212 0x2a, 0x67, 0xdc, 0x68, 0x76, 0x83, 0x46, 0xd9, 213 0x5c, 0x90, 0x98, 0x3c, 0x2d, 0x27, 0x9c, 0x64, 214 0xc4, 0x3c, 0x51, 0x13, 0x6b, 0x2a, 0x05, 0xe0, 215 0x16, 0x02, 0xd5, 0x2a, 0xa6, 0x37, 0x6f, 0xda, 216 0x17, 0xfa, 0x6e, 0x2a, 0x18, 0xa0, 0x83, 0xe4, 217 0x9d, 0x9c, 0x45, 0x0e, 0xab, 0x7b, 0x89, 0xb1, 218 0xd5, 0x55, 0x5d, 0xa5, 0xc4, 0x89, 0x87, 0x2e, 219 0x02, 0xb7, 0xe5, 0x22, 0x7b, 0x77, 0x55, 0x0a, 220 0xf1, 0x33, 0x0e, 0x5a, 0x71, 0xf8, 0xc3, 0x68, 221 // Number of locked outputs 222 0x00, 0x00, 0x00, 0x01, 223 // Mainnet AVAX asset ID 224 0x21, 0xe6, 0x73, 0x17, 0xcb, 0xc4, 0xbe, 0x2a, 225 0xeb, 0x00, 0x67, 0x7a, 0xd6, 0x46, 0x27, 0x78, 226 0xa8, 0xf5, 0x22, 0x74, 0xb9, 0xd6, 0x05, 0xdf, 227 0x25, 0x91, 0xb2, 0x30, 0x27, 0xa8, 0x7d, 0xff, 228 // secp256k1fx transferable output type ID 229 0x00, 0x00, 0x00, 0x07, 230 // amount 231 0x00, 0x00, 0x01, 0xd1, 0xa9, 0x4a, 0x20, 0x00, 232 // locktime 233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 234 // threshold 235 0x00, 0x00, 0x00, 0x01, 236 // number of addresses 237 0x00, 0x00, 0x00, 0x01, 238 // addresses[0] 239 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 240 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 241 0x44, 0x55, 0x66, 0x77, 242 // secp256k1fx owner type ID 243 0x00, 0x00, 0x00, 0x0b, 244 // locktime 245 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 246 // threshold 247 0x00, 0x00, 0x00, 0x01, 248 // number of addresses 249 0x00, 0x00, 0x00, 0x01, 250 // addresses[0] 251 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 252 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 253 0x44, 0x55, 0x66, 0x77, 254 // secp256k1fx owner type ID 255 0x00, 0x00, 0x00, 0x0b, 256 // locktime 257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 258 // threshold 259 0x00, 0x00, 0x00, 0x01, 260 // number of addresses 261 0x00, 0x00, 0x00, 0x01, 262 // addresses[0] 263 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 264 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 265 0x44, 0x55, 0x66, 0x77, 266 // delegation shares 267 0x00, 0x0f, 0x42, 0x40, 268 } 269 var unsignedSimpleAddPrimaryTx UnsignedTx = simpleAddPrimaryTx 270 unsignedSimpleAddPrimaryTxBytes, err := Codec.Marshal(CodecVersion, &unsignedSimpleAddPrimaryTx) 271 require.NoError(err) 272 require.Equal(expectedUnsignedSimpleAddPrimaryTxBytes, unsignedSimpleAddPrimaryTxBytes) 273 274 complexAddPrimaryTx := &AddPermissionlessValidatorTx{ 275 BaseTx: BaseTx{ 276 BaseTx: avax.BaseTx{ 277 NetworkID: constants.MainnetID, 278 BlockchainID: constants.PlatformChainID, 279 Outs: []*avax.TransferableOutput{ 280 { 281 Asset: avax.Asset{ 282 ID: avaxAssetID, 283 }, 284 Out: &secp256k1fx.TransferOutput{ 285 Amt: 1, 286 OutputOwners: secp256k1fx.OutputOwners{ 287 Locktime: 0, 288 Threshold: 1, 289 Addrs: []ids.ShortID{ 290 addr, 291 }, 292 }, 293 }, 294 }, 295 { 296 Asset: avax.Asset{ 297 ID: avaxAssetID, 298 }, 299 Out: &stakeable.LockOut{ 300 Locktime: 87654321, 301 TransferableOut: &secp256k1fx.TransferOutput{ 302 Amt: 1, 303 OutputOwners: secp256k1fx.OutputOwners{ 304 Locktime: 12345678, 305 Threshold: 0, 306 Addrs: []ids.ShortID{}, 307 }, 308 }, 309 }, 310 }, 311 { 312 Asset: avax.Asset{ 313 ID: customAssetID, 314 }, 315 Out: &stakeable.LockOut{ 316 Locktime: 876543210, 317 TransferableOut: &secp256k1fx.TransferOutput{ 318 Amt: 0xffffffffffffffff, 319 OutputOwners: secp256k1fx.OutputOwners{ 320 Locktime: 0, 321 Threshold: 1, 322 Addrs: []ids.ShortID{ 323 addr, 324 }, 325 }, 326 }, 327 }, 328 }, 329 }, 330 Ins: []*avax.TransferableInput{ 331 { 332 UTXOID: avax.UTXOID{ 333 TxID: txID, 334 OutputIndex: 1, 335 }, 336 Asset: avax.Asset{ 337 ID: avaxAssetID, 338 }, 339 In: &secp256k1fx.TransferInput{ 340 Amt: units.MegaAvax, 341 Input: secp256k1fx.Input{ 342 SigIndices: []uint32{2, 5}, 343 }, 344 }, 345 }, 346 { 347 UTXOID: avax.UTXOID{ 348 TxID: txID, 349 OutputIndex: 2, 350 }, 351 Asset: avax.Asset{ 352 ID: customAssetID, 353 }, 354 In: &stakeable.LockIn{ 355 Locktime: 876543210, 356 TransferableIn: &secp256k1fx.TransferInput{ 357 Amt: 0xefffffffffffffff, 358 Input: secp256k1fx.Input{ 359 SigIndices: []uint32{0}, 360 }, 361 }, 362 }, 363 }, 364 { 365 UTXOID: avax.UTXOID{ 366 TxID: txID, 367 OutputIndex: 3, 368 }, 369 Asset: avax.Asset{ 370 ID: customAssetID, 371 }, 372 In: &secp256k1fx.TransferInput{ 373 Amt: 0x1000000000000000, 374 Input: secp256k1fx.Input{ 375 SigIndices: []uint32{}, 376 }, 377 }, 378 }, 379 }, 380 Memo: types.JSONByteSlice("😅\nwell that's\x01\x23\x45!"), 381 }, 382 }, 383 Validator: Validator{ 384 NodeID: nodeID, 385 Start: 12345, 386 End: 12345 + 200*24*60*60, 387 Wght: 5 * units.KiloAvax, 388 }, 389 Subnet: constants.PrimaryNetworkID, 390 Signer: signer.NewProofOfPossession(sk), 391 StakeOuts: []*avax.TransferableOutput{ 392 { 393 Asset: avax.Asset{ 394 ID: avaxAssetID, 395 }, 396 Out: &secp256k1fx.TransferOutput{ 397 Amt: 2 * units.KiloAvax, 398 OutputOwners: secp256k1fx.OutputOwners{ 399 Locktime: 0, 400 Threshold: 1, 401 Addrs: []ids.ShortID{ 402 addr, 403 }, 404 }, 405 }, 406 }, 407 { 408 Asset: avax.Asset{ 409 ID: avaxAssetID, 410 }, 411 Out: &stakeable.LockOut{ 412 Locktime: 987654321, 413 TransferableOut: &secp256k1fx.TransferOutput{ 414 Amt: 3 * units.KiloAvax, 415 OutputOwners: secp256k1fx.OutputOwners{ 416 Locktime: 87654321, 417 Threshold: 0, 418 Addrs: []ids.ShortID{}, 419 }, 420 }, 421 }, 422 }, 423 }, 424 ValidatorRewardsOwner: &secp256k1fx.OutputOwners{ 425 Locktime: 0, 426 Threshold: 1, 427 Addrs: []ids.ShortID{ 428 addr, 429 }, 430 }, 431 DelegatorRewardsOwner: &secp256k1fx.OutputOwners{ 432 Locktime: 0, 433 Threshold: 0, 434 Addrs: []ids.ShortID{}, 435 }, 436 DelegationShares: reward.PercentDenominator, 437 } 438 require.NoError(complexAddPrimaryTx.SyntacticVerify(&snow.Context{ 439 NetworkID: 1, 440 ChainID: constants.PlatformChainID, 441 AVAXAssetID: avaxAssetID, 442 })) 443 444 expectedUnsignedComplexAddPrimaryTxBytes := []byte{ 445 // Codec version 446 0x00, 0x00, 447 // AddPermissionlessValidatorTx type ID 448 0x00, 0x00, 0x00, 0x19, 449 // Mainnet network ID 450 0x00, 0x00, 0x00, 0x01, 451 // P-chain blockchain ID 452 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 453 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 455 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 456 // Number of immediate outputs 457 0x00, 0x00, 0x00, 0x03, 458 // outputs[0] 459 // Mainnet AVAX asset ID 460 0x21, 0xe6, 0x73, 0x17, 0xcb, 0xc4, 0xbe, 0x2a, 461 0xeb, 0x00, 0x67, 0x7a, 0xd6, 0x46, 0x27, 0x78, 462 0xa8, 0xf5, 0x22, 0x74, 0xb9, 0xd6, 0x05, 0xdf, 463 0x25, 0x91, 0xb2, 0x30, 0x27, 0xa8, 0x7d, 0xff, 464 // secp256k1fx transfer output type ID 465 0x00, 0x00, 0x00, 0x07, 466 // amount 467 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 468 // locktime 469 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 470 // threshold 471 0x00, 0x00, 0x00, 0x01, 472 // number of addresses 473 0x00, 0x00, 0x00, 0x01, 474 // addresses[0] 475 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 476 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 477 0x44, 0x55, 0x66, 0x77, 478 // outputs[1] 479 // Mainnet AVAX asset ID 480 0x21, 0xe6, 0x73, 0x17, 0xcb, 0xc4, 0xbe, 0x2a, 481 0xeb, 0x00, 0x67, 0x7a, 0xd6, 0x46, 0x27, 0x78, 482 0xa8, 0xf5, 0x22, 0x74, 0xb9, 0xd6, 0x05, 0xdf, 483 0x25, 0x91, 0xb2, 0x30, 0x27, 0xa8, 0x7d, 0xff, 484 // stakeable locked output type ID 485 0x00, 0x00, 0x00, 0x16, 486 // locktime 487 0x00, 0x00, 0x00, 0x00, 0x05, 0x39, 0x7f, 0xb1, 488 // secp256k1fx transfer output type ID 489 0x00, 0x00, 0x00, 0x07, 490 // amount 491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 492 // locktime 493 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x61, 0x4e, 494 // threshold 495 0x00, 0x00, 0x00, 0x00, 496 // number of addresses 497 0x00, 0x00, 0x00, 0x00, 498 // outputs[2] 499 // custom asset ID 500 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 501 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 502 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 503 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 504 // stakeable locked output type ID 505 0x00, 0x00, 0x00, 0x16, 506 // locktime 507 0x00, 0x00, 0x00, 0x00, 0x34, 0x3e, 0xfc, 0xea, 508 // secp256k1fx transfer output type ID 509 0x00, 0x00, 0x00, 0x07, 510 // amount 511 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 512 // locktime 513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 514 // threshold 515 0x00, 0x00, 0x00, 0x01, 516 // number of addresses 517 0x00, 0x00, 0x00, 0x01, 518 // address[0] 519 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 520 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 521 0x44, 0x55, 0x66, 0x77, 522 // number of inputs 523 0x00, 0x00, 0x00, 0x03, 524 // inputs[0] 525 // TxID 526 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 527 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 528 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 529 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 530 // Tx output index 531 0x00, 0x00, 0x00, 0x01, 532 // Mainnet AVAX asset ID 533 0x21, 0xe6, 0x73, 0x17, 0xcb, 0xc4, 0xbe, 0x2a, 534 0xeb, 0x00, 0x67, 0x7a, 0xd6, 0x46, 0x27, 0x78, 535 0xa8, 0xf5, 0x22, 0x74, 0xb9, 0xd6, 0x05, 0xdf, 536 0x25, 0x91, 0xb2, 0x30, 0x27, 0xa8, 0x7d, 0xff, 537 // secp256k1fx transfer input type ID 538 0x00, 0x00, 0x00, 0x05, 539 // amount 540 0x00, 0x03, 0x8d, 0x7e, 0xa4, 0xc6, 0x80, 0x00, 541 // number of signature indices 542 0x00, 0x00, 0x00, 0x02, 543 // first signature index 544 0x00, 0x00, 0x00, 0x02, 545 // second signature index 546 0x00, 0x00, 0x00, 0x05, 547 // inputs[1] 548 // TxID 549 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 550 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 551 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 552 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 553 // Tx output index 554 0x00, 0x00, 0x00, 0x02, 555 // custom asset ID 556 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 557 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 558 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 559 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 560 // stakeable locked input type ID 561 0x00, 0x00, 0x00, 0x15, 562 // locktime 563 0x00, 0x00, 0x00, 0x00, 0x34, 0x3e, 0xfc, 0xea, 564 // secp256k1fx transfer input type ID 565 0x00, 0x00, 0x00, 0x05, 566 // amount 567 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 568 // number of signature indices 569 0x00, 0x00, 0x00, 0x01, 570 // signature index 571 0x00, 0x00, 0x00, 0x00, 572 // inputs[2] 573 // TxID 574 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 575 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 576 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 577 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 578 // Tx output index 579 0x00, 0x00, 0x00, 0x03, 580 // custom asset ID 581 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 582 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 583 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 584 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 585 // secp256k1 transfer input type ID 586 0x00, 0x00, 0x00, 0x05, 587 // amount 588 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 589 // number of signature indices 590 0x00, 0x00, 0x00, 0x00, 591 // memo length 592 0x00, 0x00, 0x00, 0x14, 593 // memo 594 0xf0, 0x9f, 0x98, 0x85, 0x0a, 0x77, 0x65, 0x6c, 595 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x27, 0x73, 596 0x01, 0x23, 0x45, 0x21, 597 // nodeID 598 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 599 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 600 0x11, 0x22, 0x33, 0x44, 601 // Start time 602 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39, 603 // End time 604 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0xdc, 0x39, 605 // Stake weight 606 0x00, 0x00, 0x04, 0x8c, 0x27, 0x39, 0x50, 0x00, 607 // Primary Network subnet ID 608 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 609 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 610 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 611 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 612 // BLS PoP type ID 613 0x00, 0x00, 0x00, 0x1c, 614 // BLS compressed public key 615 0xaf, 0xf4, 0xac, 0xb4, 0xc5, 0x43, 0x9b, 0x5d, 616 0x42, 0x6c, 0xad, 0xf9, 0xe9, 0x46, 0xd3, 0xa4, 617 0x52, 0xf7, 0xde, 0x34, 0x14, 0xd1, 0xad, 0x27, 618 0x33, 0x61, 0x33, 0x21, 0x1d, 0x8b, 0x90, 0xcf, 619 0x49, 0xfb, 0x97, 0xee, 0xbc, 0xde, 0xee, 0xf7, 620 0x14, 0xdc, 0x20, 0xf5, 0x4e, 0xd0, 0xd4, 0xd1, 621 // BLS compressed signature 622 0x8c, 0xfd, 0x79, 0x09, 0xd1, 0x53, 0xb9, 0x60, 623 0x4b, 0x62, 0xb1, 0x43, 0xba, 0x36, 0x20, 0x7b, 624 0xb7, 0xe6, 0x48, 0x67, 0x42, 0x44, 0x80, 0x20, 625 0x2a, 0x67, 0xdc, 0x68, 0x76, 0x83, 0x46, 0xd9, 626 0x5c, 0x90, 0x98, 0x3c, 0x2d, 0x27, 0x9c, 0x64, 627 0xc4, 0x3c, 0x51, 0x13, 0x6b, 0x2a, 0x05, 0xe0, 628 0x16, 0x02, 0xd5, 0x2a, 0xa6, 0x37, 0x6f, 0xda, 629 0x17, 0xfa, 0x6e, 0x2a, 0x18, 0xa0, 0x83, 0xe4, 630 0x9d, 0x9c, 0x45, 0x0e, 0xab, 0x7b, 0x89, 0xb1, 631 0xd5, 0x55, 0x5d, 0xa5, 0xc4, 0x89, 0x87, 0x2e, 632 0x02, 0xb7, 0xe5, 0x22, 0x7b, 0x77, 0x55, 0x0a, 633 0xf1, 0x33, 0x0e, 0x5a, 0x71, 0xf8, 0xc3, 0x68, 634 // number of locked outputs 635 0x00, 0x00, 0x00, 0x02, 636 // Mainnet AVAX asset ID 637 0x21, 0xe6, 0x73, 0x17, 0xcb, 0xc4, 0xbe, 0x2a, 638 0xeb, 0x00, 0x67, 0x7a, 0xd6, 0x46, 0x27, 0x78, 639 0xa8, 0xf5, 0x22, 0x74, 0xb9, 0xd6, 0x05, 0xdf, 640 0x25, 0x91, 0xb2, 0x30, 0x27, 0xa8, 0x7d, 0xff, 641 // secp256k1 transfer output type ID 642 0x00, 0x00, 0x00, 0x07, 643 // amount 644 0x00, 0x00, 0x01, 0xd1, 0xa9, 0x4a, 0x20, 0x00, 645 // locktime 646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 647 // threshold 648 0x00, 0x00, 0x00, 0x01, 649 // number of addresses 650 0x00, 0x00, 0x00, 0x01, 651 // addresses[0] 652 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 653 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 654 0x44, 0x55, 0x66, 0x77, 655 // Mainnet AVAX asset ID 656 0x21, 0xe6, 0x73, 0x17, 0xcb, 0xc4, 0xbe, 0x2a, 657 0xeb, 0x00, 0x67, 0x7a, 0xd6, 0x46, 0x27, 0x78, 658 0xa8, 0xf5, 0x22, 0x74, 0xb9, 0xd6, 0x05, 0xdf, 659 0x25, 0x91, 0xb2, 0x30, 0x27, 0xa8, 0x7d, 0xff, 660 // stakeable locked output type ID 661 0x00, 0x00, 0x00, 0x16, 662 // locktime 663 0x00, 0x00, 0x00, 0x00, 0x3a, 0xde, 0x68, 0xb1, 664 // secp256k1 transfer output type ID 665 0x00, 0x00, 0x00, 0x07, 666 // amount 667 0x00, 0x00, 0x02, 0xba, 0x7d, 0xef, 0x30, 0x00, 668 // locktime 669 0x00, 0x00, 0x00, 0x00, 0x05, 0x39, 0x7f, 0xb1, 670 // threshold 671 0x00, 0x00, 0x00, 0x00, 672 // number of addresses 673 0x00, 0x00, 0x00, 0x00, 674 // secp256k1 owner type ID 675 0x00, 0x00, 0x00, 0x0b, 676 // locktime 677 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 678 // threshold 679 0x00, 0x00, 0x00, 0x01, 680 // number of addresses 681 0x00, 0x00, 0x00, 0x01, 682 // addresses[0] 683 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 684 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 685 0x44, 0x55, 0x66, 0x77, 686 // secp256k1 owner type ID 687 0x00, 0x00, 0x00, 0x0b, 688 // locktime 689 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 690 // threshold 691 0x00, 0x00, 0x00, 0x00, 692 // number of addresses 693 0x00, 0x00, 0x00, 0x00, 694 // delegation shares 695 0x00, 0x0f, 0x42, 0x40, 696 } 697 var unsignedComplexAddPrimaryTx UnsignedTx = complexAddPrimaryTx 698 unsignedComplexAddPrimaryTxBytes, err := Codec.Marshal(CodecVersion, &unsignedComplexAddPrimaryTx) 699 require.NoError(err) 700 require.Equal(expectedUnsignedComplexAddPrimaryTxBytes, unsignedComplexAddPrimaryTxBytes) 701 } 702 703 func TestAddPermissionlessSubnetValidator(t *testing.T) { 704 require := require.New(t) 705 706 addr := ids.ShortID{ 707 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 708 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 709 0x44, 0x55, 0x66, 0x77, 710 } 711 712 avaxAssetID, err := ids.FromString("FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z") 713 require.NoError(err) 714 715 customAssetID := ids.ID{ 716 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 717 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 718 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 719 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 720 } 721 722 txID := ids.ID{ 723 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 724 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 725 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 726 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 727 } 728 nodeID := ids.BuildTestNodeID([]byte{ 729 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 730 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 731 0x11, 0x22, 0x33, 0x44, 732 }) 733 subnetID := ids.ID{ 734 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 735 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 736 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 737 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 738 } 739 740 simpleAddSubnetTx := &AddPermissionlessValidatorTx{ 741 BaseTx: BaseTx{ 742 BaseTx: avax.BaseTx{ 743 NetworkID: constants.MainnetID, 744 BlockchainID: constants.PlatformChainID, 745 Outs: []*avax.TransferableOutput{}, 746 Ins: []*avax.TransferableInput{ 747 { 748 UTXOID: avax.UTXOID{ 749 TxID: txID, 750 OutputIndex: 1, 751 }, 752 Asset: avax.Asset{ 753 ID: avaxAssetID, 754 }, 755 In: &secp256k1fx.TransferInput{ 756 Amt: units.MilliAvax, 757 Input: secp256k1fx.Input{ 758 SigIndices: []uint32{1}, 759 }, 760 }, 761 }, 762 { 763 UTXOID: avax.UTXOID{ 764 TxID: txID, 765 OutputIndex: 2, 766 }, 767 Asset: avax.Asset{ 768 ID: customAssetID, 769 }, 770 In: &secp256k1fx.TransferInput{ 771 Amt: 1, 772 Input: secp256k1fx.Input{ 773 SigIndices: []uint32{1}, 774 }, 775 }, 776 }, 777 }, 778 Memo: types.JSONByteSlice{}, 779 }, 780 }, 781 Validator: Validator{ 782 NodeID: nodeID, 783 Start: 12345, 784 End: 12346, 785 Wght: 1, 786 }, 787 Subnet: subnetID, 788 Signer: &signer.Empty{}, 789 StakeOuts: []*avax.TransferableOutput{ 790 { 791 Asset: avax.Asset{ 792 ID: customAssetID, 793 }, 794 Out: &secp256k1fx.TransferOutput{ 795 Amt: 1, 796 OutputOwners: secp256k1fx.OutputOwners{ 797 Locktime: 0, 798 Threshold: 1, 799 Addrs: []ids.ShortID{ 800 addr, 801 }, 802 }, 803 }, 804 }, 805 }, 806 ValidatorRewardsOwner: &secp256k1fx.OutputOwners{ 807 Locktime: 0, 808 Threshold: 1, 809 Addrs: []ids.ShortID{ 810 addr, 811 }, 812 }, 813 DelegatorRewardsOwner: &secp256k1fx.OutputOwners{ 814 Locktime: 0, 815 Threshold: 1, 816 Addrs: []ids.ShortID{ 817 addr, 818 }, 819 }, 820 DelegationShares: reward.PercentDenominator, 821 } 822 avax.SortTransferableOutputs(simpleAddSubnetTx.Outs, Codec) 823 avax.SortTransferableOutputs(simpleAddSubnetTx.StakeOuts, Codec) 824 utils.Sort(simpleAddSubnetTx.Ins) 825 require.NoError(simpleAddSubnetTx.SyntacticVerify(&snow.Context{ 826 NetworkID: 1, 827 ChainID: constants.PlatformChainID, 828 AVAXAssetID: avaxAssetID, 829 })) 830 831 expectedUnsignedSimpleAddSubnetTxBytes := []byte{ 832 // Codec version 833 0x00, 0x00, 834 // AddPermissionlessValidatorTx type ID 835 0x00, 0x00, 0x00, 0x19, 836 // Mainnet network ID 837 0x00, 0x00, 0x00, 0x01, 838 // P-chain blockchain ID 839 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 840 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 841 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 842 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 843 // Number of immediate outputs 844 0x00, 0x00, 0x00, 0x00, 845 // Number of inputs 846 0x00, 0x00, 0x00, 0x02, 847 // inputs[0] 848 // TxID 849 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 850 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 851 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 852 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 853 // Tx output index 854 0x00, 0x00, 0x00, 0x01, 855 // Mainnet AVAX asset ID 856 0x21, 0xe6, 0x73, 0x17, 0xcb, 0xc4, 0xbe, 0x2a, 857 0xeb, 0x00, 0x67, 0x7a, 0xd6, 0x46, 0x27, 0x78, 858 0xa8, 0xf5, 0x22, 0x74, 0xb9, 0xd6, 0x05, 0xdf, 859 0x25, 0x91, 0xb2, 0x30, 0x27, 0xa8, 0x7d, 0xff, 860 // secp256k1fx transfer input type ID 861 0x00, 0x00, 0x00, 0x05, 862 // Amount = 1 MilliAVAX 863 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x42, 0x40, 864 // Number of input signature indices 865 0x00, 0x00, 0x00, 0x01, 866 // signature index 867 0x00, 0x00, 0x00, 0x01, 868 // inputs[1] 869 // TxID 870 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 871 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 872 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 873 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 874 // Tx output index 875 0x00, 0x00, 0x00, 0x02, 876 // custom asset ID 877 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 878 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 879 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 880 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 881 // secp256k1fx transfer input type ID 882 0x00, 0x00, 0x00, 0x05, 883 // Amount 884 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 885 // Number of input signature indices 886 0x00, 0x00, 0x00, 0x01, 887 // signature index 888 0x00, 0x00, 0x00, 0x01, 889 // memo length 890 0x00, 0x00, 0x00, 0x00, 891 // NodeID 892 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 893 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 894 0x11, 0x22, 0x33, 0x44, 895 // Start time 896 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39, 897 // End time 898 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3a, 899 // Stake weight 900 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 901 // SubnetID 902 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 903 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 904 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 905 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 906 // No signer type ID 907 0x00, 0x00, 0x00, 0x1b, 908 // Number of locked outputs 909 0x00, 0x00, 0x00, 0x01, 910 // custom asset ID 911 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 912 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 913 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 914 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 915 // secp256k1fx transferable output type ID 916 0x00, 0x00, 0x00, 0x07, 917 // amount 918 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 919 // locktime 920 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 921 // threshold 922 0x00, 0x00, 0x00, 0x01, 923 // number of addresses 924 0x00, 0x00, 0x00, 0x01, 925 // addresses[0] 926 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 927 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 928 0x44, 0x55, 0x66, 0x77, 929 // secp256k1fx owner type ID 930 0x00, 0x00, 0x00, 0x0b, 931 // locktime 932 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 933 // threshold 934 0x00, 0x00, 0x00, 0x01, 935 // number of addresses 936 0x00, 0x00, 0x00, 0x01, 937 // addresses[0] 938 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 939 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 940 0x44, 0x55, 0x66, 0x77, 941 // secp256k1fx owner type ID 942 0x00, 0x00, 0x00, 0x0b, 943 // locktime 944 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 945 // threshold 946 0x00, 0x00, 0x00, 0x01, 947 // number of addresses 948 0x00, 0x00, 0x00, 0x01, 949 // addresses[0] 950 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 951 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 952 0x44, 0x55, 0x66, 0x77, 953 // delegation shares 954 0x00, 0x0f, 0x42, 0x40, 955 } 956 var unsignedSimpleAddSubnetTx UnsignedTx = simpleAddSubnetTx 957 unsignedSimpleAddSubnetTxBytes, err := Codec.Marshal(CodecVersion, &unsignedSimpleAddSubnetTx) 958 require.NoError(err) 959 require.Equal(expectedUnsignedSimpleAddSubnetTxBytes, unsignedSimpleAddSubnetTxBytes) 960 961 complexAddSubnetTx := &AddPermissionlessValidatorTx{ 962 BaseTx: BaseTx{ 963 BaseTx: avax.BaseTx{ 964 NetworkID: constants.MainnetID, 965 BlockchainID: constants.PlatformChainID, 966 Outs: []*avax.TransferableOutput{ 967 { 968 Asset: avax.Asset{ 969 ID: avaxAssetID, 970 }, 971 Out: &secp256k1fx.TransferOutput{ 972 Amt: 1, 973 OutputOwners: secp256k1fx.OutputOwners{ 974 Locktime: 0, 975 Threshold: 1, 976 Addrs: []ids.ShortID{ 977 addr, 978 }, 979 }, 980 }, 981 }, 982 { 983 Asset: avax.Asset{ 984 ID: avaxAssetID, 985 }, 986 Out: &stakeable.LockOut{ 987 Locktime: 87654321, 988 TransferableOut: &secp256k1fx.TransferOutput{ 989 Amt: 1, 990 OutputOwners: secp256k1fx.OutputOwners{ 991 Locktime: 12345678, 992 Threshold: 0, 993 Addrs: []ids.ShortID{}, 994 }, 995 }, 996 }, 997 }, 998 { 999 Asset: avax.Asset{ 1000 ID: customAssetID, 1001 }, 1002 Out: &stakeable.LockOut{ 1003 Locktime: 876543210, 1004 TransferableOut: &secp256k1fx.TransferOutput{ 1005 Amt: 0xfffffffffffffff0, 1006 OutputOwners: secp256k1fx.OutputOwners{ 1007 Locktime: 0, 1008 Threshold: 1, 1009 Addrs: []ids.ShortID{ 1010 addr, 1011 }, 1012 }, 1013 }, 1014 }, 1015 }, 1016 }, 1017 Ins: []*avax.TransferableInput{ 1018 { 1019 UTXOID: avax.UTXOID{ 1020 TxID: txID, 1021 OutputIndex: 1, 1022 }, 1023 Asset: avax.Asset{ 1024 ID: avaxAssetID, 1025 }, 1026 In: &secp256k1fx.TransferInput{ 1027 Amt: units.MegaAvax, 1028 Input: secp256k1fx.Input{ 1029 SigIndices: []uint32{2, 5}, 1030 }, 1031 }, 1032 }, 1033 { 1034 UTXOID: avax.UTXOID{ 1035 TxID: txID, 1036 OutputIndex: 2, 1037 }, 1038 Asset: avax.Asset{ 1039 ID: customAssetID, 1040 }, 1041 In: &stakeable.LockIn{ 1042 Locktime: 876543210, 1043 TransferableIn: &secp256k1fx.TransferInput{ 1044 Amt: 0xefffffffffffffff, 1045 Input: secp256k1fx.Input{ 1046 SigIndices: []uint32{0}, 1047 }, 1048 }, 1049 }, 1050 }, 1051 { 1052 UTXOID: avax.UTXOID{ 1053 TxID: txID, 1054 OutputIndex: 3, 1055 }, 1056 Asset: avax.Asset{ 1057 ID: customAssetID, 1058 }, 1059 In: &secp256k1fx.TransferInput{ 1060 Amt: 0x1000000000000000, 1061 Input: secp256k1fx.Input{ 1062 SigIndices: []uint32{}, 1063 }, 1064 }, 1065 }, 1066 }, 1067 Memo: types.JSONByteSlice("😅\nwell that's\x01\x23\x45!"), 1068 }, 1069 }, 1070 Validator: Validator{ 1071 NodeID: nodeID, 1072 Start: 12345, 1073 End: 12345 + 1, 1074 Wght: 9, 1075 }, 1076 Subnet: subnetID, 1077 Signer: &signer.Empty{}, 1078 StakeOuts: []*avax.TransferableOutput{ 1079 { 1080 Asset: avax.Asset{ 1081 ID: customAssetID, 1082 }, 1083 Out: &secp256k1fx.TransferOutput{ 1084 Amt: 2, 1085 OutputOwners: secp256k1fx.OutputOwners{ 1086 Locktime: 0, 1087 Threshold: 1, 1088 Addrs: []ids.ShortID{ 1089 addr, 1090 }, 1091 }, 1092 }, 1093 }, 1094 { 1095 Asset: avax.Asset{ 1096 ID: customAssetID, 1097 }, 1098 Out: &stakeable.LockOut{ 1099 Locktime: 987654321, 1100 TransferableOut: &secp256k1fx.TransferOutput{ 1101 Amt: 7, 1102 OutputOwners: secp256k1fx.OutputOwners{ 1103 Locktime: 87654321, 1104 Threshold: 0, 1105 Addrs: []ids.ShortID{}, 1106 }, 1107 }, 1108 }, 1109 }, 1110 }, 1111 ValidatorRewardsOwner: &secp256k1fx.OutputOwners{ 1112 Locktime: 0, 1113 Threshold: 1, 1114 Addrs: []ids.ShortID{ 1115 addr, 1116 }, 1117 }, 1118 DelegatorRewardsOwner: &secp256k1fx.OutputOwners{ 1119 Locktime: 0, 1120 Threshold: 0, 1121 Addrs: []ids.ShortID{}, 1122 }, 1123 DelegationShares: reward.PercentDenominator, 1124 } 1125 require.NoError(complexAddSubnetTx.SyntacticVerify(&snow.Context{ 1126 NetworkID: 1, 1127 ChainID: constants.PlatformChainID, 1128 AVAXAssetID: avaxAssetID, 1129 })) 1130 1131 expectedUnsignedComplexAddSubnetTxBytes := []byte{ 1132 // Codec version 1133 0x00, 0x00, 1134 // AddPermissionlessValidatorTx type ID 1135 0x00, 0x00, 0x00, 0x19, 1136 // Mainnet network ID 1137 0x00, 0x00, 0x00, 0x01, 1138 // P-chain blockchain ID 1139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1143 // Number of immediate outputs 1144 0x00, 0x00, 0x00, 0x03, 1145 // outputs[0] 1146 // Mainnet AVAX asset ID 1147 0x21, 0xe6, 0x73, 0x17, 0xcb, 0xc4, 0xbe, 0x2a, 1148 0xeb, 0x00, 0x67, 0x7a, 0xd6, 0x46, 0x27, 0x78, 1149 0xa8, 0xf5, 0x22, 0x74, 0xb9, 0xd6, 0x05, 0xdf, 1150 0x25, 0x91, 0xb2, 0x30, 0x27, 0xa8, 0x7d, 0xff, 1151 // secp256k1fx transfer output type ID 1152 0x00, 0x00, 0x00, 0x07, 1153 // amount 1154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 1155 // locktime 1156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1157 // threshold 1158 0x00, 0x00, 0x00, 0x01, 1159 // number of addresses 1160 0x00, 0x00, 0x00, 0x01, 1161 // addresses[0] 1162 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 1163 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 1164 0x44, 0x55, 0x66, 0x77, 1165 // outputs[1] 1166 // Mainnet AVAX asset ID 1167 0x21, 0xe6, 0x73, 0x17, 0xcb, 0xc4, 0xbe, 0x2a, 1168 0xeb, 0x00, 0x67, 0x7a, 0xd6, 0x46, 0x27, 0x78, 1169 0xa8, 0xf5, 0x22, 0x74, 0xb9, 0xd6, 0x05, 0xdf, 1170 0x25, 0x91, 0xb2, 0x30, 0x27, 0xa8, 0x7d, 0xff, 1171 // stakeable locked output type ID 1172 0x00, 0x00, 0x00, 0x16, 1173 // locktime 1174 0x00, 0x00, 0x00, 0x00, 0x05, 0x39, 0x7f, 0xb1, 1175 // secp256k1fx transfer output type ID 1176 0x00, 0x00, 0x00, 0x07, 1177 // amount 1178 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 1179 // locktime 1180 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x61, 0x4e, 1181 // threshold 1182 0x00, 0x00, 0x00, 0x00, 1183 // number of addresses 1184 0x00, 0x00, 0x00, 0x00, 1185 // outputs[2] 1186 // custom asset ID 1187 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 1188 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 1189 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 1190 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 1191 // stakeable locked output type ID 1192 0x00, 0x00, 0x00, 0x16, 1193 // locktime 1194 0x00, 0x00, 0x00, 0x00, 0x34, 0x3e, 0xfc, 0xea, 1195 // secp256k1fx transfer output type ID 1196 0x00, 0x00, 0x00, 0x07, 1197 // amount 1198 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 1199 // locktime 1200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1201 // threshold 1202 0x00, 0x00, 0x00, 0x01, 1203 // number of addresses 1204 0x00, 0x00, 0x00, 0x01, 1205 // address[0] 1206 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 1207 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 1208 0x44, 0x55, 0x66, 0x77, 1209 // number of inputs 1210 0x00, 0x00, 0x00, 0x03, 1211 // inputs[0] 1212 // TxID 1213 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 1214 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 1215 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 1216 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 1217 // Tx output index 1218 0x00, 0x00, 0x00, 0x01, 1219 // Mainnet AVAX asset ID 1220 0x21, 0xe6, 0x73, 0x17, 0xcb, 0xc4, 0xbe, 0x2a, 1221 0xeb, 0x00, 0x67, 0x7a, 0xd6, 0x46, 0x27, 0x78, 1222 0xa8, 0xf5, 0x22, 0x74, 0xb9, 0xd6, 0x05, 0xdf, 1223 0x25, 0x91, 0xb2, 0x30, 0x27, 0xa8, 0x7d, 0xff, 1224 // secp256k1fx transfer input type ID 1225 0x00, 0x00, 0x00, 0x05, 1226 // amount 1227 0x00, 0x03, 0x8d, 0x7e, 0xa4, 0xc6, 0x80, 0x00, 1228 // number of signature indices 1229 0x00, 0x00, 0x00, 0x02, 1230 // first signature index 1231 0x00, 0x00, 0x00, 0x02, 1232 // second signature index 1233 0x00, 0x00, 0x00, 0x05, 1234 // inputs[1] 1235 // TxID 1236 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 1237 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 1238 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 1239 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 1240 // Tx output index 1241 0x00, 0x00, 0x00, 0x02, 1242 // custom asset ID 1243 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 1244 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 1245 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 1246 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 1247 // stakeable locked input type ID 1248 0x00, 0x00, 0x00, 0x15, 1249 // locktime 1250 0x00, 0x00, 0x00, 0x00, 0x34, 0x3e, 0xfc, 0xea, 1251 // secp256k1fx transfer input type ID 1252 0x00, 0x00, 0x00, 0x05, 1253 // amount 1254 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 1255 // number of signature indices 1256 0x00, 0x00, 0x00, 0x01, 1257 // signature index 1258 0x00, 0x00, 0x00, 0x00, 1259 // inputs[2] 1260 // TxID 1261 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 1262 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 1263 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 1264 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 1265 // Tx output index 1266 0x00, 0x00, 0x00, 0x03, 1267 // custom asset ID 1268 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 1269 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 1270 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 1271 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 1272 // secp256k1 transfer input type ID 1273 0x00, 0x00, 0x00, 0x05, 1274 // amount 1275 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1276 // number of signature indices 1277 0x00, 0x00, 0x00, 0x00, 1278 // memo length 1279 0x00, 0x00, 0x00, 0x14, 1280 // memo 1281 0xf0, 0x9f, 0x98, 0x85, 0x0a, 0x77, 0x65, 0x6c, 1282 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x27, 0x73, 1283 0x01, 0x23, 0x45, 0x21, 1284 // nodeID 1285 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 1286 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 1287 0x11, 0x22, 0x33, 0x44, 1288 // Start time 1289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39, 1290 // End time 1291 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3a, 1292 // Stake weight 1293 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 1294 // subnetID 1295 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 1296 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 1297 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 1298 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 1299 // Empty signer type ID 1300 0x00, 0x00, 0x00, 0x1b, 1301 // number of locked outputs 1302 0x00, 0x00, 0x00, 0x02, 1303 // custom asset ID 1304 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 1305 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 1306 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 1307 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 1308 // secp256k1 transfer output type ID 1309 0x00, 0x00, 0x00, 0x07, 1310 // amount 1311 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 1312 // locktime 1313 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1314 // threshold 1315 0x00, 0x00, 0x00, 0x01, 1316 // number of addresses 1317 0x00, 0x00, 0x00, 0x01, 1318 // addresses[0] 1319 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 1320 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 1321 0x44, 0x55, 0x66, 0x77, 1322 // custom asset ID 1323 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 1324 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 1325 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 1326 0x99, 0x77, 0x55, 0x77, 0x11, 0x33, 0x55, 0x31, 1327 // stakeable locked output type ID 1328 0x00, 0x00, 0x00, 0x16, 1329 // locktime 1330 0x00, 0x00, 0x00, 0x00, 0x3a, 0xde, 0x68, 0xb1, 1331 // secp256k1 transfer output type ID 1332 0x00, 0x00, 0x00, 0x07, 1333 // amount 1334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 1335 // locktime 1336 0x00, 0x00, 0x00, 0x00, 0x05, 0x39, 0x7f, 0xb1, 1337 // threshold 1338 0x00, 0x00, 0x00, 0x00, 1339 // number of addresses 1340 0x00, 0x00, 0x00, 0x00, 1341 // secp256k1 owner type ID 1342 0x00, 0x00, 0x00, 0x0b, 1343 // locktime 1344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1345 // threshold 1346 0x00, 0x00, 0x00, 0x01, 1347 // number of addresses 1348 0x00, 0x00, 0x00, 0x01, 1349 // addresses[0] 1350 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 1351 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 1352 0x44, 0x55, 0x66, 0x77, 1353 // secp256k1 owner type ID 1354 0x00, 0x00, 0x00, 0x0b, 1355 // locktime 1356 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1357 // threshold 1358 0x00, 0x00, 0x00, 0x00, 1359 // number of addresses 1360 0x00, 0x00, 0x00, 0x00, 1361 // delegation shares 1362 0x00, 0x0f, 0x42, 0x40, 1363 } 1364 var unsignedComplexAddSubnetTx UnsignedTx = complexAddSubnetTx 1365 unsignedComplexAddSubnetTxBytes, err := Codec.Marshal(CodecVersion, &unsignedComplexAddSubnetTx) 1366 require.NoError(err) 1367 require.Equal(expectedUnsignedComplexAddSubnetTxBytes, unsignedComplexAddSubnetTxBytes) 1368 } 1369 1370 func TestAddPermissionlessValidatorTxSyntacticVerify(t *testing.T) { 1371 type test struct { 1372 name string 1373 txFunc func(*gomock.Controller) *AddPermissionlessValidatorTx 1374 err error 1375 } 1376 1377 var ( 1378 networkID = uint32(1337) 1379 chainID = ids.GenerateTestID() 1380 ) 1381 1382 ctx := &snow.Context{ 1383 ChainID: chainID, 1384 NetworkID: networkID, 1385 } 1386 1387 // A BaseTx that already passed syntactic verification. 1388 verifiedBaseTx := BaseTx{ 1389 SyntacticallyVerified: true, 1390 } 1391 1392 // A BaseTx that passes syntactic verification. 1393 validBaseTx := BaseTx{ 1394 BaseTx: avax.BaseTx{ 1395 NetworkID: networkID, 1396 BlockchainID: chainID, 1397 }, 1398 } 1399 1400 blsSK, err := bls.NewSecretKey() 1401 require.NoError(t, err) 1402 1403 blsPOP := signer.NewProofOfPossession(blsSK) 1404 1405 // A BaseTx that fails syntactic verification. 1406 invalidBaseTx := BaseTx{} 1407 1408 tests := []test{ 1409 { 1410 name: "nil tx", 1411 txFunc: func(*gomock.Controller) *AddPermissionlessValidatorTx { 1412 return nil 1413 }, 1414 err: ErrNilTx, 1415 }, 1416 { 1417 name: "already verified", 1418 txFunc: func(*gomock.Controller) *AddPermissionlessValidatorTx { 1419 return &AddPermissionlessValidatorTx{ 1420 BaseTx: verifiedBaseTx, 1421 } 1422 }, 1423 err: nil, 1424 }, 1425 { 1426 name: "empty nodeID", 1427 txFunc: func(*gomock.Controller) *AddPermissionlessValidatorTx { 1428 return &AddPermissionlessValidatorTx{ 1429 BaseTx: validBaseTx, 1430 Validator: Validator{ 1431 NodeID: ids.EmptyNodeID, 1432 }, 1433 } 1434 }, 1435 err: errEmptyNodeID, 1436 }, 1437 { 1438 name: "no provided stake", 1439 txFunc: func(*gomock.Controller) *AddPermissionlessValidatorTx { 1440 return &AddPermissionlessValidatorTx{ 1441 BaseTx: validBaseTx, 1442 Validator: Validator{ 1443 NodeID: ids.GenerateTestNodeID(), 1444 }, 1445 StakeOuts: nil, 1446 } 1447 }, 1448 err: errNoStake, 1449 }, 1450 { 1451 name: "too many shares", 1452 txFunc: func(*gomock.Controller) *AddPermissionlessValidatorTx { 1453 return &AddPermissionlessValidatorTx{ 1454 BaseTx: validBaseTx, 1455 Validator: Validator{ 1456 NodeID: ids.GenerateTestNodeID(), 1457 }, 1458 StakeOuts: []*avax.TransferableOutput{ 1459 { 1460 Asset: avax.Asset{ 1461 ID: ids.GenerateTestID(), 1462 }, 1463 Out: &secp256k1fx.TransferOutput{ 1464 Amt: 1, 1465 }, 1466 }, 1467 }, 1468 DelegationShares: reward.PercentDenominator + 1, 1469 } 1470 }, 1471 err: errTooManyShares, 1472 }, 1473 { 1474 name: "invalid BaseTx", 1475 txFunc: func(*gomock.Controller) *AddPermissionlessValidatorTx { 1476 return &AddPermissionlessValidatorTx{ 1477 BaseTx: invalidBaseTx, 1478 Validator: Validator{ 1479 NodeID: ids.GenerateTestNodeID(), 1480 }, 1481 StakeOuts: []*avax.TransferableOutput{ 1482 { 1483 Asset: avax.Asset{ 1484 ID: ids.GenerateTestID(), 1485 }, 1486 Out: &secp256k1fx.TransferOutput{ 1487 Amt: 1, 1488 }, 1489 }, 1490 }, 1491 DelegationShares: reward.PercentDenominator, 1492 } 1493 }, 1494 err: avax.ErrWrongNetworkID, 1495 }, 1496 { 1497 name: "invalid rewards owner", 1498 txFunc: func(ctrl *gomock.Controller) *AddPermissionlessValidatorTx { 1499 rewardsOwner := fxmock.NewOwner(ctrl) 1500 rewardsOwner.EXPECT().Verify().Return(errCustom) 1501 return &AddPermissionlessValidatorTx{ 1502 BaseTx: validBaseTx, 1503 Validator: Validator{ 1504 NodeID: ids.GenerateTestNodeID(), 1505 Wght: 1, 1506 }, 1507 Subnet: ids.GenerateTestID(), 1508 Signer: &signer.Empty{}, 1509 StakeOuts: []*avax.TransferableOutput{ 1510 { 1511 Asset: avax.Asset{ 1512 ID: ids.GenerateTestID(), 1513 }, 1514 Out: &secp256k1fx.TransferOutput{ 1515 Amt: 1, 1516 }, 1517 }, 1518 }, 1519 ValidatorRewardsOwner: rewardsOwner, 1520 DelegatorRewardsOwner: rewardsOwner, 1521 DelegationShares: reward.PercentDenominator, 1522 } 1523 }, 1524 err: errCustom, 1525 }, 1526 { 1527 name: "wrong signer", 1528 txFunc: func(ctrl *gomock.Controller) *AddPermissionlessValidatorTx { 1529 rewardsOwner := fxmock.NewOwner(ctrl) 1530 rewardsOwner.EXPECT().Verify().Return(nil).AnyTimes() 1531 return &AddPermissionlessValidatorTx{ 1532 BaseTx: validBaseTx, 1533 Validator: Validator{ 1534 NodeID: ids.GenerateTestNodeID(), 1535 Wght: 1, 1536 }, 1537 Subnet: constants.PrimaryNetworkID, 1538 Signer: &signer.Empty{}, 1539 StakeOuts: []*avax.TransferableOutput{ 1540 { 1541 Asset: avax.Asset{ 1542 ID: ids.GenerateTestID(), 1543 }, 1544 Out: &secp256k1fx.TransferOutput{ 1545 Amt: 1, 1546 }, 1547 }, 1548 }, 1549 ValidatorRewardsOwner: rewardsOwner, 1550 DelegatorRewardsOwner: rewardsOwner, 1551 DelegationShares: reward.PercentDenominator, 1552 } 1553 }, 1554 err: errInvalidSigner, 1555 }, 1556 { 1557 name: "invalid stake output", 1558 txFunc: func(ctrl *gomock.Controller) *AddPermissionlessValidatorTx { 1559 rewardsOwner := fxmock.NewOwner(ctrl) 1560 rewardsOwner.EXPECT().Verify().Return(nil).AnyTimes() 1561 1562 stakeOut := avaxmock.NewTransferableOut(ctrl) 1563 stakeOut.EXPECT().Verify().Return(errCustom) 1564 return &AddPermissionlessValidatorTx{ 1565 BaseTx: validBaseTx, 1566 Validator: Validator{ 1567 NodeID: ids.GenerateTestNodeID(), 1568 Wght: 1, 1569 }, 1570 Subnet: ids.GenerateTestID(), 1571 Signer: &signer.Empty{}, 1572 StakeOuts: []*avax.TransferableOutput{ 1573 { 1574 Asset: avax.Asset{ 1575 ID: ids.GenerateTestID(), 1576 }, 1577 Out: stakeOut, 1578 }, 1579 }, 1580 ValidatorRewardsOwner: rewardsOwner, 1581 DelegatorRewardsOwner: rewardsOwner, 1582 DelegationShares: reward.PercentDenominator, 1583 } 1584 }, 1585 err: errCustom, 1586 }, 1587 { 1588 name: "stake overflow", 1589 txFunc: func(ctrl *gomock.Controller) *AddPermissionlessValidatorTx { 1590 rewardsOwner := fxmock.NewOwner(ctrl) 1591 rewardsOwner.EXPECT().Verify().Return(nil).AnyTimes() 1592 assetID := ids.GenerateTestID() 1593 return &AddPermissionlessValidatorTx{ 1594 BaseTx: validBaseTx, 1595 Validator: Validator{ 1596 NodeID: ids.GenerateTestNodeID(), 1597 Wght: 1, 1598 }, 1599 Subnet: ids.GenerateTestID(), 1600 Signer: &signer.Empty{}, 1601 StakeOuts: []*avax.TransferableOutput{ 1602 { 1603 Asset: avax.Asset{ 1604 ID: assetID, 1605 }, 1606 Out: &secp256k1fx.TransferOutput{ 1607 Amt: math.MaxUint64, 1608 }, 1609 }, 1610 { 1611 Asset: avax.Asset{ 1612 ID: assetID, 1613 }, 1614 Out: &secp256k1fx.TransferOutput{ 1615 Amt: 2, 1616 }, 1617 }, 1618 }, 1619 ValidatorRewardsOwner: rewardsOwner, 1620 DelegatorRewardsOwner: rewardsOwner, 1621 DelegationShares: reward.PercentDenominator, 1622 } 1623 }, 1624 err: safemath.ErrOverflow, 1625 }, 1626 { 1627 name: "multiple staked assets", 1628 txFunc: func(ctrl *gomock.Controller) *AddPermissionlessValidatorTx { 1629 rewardsOwner := fxmock.NewOwner(ctrl) 1630 rewardsOwner.EXPECT().Verify().Return(nil).AnyTimes() 1631 return &AddPermissionlessValidatorTx{ 1632 BaseTx: validBaseTx, 1633 Validator: Validator{ 1634 NodeID: ids.GenerateTestNodeID(), 1635 Wght: 1, 1636 }, 1637 Subnet: ids.GenerateTestID(), 1638 Signer: &signer.Empty{}, 1639 StakeOuts: []*avax.TransferableOutput{ 1640 { 1641 Asset: avax.Asset{ 1642 ID: ids.GenerateTestID(), 1643 }, 1644 Out: &secp256k1fx.TransferOutput{ 1645 Amt: 1, 1646 }, 1647 }, 1648 { 1649 Asset: avax.Asset{ 1650 ID: ids.GenerateTestID(), 1651 }, 1652 Out: &secp256k1fx.TransferOutput{ 1653 Amt: 1, 1654 }, 1655 }, 1656 }, 1657 ValidatorRewardsOwner: rewardsOwner, 1658 DelegatorRewardsOwner: rewardsOwner, 1659 DelegationShares: reward.PercentDenominator, 1660 } 1661 }, 1662 err: errMultipleStakedAssets, 1663 }, 1664 { 1665 name: "stake not sorted", 1666 txFunc: func(ctrl *gomock.Controller) *AddPermissionlessValidatorTx { 1667 rewardsOwner := fxmock.NewOwner(ctrl) 1668 rewardsOwner.EXPECT().Verify().Return(nil).AnyTimes() 1669 assetID := ids.GenerateTestID() 1670 return &AddPermissionlessValidatorTx{ 1671 BaseTx: validBaseTx, 1672 Validator: Validator{ 1673 NodeID: ids.GenerateTestNodeID(), 1674 Wght: 1, 1675 }, 1676 Subnet: ids.GenerateTestID(), 1677 Signer: &signer.Empty{}, 1678 StakeOuts: []*avax.TransferableOutput{ 1679 { 1680 Asset: avax.Asset{ 1681 ID: assetID, 1682 }, 1683 Out: &secp256k1fx.TransferOutput{ 1684 Amt: 2, 1685 }, 1686 }, 1687 { 1688 Asset: avax.Asset{ 1689 ID: assetID, 1690 }, 1691 Out: &secp256k1fx.TransferOutput{ 1692 Amt: 1, 1693 }, 1694 }, 1695 }, 1696 ValidatorRewardsOwner: rewardsOwner, 1697 DelegatorRewardsOwner: rewardsOwner, 1698 DelegationShares: reward.PercentDenominator, 1699 } 1700 }, 1701 err: errOutputsNotSorted, 1702 }, 1703 { 1704 name: "weight mismatch", 1705 txFunc: func(ctrl *gomock.Controller) *AddPermissionlessValidatorTx { 1706 rewardsOwner := fxmock.NewOwner(ctrl) 1707 rewardsOwner.EXPECT().Verify().Return(nil).AnyTimes() 1708 assetID := ids.GenerateTestID() 1709 return &AddPermissionlessValidatorTx{ 1710 BaseTx: validBaseTx, 1711 Validator: Validator{ 1712 NodeID: ids.GenerateTestNodeID(), 1713 Wght: 1, 1714 }, 1715 Subnet: ids.GenerateTestID(), 1716 Signer: &signer.Empty{}, 1717 StakeOuts: []*avax.TransferableOutput{ 1718 { 1719 Asset: avax.Asset{ 1720 ID: assetID, 1721 }, 1722 Out: &secp256k1fx.TransferOutput{ 1723 Amt: 1, 1724 }, 1725 }, 1726 { 1727 Asset: avax.Asset{ 1728 ID: assetID, 1729 }, 1730 Out: &secp256k1fx.TransferOutput{ 1731 Amt: 1, 1732 }, 1733 }, 1734 }, 1735 ValidatorRewardsOwner: rewardsOwner, 1736 DelegatorRewardsOwner: rewardsOwner, 1737 DelegationShares: reward.PercentDenominator, 1738 } 1739 }, 1740 err: errValidatorWeightMismatch, 1741 }, 1742 { 1743 name: "valid subnet validator", 1744 txFunc: func(ctrl *gomock.Controller) *AddPermissionlessValidatorTx { 1745 rewardsOwner := fxmock.NewOwner(ctrl) 1746 rewardsOwner.EXPECT().Verify().Return(nil).AnyTimes() 1747 assetID := ids.GenerateTestID() 1748 return &AddPermissionlessValidatorTx{ 1749 BaseTx: validBaseTx, 1750 Validator: Validator{ 1751 NodeID: ids.GenerateTestNodeID(), 1752 Wght: 2, 1753 }, 1754 Subnet: ids.GenerateTestID(), 1755 Signer: &signer.Empty{}, 1756 StakeOuts: []*avax.TransferableOutput{ 1757 { 1758 Asset: avax.Asset{ 1759 ID: assetID, 1760 }, 1761 Out: &secp256k1fx.TransferOutput{ 1762 Amt: 1, 1763 }, 1764 }, 1765 { 1766 Asset: avax.Asset{ 1767 ID: assetID, 1768 }, 1769 Out: &secp256k1fx.TransferOutput{ 1770 Amt: 1, 1771 }, 1772 }, 1773 }, 1774 ValidatorRewardsOwner: rewardsOwner, 1775 DelegatorRewardsOwner: rewardsOwner, 1776 DelegationShares: reward.PercentDenominator, 1777 } 1778 }, 1779 err: nil, 1780 }, 1781 { 1782 name: "valid primary network validator", 1783 txFunc: func(ctrl *gomock.Controller) *AddPermissionlessValidatorTx { 1784 rewardsOwner := fxmock.NewOwner(ctrl) 1785 rewardsOwner.EXPECT().Verify().Return(nil).AnyTimes() 1786 assetID := ids.GenerateTestID() 1787 return &AddPermissionlessValidatorTx{ 1788 BaseTx: validBaseTx, 1789 Validator: Validator{ 1790 NodeID: ids.GenerateTestNodeID(), 1791 Wght: 2, 1792 }, 1793 Subnet: constants.PrimaryNetworkID, 1794 Signer: blsPOP, 1795 StakeOuts: []*avax.TransferableOutput{ 1796 { 1797 Asset: avax.Asset{ 1798 ID: assetID, 1799 }, 1800 Out: &secp256k1fx.TransferOutput{ 1801 Amt: 1, 1802 }, 1803 }, 1804 { 1805 Asset: avax.Asset{ 1806 ID: assetID, 1807 }, 1808 Out: &secp256k1fx.TransferOutput{ 1809 Amt: 1, 1810 }, 1811 }, 1812 }, 1813 ValidatorRewardsOwner: rewardsOwner, 1814 DelegatorRewardsOwner: rewardsOwner, 1815 DelegationShares: reward.PercentDenominator, 1816 } 1817 }, 1818 err: nil, 1819 }, 1820 } 1821 1822 for _, tt := range tests { 1823 t.Run(tt.name, func(t *testing.T) { 1824 ctrl := gomock.NewController(t) 1825 1826 tx := tt.txFunc(ctrl) 1827 err := tx.SyntacticVerify(ctx) 1828 require.ErrorIs(t, err, tt.err) 1829 }) 1830 } 1831 } 1832 1833 func TestAddPermissionlessValidatorTxNotDelegatorTx(t *testing.T) { 1834 txIntf := any((*AddPermissionlessValidatorTx)(nil)) 1835 _, ok := txIntf.(DelegatorTx) 1836 require.False(t, ok) 1837 }