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