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  }