github.com/ava-labs/avalanchego@v1.11.11/vms/platformvm/txs/add_permissionless_validator_tx_test.go (about)

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