gitlab.com/flarenetwork/coreth@v0.1.1/plugin/evm/vm_test.go (about)

     1  // (c) 2019-2020, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package evm
     5  
     6  import (
     7  	"context"
     8  	"crypto/rand"
     9  	"encoding/json"
    10  	"errors"
    11  	"fmt"
    12  	"math/big"
    13  	"os"
    14  	"path/filepath"
    15  	"strings"
    16  	"testing"
    17  	"time"
    18  
    19  	"github.com/ethereum/go-ethereum/common"
    20  	"github.com/ethereum/go-ethereum/log"
    21  	"github.com/ethereum/go-ethereum/trie"
    22  
    23  	"github.com/stretchr/testify/assert"
    24  
    25  	"github.com/ava-labs/avalanchego/api/keystore"
    26  	"github.com/ava-labs/avalanchego/chains/atomic"
    27  	"github.com/ava-labs/avalanchego/database/manager"
    28  	"github.com/ava-labs/avalanchego/database/prefixdb"
    29  	"github.com/ava-labs/avalanchego/ids"
    30  	"github.com/ava-labs/avalanchego/snow"
    31  	"github.com/ava-labs/avalanchego/snow/choices"
    32  	"github.com/ava-labs/avalanchego/utils/crypto"
    33  	"github.com/ava-labs/avalanchego/utils/formatting"
    34  	"github.com/ava-labs/avalanchego/utils/logging"
    35  	"github.com/ava-labs/avalanchego/utils/units"
    36  	"github.com/ava-labs/avalanchego/version"
    37  	"github.com/ava-labs/avalanchego/vms/components/avax"
    38  	"github.com/ava-labs/avalanchego/vms/components/chain"
    39  	"github.com/ava-labs/avalanchego/vms/secp256k1fx"
    40  
    41  	engCommon "github.com/ava-labs/avalanchego/snow/engine/common"
    42  
    43  	"gitlab.com/flarenetwork/coreth/core"
    44  	"gitlab.com/flarenetwork/coreth/core/types"
    45  	"gitlab.com/flarenetwork/coreth/eth"
    46  	"gitlab.com/flarenetwork/coreth/params"
    47  	"gitlab.com/flarenetwork/coreth/rpc"
    48  
    49  	accountKeystore "gitlab.com/flarenetwork/coreth/accounts/keystore"
    50  )
    51  
    52  var (
    53  	testNetworkID    uint32 = 10
    54  	testCChainID            = ids.ID{'c', 'c', 'h', 'a', 'i', 'n', 't', 'e', 's', 't'}
    55  	testXChainID            = ids.ID{'t', 'e', 's', 't', 'x'}
    56  	nonExistentID           = ids.ID{'F'}
    57  	testKeys         []*crypto.PrivateKeySECP256K1R
    58  	testEthAddrs     []common.Address // testEthAddrs[i] corresponds to testKeys[i]
    59  	testShortIDAddrs []ids.ShortID
    60  	testAvaxAssetID  = ids.ID{1, 2, 3}
    61  	username         = "Johns"
    62  	password         = "CjasdjhiPeirbSenfeI13" // #nosec G101
    63  	// Use chainId: 43111, so that it does not overlap with any Avalanche ChainIDs, which may have their
    64  	// config overridden in vm.Initialize.
    65  	genesisJSONApricotPhase0 = "{\"config\":{\"chainId\":43111,\"homesteadBlock\":0,\"daoForkBlock\":0,\"daoForkSupport\":true,\"eip150Block\":0,\"eip150Hash\":\"0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0\",\"eip155Block\":0,\"eip158Block\":0,\"byzantiumBlock\":0,\"constantinopleBlock\":0,\"petersburgBlock\":0,\"istanbulBlock\":0,\"muirGlacierBlock\":0},\"nonce\":\"0x0\",\"timestamp\":\"0x0\",\"extraData\":\"0x00\",\"gasLimit\":\"0x5f5e100\",\"difficulty\":\"0x0\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"coinbase\":\"0x0000000000000000000000000000000000000000\",\"alloc\":{\"0100000000000000000000000000000000000000\":{\"code\":\"0x7300000000000000000000000000000000000000003014608060405260043610603d5760003560e01c80631e010439146042578063b6510bb314606e575b600080fd5b605c60048036036020811015605657600080fd5b503560b1565b60408051918252519081900360200190f35b818015607957600080fd5b5060af60048036036080811015608e57600080fd5b506001600160a01b03813516906020810135906040810135906060013560b6565b005b30cd90565b836001600160a01b031681836108fc8690811502906040516000604051808303818888878c8acf9550505050505015801560f4573d6000803e3d6000fd5b505050505056fea26469706673582212201eebce970fe3f5cb96bf8ac6ba5f5c133fc2908ae3dcd51082cfee8f583429d064736f6c634300060a0033\",\"balance\":\"0x0\"}},\"number\":\"0x0\",\"gasUsed\":\"0x0\",\"parentHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\"}"
    66  	genesisJSONApricotPhase1 = "{\"config\":{\"chainId\":43111,\"homesteadBlock\":0,\"daoForkBlock\":0,\"daoForkSupport\":true,\"eip150Block\":0,\"eip150Hash\":\"0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0\",\"eip155Block\":0,\"eip158Block\":0,\"byzantiumBlock\":0,\"constantinopleBlock\":0,\"petersburgBlock\":0,\"istanbulBlock\":0,\"muirGlacierBlock\":0,\"apricotPhase1BlockTimestamp\":0},\"nonce\":\"0x0\",\"timestamp\":\"0x0\",\"extraData\":\"0x00\",\"gasLimit\":\"0x5f5e100\",\"difficulty\":\"0x0\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"coinbase\":\"0x0000000000000000000000000000000000000000\",\"alloc\":{\"0100000000000000000000000000000000000000\":{\"code\":\"0x7300000000000000000000000000000000000000003014608060405260043610603d5760003560e01c80631e010439146042578063b6510bb314606e575b600080fd5b605c60048036036020811015605657600080fd5b503560b1565b60408051918252519081900360200190f35b818015607957600080fd5b5060af60048036036080811015608e57600080fd5b506001600160a01b03813516906020810135906040810135906060013560b6565b005b30cd90565b836001600160a01b031681836108fc8690811502906040516000604051808303818888878c8acf9550505050505015801560f4573d6000803e3d6000fd5b505050505056fea26469706673582212201eebce970fe3f5cb96bf8ac6ba5f5c133fc2908ae3dcd51082cfee8f583429d064736f6c634300060a0033\",\"balance\":\"0x0\"}},\"number\":\"0x0\",\"gasUsed\":\"0x0\",\"parentHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\"}"
    67  	genesisJSONApricotPhase2 = "{\"config\":{\"chainId\":43111,\"homesteadBlock\":0,\"daoForkBlock\":0,\"daoForkSupport\":true,\"eip150Block\":0,\"eip150Hash\":\"0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0\",\"eip155Block\":0,\"eip158Block\":0,\"byzantiumBlock\":0,\"constantinopleBlock\":0,\"petersburgBlock\":0,\"istanbulBlock\":0,\"muirGlacierBlock\":0,\"apricotPhase1BlockTimestamp\":0,\"apricotPhase2BlockTimestamp\":0},\"nonce\":\"0x0\",\"timestamp\":\"0x0\",\"extraData\":\"0x00\",\"gasLimit\":\"0x5f5e100\",\"difficulty\":\"0x0\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"coinbase\":\"0x0000000000000000000000000000000000000000\",\"alloc\":{\"0100000000000000000000000000000000000000\":{\"code\":\"0x7300000000000000000000000000000000000000003014608060405260043610603d5760003560e01c80631e010439146042578063b6510bb314606e575b600080fd5b605c60048036036020811015605657600080fd5b503560b1565b60408051918252519081900360200190f35b818015607957600080fd5b5060af60048036036080811015608e57600080fd5b506001600160a01b03813516906020810135906040810135906060013560b6565b005b30cd90565b836001600160a01b031681836108fc8690811502906040516000604051808303818888878c8acf9550505050505015801560f4573d6000803e3d6000fd5b505050505056fea26469706673582212201eebce970fe3f5cb96bf8ac6ba5f5c133fc2908ae3dcd51082cfee8f583429d064736f6c634300060a0033\",\"balance\":\"0x0\"}},\"number\":\"0x0\",\"gasUsed\":\"0x0\",\"parentHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\"}"
    68  	genesisJSONApricotPhase3 = "{\"config\":{\"chainId\":43111,\"homesteadBlock\":0,\"daoForkBlock\":0,\"daoForkSupport\":true,\"eip150Block\":0,\"eip150Hash\":\"0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0\",\"eip155Block\":0,\"eip158Block\":0,\"byzantiumBlock\":0,\"constantinopleBlock\":0,\"petersburgBlock\":0,\"istanbulBlock\":0,\"muirGlacierBlock\":0,\"apricotPhase1BlockTimestamp\":0,\"apricotPhase2BlockTimestamp\":0,\"apricotPhase3BlockTimestamp\":0},\"nonce\":\"0x0\",\"timestamp\":\"0x0\",\"extraData\":\"0x00\",\"gasLimit\":\"0x5f5e100\",\"difficulty\":\"0x0\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"coinbase\":\"0x0000000000000000000000000000000000000000\",\"alloc\":{\"0100000000000000000000000000000000000000\":{\"code\":\"0x7300000000000000000000000000000000000000003014608060405260043610603d5760003560e01c80631e010439146042578063b6510bb314606e575b600080fd5b605c60048036036020811015605657600080fd5b503560b1565b60408051918252519081900360200190f35b818015607957600080fd5b5060af60048036036080811015608e57600080fd5b506001600160a01b03813516906020810135906040810135906060013560b6565b005b30cd90565b836001600160a01b031681836108fc8690811502906040516000604051808303818888878c8acf9550505050505015801560f4573d6000803e3d6000fd5b505050505056fea26469706673582212201eebce970fe3f5cb96bf8ac6ba5f5c133fc2908ae3dcd51082cfee8f583429d064736f6c634300060a0033\",\"balance\":\"0x0\"}},\"number\":\"0x0\",\"gasUsed\":\"0x0\",\"parentHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\"}"
    69  
    70  	apricotRulesPhase0 = params.Rules{}
    71  	apricotRulesPhase1 = params.Rules{IsApricotPhase1: true}
    72  	apricotRulesPhase2 = params.Rules{IsApricotPhase1: true, IsApricotPhase2: true}
    73  	apricotRulesPhase3 = params.Rules{IsApricotPhase1: true, IsApricotPhase2: true, IsApricotPhase3: true}
    74  )
    75  
    76  func init() {
    77  	var b []byte
    78  	factory := crypto.FactorySECP256K1R{}
    79  
    80  	for _, key := range []string{
    81  		"24jUJ9vZexUM6expyMcT48LBx27k1m7xpraoV62oSQAHdziao5",
    82  		"2MMvUMsxx6zsHSNXJdFD8yc5XkancvwyKPwpw4xUK3TCGDuNBY",
    83  		"cxb7KpGWhDMALTjNNSJ7UQkkomPesyWAPUaWRGdyeBNzR6f35",
    84  	} {
    85  		b, _ = formatting.Decode(formatting.CB58, key)
    86  		pk, _ := factory.ToPrivateKey(b)
    87  		secpKey := pk.(*crypto.PrivateKeySECP256K1R)
    88  		testKeys = append(testKeys, secpKey)
    89  		testEthAddrs = append(testEthAddrs, GetEthAddress(secpKey))
    90  		testShortIDAddrs = append(testShortIDAddrs, pk.PublicKey().Address())
    91  	}
    92  }
    93  
    94  // BuildGenesisTest returns the genesis bytes for Coreth VM to be used in testing
    95  func BuildGenesisTest(t *testing.T, genesisJSON string) []byte {
    96  	ss := StaticService{}
    97  
    98  	genesis := &core.Genesis{}
    99  	if err := json.Unmarshal([]byte(genesisJSON), genesis); err != nil {
   100  		t.Fatalf("Problem unmarshaling genesis JSON: %s", err)
   101  	}
   102  	genesisReply, err := ss.BuildGenesis(nil, genesis)
   103  	if err != nil {
   104  		t.Fatalf("Failed to create test genesis")
   105  	}
   106  	genesisBytes, err := formatting.Decode(genesisReply.Encoding, genesisReply.Bytes)
   107  	if err != nil {
   108  		t.Fatalf("Failed to decode genesis bytes: %s", err)
   109  	}
   110  	return genesisBytes
   111  }
   112  
   113  func NewContext() *snow.Context {
   114  	ctx := snow.DefaultContextTest()
   115  	ctx.NetworkID = testNetworkID
   116  	ctx.ChainID = testCChainID
   117  	ctx.AVAXAssetID = testAvaxAssetID
   118  	ctx.XChainID = ids.Empty.Prefix(0)
   119  	aliaser := ctx.BCLookup.(*ids.Aliaser)
   120  	_ = aliaser.Alias(testCChainID, "C")
   121  	_ = aliaser.Alias(testCChainID, testCChainID.String())
   122  	_ = aliaser.Alias(testXChainID, "X")
   123  	_ = aliaser.Alias(testXChainID, testXChainID.String())
   124  
   125  	// SNLookup might be required here???
   126  	return ctx
   127  }
   128  
   129  func setupGenesis(t *testing.T, genesisJSON string) (*VM, *snow.Context, manager.Manager, []byte, chan engCommon.Message, *atomic.Memory) {
   130  	genesisBytes := BuildGenesisTest(t, genesisJSON)
   131  	ctx := NewContext()
   132  
   133  	baseDBManager := manager.NewMemDB(version.NewDefaultVersion(1, 4, 5))
   134  
   135  	m := &atomic.Memory{}
   136  	m.Initialize(logging.NoLog{}, prefixdb.New([]byte{0}, baseDBManager.Current().Database))
   137  	ctx.SharedMemory = m.NewSharedMemory(ctx.ChainID)
   138  
   139  	// NB: this lock is intentionally left locked when this function returns.
   140  	// The caller of this function is responsible for unlocking.
   141  	ctx.Lock.Lock()
   142  
   143  	userKeystore := keystore.New(logging.NoLog{}, manager.NewMemDB(version.NewDefaultVersion(1, 4, 5)))
   144  	if err := userKeystore.CreateUser(username, password); err != nil {
   145  		t.Fatal(err)
   146  	}
   147  	ctx.Keystore = userKeystore.NewBlockchainKeyStore(ctx.ChainID)
   148  
   149  	issuer := make(chan engCommon.Message, 1)
   150  	vm := &VM{}
   151  	prefixedDBManager := baseDBManager.NewPrefixDBManager([]byte{1})
   152  	return vm, ctx, prefixedDBManager, genesisBytes, issuer, m
   153  }
   154  
   155  // GenesisVM creates a VM instance with the genesis test bytes and returns
   156  // the channel use to send messages to the engine, the vm, and atomic memory
   157  func GenesisVM(t *testing.T, finishBootstrapping bool, genesisJSON string, configJSON string, upgradeJSON string) (chan engCommon.Message, *VM, manager.Manager, *atomic.Memory) {
   158  	vm, ctx, dbManager, genesisBytes, issuer, m := setupGenesis(t, genesisJSON)
   159  	if err := vm.Initialize(
   160  		ctx,
   161  		dbManager,
   162  		genesisBytes,
   163  		[]byte(upgradeJSON),
   164  		[]byte(configJSON),
   165  		issuer,
   166  		[]*engCommon.Fx{},
   167  	); err != nil {
   168  		t.Fatal(err)
   169  	}
   170  
   171  	if finishBootstrapping {
   172  		assert.NoError(t, vm.Bootstrapping())
   173  		assert.NoError(t, vm.Bootstrapped())
   174  	}
   175  
   176  	return issuer, vm, dbManager, m
   177  }
   178  
   179  func TestVMConfig(t *testing.T) {
   180  	txFeeCap := float64(11)
   181  	netApiEnabled := true
   182  	configJSON := fmt.Sprintf("{\"rpc-tx-fee-cap\": %g,\"net-api-enabled\": %t}", txFeeCap, netApiEnabled)
   183  	_, vm, _, _ := GenesisVM(t, false, genesisJSONApricotPhase0, configJSON, "")
   184  	assert.Equal(t, vm.config.RPCTxFeeCap, txFeeCap, "Tx Fee Cap should be set")
   185  	assert.Equal(t, vm.config.NetAPIEnabled, netApiEnabled, "Net API Enabled should be set")
   186  	assert.NoError(t, vm.Shutdown())
   187  }
   188  
   189  func TestVMConfigDefaults(t *testing.T) {
   190  	txFeeCap := float64(11)
   191  	netApiEnabled := true
   192  	configJSON := fmt.Sprintf("{\"rpc-tx-fee-cap\": %g,\"net-api-enabled\": %t}", txFeeCap, netApiEnabled)
   193  	_, vm, _, _ := GenesisVM(t, false, genesisJSONApricotPhase0, configJSON, "")
   194  
   195  	var vmConfig Config
   196  	vmConfig.SetDefaults()
   197  	vmConfig.RPCTxFeeCap = txFeeCap
   198  	vmConfig.NetAPIEnabled = netApiEnabled
   199  	assert.Equal(t, vmConfig, vm.config, "VM Config should match default with overrides")
   200  	assert.NoError(t, vm.Shutdown())
   201  }
   202  
   203  func TestVMNilConfig(t *testing.T) {
   204  	_, vm, _, _ := GenesisVM(t, false, genesisJSONApricotPhase0, "", "")
   205  
   206  	// VM Config should match defaults if no config is passed in
   207  	var vmConfig Config
   208  	vmConfig.SetDefaults()
   209  	assert.Equal(t, vmConfig, vm.config, "VM Config should match default config")
   210  	assert.NoError(t, vm.Shutdown())
   211  }
   212  
   213  func TestVMContinuosProfiler(t *testing.T) {
   214  	profilerDir := t.TempDir()
   215  	profilerFrequency := 500 * time.Millisecond
   216  	configJSON := fmt.Sprintf("{\"continuous-profiler-dir\": %q,\"continuous-profiler-frequency\": \"500ms\"}", profilerDir)
   217  	_, vm, _, _ := GenesisVM(t, false, genesisJSONApricotPhase0, configJSON, "")
   218  	assert.Equal(t, vm.config.ContinuousProfilerDir, profilerDir, "profiler dir should be set")
   219  	assert.Equal(t, vm.config.ContinuousProfilerFrequency.Duration, profilerFrequency, "profiler frequency should be set")
   220  
   221  	// Sleep for twice the frequency of the profiler to give it time
   222  	// to generate the first profile.
   223  	time.Sleep(2 * time.Second)
   224  	assert.NoError(t, vm.Shutdown())
   225  
   226  	// Check that the first profile was generated
   227  	expectedFileName := filepath.Join(profilerDir, "cpu.profile.1")
   228  	_, err := os.Stat(expectedFileName)
   229  	assert.NoError(t, err, "Expected continuous profiler to generate the first CPU profile at %s", expectedFileName)
   230  }
   231  
   232  func TestVMGenesis(t *testing.T) {
   233  	genesisTests := []struct {
   234  		name             string
   235  		genesis          string
   236  		expectedGasPrice *big.Int
   237  	}{
   238  		{
   239  			name:             "Apricot Phase 0",
   240  			genesis:          genesisJSONApricotPhase0,
   241  			expectedGasPrice: big.NewInt(params.LaunchMinGasPrice),
   242  		},
   243  		{
   244  			name:             "Apricot Phase 1",
   245  			genesis:          genesisJSONApricotPhase1,
   246  			expectedGasPrice: big.NewInt(params.ApricotPhase1MinGasPrice),
   247  		},
   248  		{
   249  			name:             "Apricot Phase 2",
   250  			genesis:          genesisJSONApricotPhase2,
   251  			expectedGasPrice: big.NewInt(params.ApricotPhase1MinGasPrice),
   252  		},
   253  		{
   254  			name:             "Apricot Phase 3",
   255  			genesis:          genesisJSONApricotPhase3,
   256  			expectedGasPrice: big.NewInt(0),
   257  		},
   258  	}
   259  	for _, test := range genesisTests {
   260  		t.Run(test.name, func(t *testing.T) {
   261  			_, vm, _, _ := GenesisVM(t, true, test.genesis, "", "")
   262  
   263  			if gasPrice := vm.chain.GetTxPool().GasPrice(); gasPrice.Cmp(test.expectedGasPrice) != 0 {
   264  				t.Fatalf("Expected pool gas price to be %d but found %d", test.expectedGasPrice, gasPrice)
   265  			}
   266  			defer func() {
   267  				shutdownChan := make(chan error, 1)
   268  				shutdownFunc := func() {
   269  					err := vm.Shutdown()
   270  					shutdownChan <- err
   271  				}
   272  
   273  				go shutdownFunc()
   274  				shutdownTimeout := 50 * time.Millisecond
   275  				ticker := time.NewTicker(shutdownTimeout)
   276  				select {
   277  				case <-ticker.C:
   278  					t.Fatalf("VM shutdown took longer than timeout: %v", shutdownTimeout)
   279  				case err := <-shutdownChan:
   280  					if err != nil {
   281  						t.Fatalf("Shutdown errored: %s", err)
   282  					}
   283  				}
   284  			}()
   285  
   286  			lastAcceptedID, err := vm.LastAccepted()
   287  			if err != nil {
   288  				t.Fatal(err)
   289  			}
   290  
   291  			if lastAcceptedID != ids.ID(vm.genesisHash) {
   292  				t.Fatal("Expected last accepted block to match the genesis block hash")
   293  			}
   294  
   295  			genesisBlk, err := vm.GetBlock(lastAcceptedID)
   296  			if err != nil {
   297  				t.Fatalf("Failed to get genesis block due to %s", err)
   298  			}
   299  
   300  			if height := genesisBlk.Height(); height != 0 {
   301  				t.Fatalf("Expected height of geneiss block to be 0, found: %d", height)
   302  			}
   303  
   304  			if _, err := vm.ParseBlock(genesisBlk.Bytes()); err != nil {
   305  				t.Fatalf("Failed to parse genesis block due to %s", err)
   306  			}
   307  
   308  			genesisStatus := genesisBlk.Status()
   309  			if genesisStatus != choices.Accepted {
   310  				t.Fatalf("expected genesis status to be %s but was %s", choices.Accepted, genesisStatus)
   311  			}
   312  		})
   313  	}
   314  }
   315  
   316  // Simple test to ensure we can issue an import transaction followed by an export transaction
   317  // and they will be indexed correctly when accepted.
   318  func TestIssueAtomicTxs(t *testing.T) {
   319  	issuer, vm, _, sharedMemory := GenesisVM(t, true, genesisJSONApricotPhase2, "", "")
   320  
   321  	defer func() {
   322  		if err := vm.Shutdown(); err != nil {
   323  			t.Fatal(err)
   324  		}
   325  	}()
   326  
   327  	importAmount := uint64(50000000)
   328  	utxoID := avax.UTXOID{
   329  		TxID: ids.ID{
   330  			0x0f, 0x2f, 0x4f, 0x6f, 0x8e, 0xae, 0xce, 0xee,
   331  			0x0d, 0x2d, 0x4d, 0x6d, 0x8c, 0xac, 0xcc, 0xec,
   332  			0x0b, 0x2b, 0x4b, 0x6b, 0x8a, 0xaa, 0xca, 0xea,
   333  			0x09, 0x29, 0x49, 0x69, 0x88, 0xa8, 0xc8, 0xe8,
   334  		},
   335  	}
   336  
   337  	utxo := &avax.UTXO{
   338  		UTXOID: utxoID,
   339  		Asset:  avax.Asset{ID: vm.ctx.AVAXAssetID},
   340  		Out: &secp256k1fx.TransferOutput{
   341  			Amt: importAmount,
   342  			OutputOwners: secp256k1fx.OutputOwners{
   343  				Threshold: 1,
   344  				Addrs:     []ids.ShortID{testKeys[0].PublicKey().Address()},
   345  			},
   346  		},
   347  	}
   348  	utxoBytes, err := vm.codec.Marshal(codecVersion, utxo)
   349  	if err != nil {
   350  		t.Fatal(err)
   351  	}
   352  
   353  	xChainSharedMemory := sharedMemory.NewSharedMemory(vm.ctx.XChainID)
   354  	inputID := utxo.InputID()
   355  	if err := xChainSharedMemory.Apply(map[ids.ID]*atomic.Requests{vm.ctx.ChainID: {PutRequests: []*atomic.Element{{
   356  		Key:   inputID[:],
   357  		Value: utxoBytes,
   358  		Traits: [][]byte{
   359  			testKeys[0].PublicKey().Address().Bytes(),
   360  		},
   361  	}}}}); err != nil {
   362  		t.Fatal(err)
   363  	}
   364  
   365  	importTx, err := vm.newImportTx(vm.ctx.XChainID, testEthAddrs[0], initialBaseFee, []*crypto.PrivateKeySECP256K1R{testKeys[0]})
   366  	if err != nil {
   367  		t.Fatal(err)
   368  	}
   369  
   370  	if err := vm.issueTx(importTx); err != nil {
   371  		t.Fatal(err)
   372  	}
   373  
   374  	<-issuer
   375  
   376  	blk, err := vm.BuildBlock()
   377  	if err != nil {
   378  		t.Fatal(err)
   379  	}
   380  
   381  	if err := blk.Verify(); err != nil {
   382  		t.Fatal(err)
   383  	}
   384  
   385  	if status := blk.Status(); status != choices.Processing {
   386  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
   387  	}
   388  
   389  	if err := vm.SetPreference(blk.ID()); err != nil {
   390  		t.Fatal(err)
   391  	}
   392  
   393  	if err := blk.Accept(); err != nil {
   394  		t.Fatal(err)
   395  	}
   396  
   397  	if status := blk.Status(); status != choices.Accepted {
   398  		t.Fatalf("Expected status of accepted block to be %s, but found %s", choices.Accepted, status)
   399  	}
   400  
   401  	if lastAcceptedID, err := vm.LastAccepted(); err != nil {
   402  		t.Fatal(err)
   403  	} else if lastAcceptedID != blk.ID() {
   404  		t.Fatalf("Expected last accepted blockID to be the accepted block: %s, but found %s", blk.ID(), lastAcceptedID)
   405  	}
   406  
   407  	exportTx, err := vm.newExportTx(vm.ctx.AVAXAssetID, importAmount-(2*params.AvalancheAtomicTxFee), vm.ctx.XChainID, testShortIDAddrs[0], initialBaseFee, []*crypto.PrivateKeySECP256K1R{testKeys[0]})
   408  	if err != nil {
   409  		t.Fatal(err)
   410  	}
   411  
   412  	if err := vm.issueTx(exportTx); err != nil {
   413  		t.Fatal(err)
   414  	}
   415  
   416  	<-issuer
   417  
   418  	blk2, err := vm.BuildBlock()
   419  	if err != nil {
   420  		t.Fatal(err)
   421  	}
   422  
   423  	if err := blk2.Verify(); err != nil {
   424  		t.Fatal(err)
   425  	}
   426  
   427  	if status := blk2.Status(); status != choices.Processing {
   428  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
   429  	}
   430  
   431  	if err := blk2.Accept(); err != nil {
   432  		t.Fatal(err)
   433  	}
   434  
   435  	if status := blk2.Status(); status != choices.Accepted {
   436  		t.Fatalf("Expected status of accepted block to be %s, but found %s", choices.Accepted, status)
   437  	}
   438  
   439  	if lastAcceptedID, err := vm.LastAccepted(); err != nil {
   440  		t.Fatal(err)
   441  	} else if lastAcceptedID != blk2.ID() {
   442  		t.Fatalf("Expected last accepted blockID to be the accepted block: %s, but found %s", blk2.ID(), lastAcceptedID)
   443  	}
   444  
   445  	// Check that both atomic transactions were indexed as expected.
   446  	indexedImportTx, status, height, err := vm.getAtomicTx(importTx.ID())
   447  	assert.NoError(t, err)
   448  	assert.Equal(t, Accepted, status)
   449  	assert.Equal(t, uint64(1), height, "expected height of indexed import tx to be 1")
   450  	assert.Equal(t, indexedImportTx.ID(), importTx.ID(), "expected ID of indexed import tx to match original txID")
   451  
   452  	indexedExportTx, status, height, err := vm.getAtomicTx(exportTx.ID())
   453  	assert.NoError(t, err)
   454  	assert.Equal(t, Accepted, status)
   455  	assert.Equal(t, uint64(2), height, "expected height of indexed export tx to be 2")
   456  	assert.Equal(t, indexedExportTx.ID(), exportTx.ID(), "expected ID of indexed import tx to match original txID")
   457  }
   458  
   459  func TestBuildEthTxBlock(t *testing.T) {
   460  	issuer, vm, dbManager, sharedMemory := GenesisVM(t, true, genesisJSONApricotPhase2, "{\"pruning-enabled\":true}", "")
   461  
   462  	defer func() {
   463  		if err := vm.Shutdown(); err != nil {
   464  			t.Fatal(err)
   465  		}
   466  	}()
   467  
   468  	newTxPoolHeadChan := make(chan core.NewTxPoolReorgEvent, 1)
   469  	vm.chain.GetTxPool().SubscribeNewReorgEvent(newTxPoolHeadChan)
   470  
   471  	key, err := accountKeystore.NewKey(rand.Reader)
   472  	if err != nil {
   473  		t.Fatal(err)
   474  	}
   475  
   476  	importAmount := uint64(20000000)
   477  	utxoID := avax.UTXOID{
   478  		TxID: ids.ID{
   479  			0x0f, 0x2f, 0x4f, 0x6f, 0x8e, 0xae, 0xce, 0xee,
   480  			0x0d, 0x2d, 0x4d, 0x6d, 0x8c, 0xac, 0xcc, 0xec,
   481  			0x0b, 0x2b, 0x4b, 0x6b, 0x8a, 0xaa, 0xca, 0xea,
   482  			0x09, 0x29, 0x49, 0x69, 0x88, 0xa8, 0xc8, 0xe8,
   483  		},
   484  	}
   485  
   486  	utxo := &avax.UTXO{
   487  		UTXOID: utxoID,
   488  		Asset:  avax.Asset{ID: vm.ctx.AVAXAssetID},
   489  		Out: &secp256k1fx.TransferOutput{
   490  			Amt: importAmount,
   491  			OutputOwners: secp256k1fx.OutputOwners{
   492  				Threshold: 1,
   493  				Addrs:     []ids.ShortID{testKeys[0].PublicKey().Address()},
   494  			},
   495  		},
   496  	}
   497  	utxoBytes, err := vm.codec.Marshal(codecVersion, utxo)
   498  	if err != nil {
   499  		t.Fatal(err)
   500  	}
   501  
   502  	xChainSharedMemory := sharedMemory.NewSharedMemory(vm.ctx.XChainID)
   503  	inputID := utxo.InputID()
   504  	if err := xChainSharedMemory.Apply(map[ids.ID]*atomic.Requests{vm.ctx.ChainID: {PutRequests: []*atomic.Element{{
   505  		Key:   inputID[:],
   506  		Value: utxoBytes,
   507  		Traits: [][]byte{
   508  			testKeys[0].PublicKey().Address().Bytes(),
   509  		},
   510  	}}}}); err != nil {
   511  		t.Fatal(err)
   512  	}
   513  
   514  	importTx, err := vm.newImportTx(vm.ctx.XChainID, key.Address, initialBaseFee, []*crypto.PrivateKeySECP256K1R{testKeys[0]})
   515  	if err != nil {
   516  		t.Fatal(err)
   517  	}
   518  
   519  	if err := vm.issueTx(importTx); err != nil {
   520  		t.Fatal(err)
   521  	}
   522  
   523  	<-issuer
   524  
   525  	blk1, err := vm.BuildBlock()
   526  	if err != nil {
   527  		t.Fatal(err)
   528  	}
   529  
   530  	if err := blk1.Verify(); err != nil {
   531  		t.Fatal(err)
   532  	}
   533  
   534  	if status := blk1.Status(); status != choices.Processing {
   535  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
   536  	}
   537  
   538  	if err := vm.SetPreference(blk1.ID()); err != nil {
   539  		t.Fatal(err)
   540  	}
   541  
   542  	if err := blk1.Accept(); err != nil {
   543  		t.Fatal(err)
   544  	}
   545  
   546  	newHead := <-newTxPoolHeadChan
   547  	if newHead.Head.Hash() != common.Hash(blk1.ID()) {
   548  		t.Fatalf("Expected new block to match")
   549  	}
   550  
   551  	txs := make([]*types.Transaction, 10)
   552  	for i := 0; i < 10; i++ {
   553  		tx := types.NewTransaction(uint64(i), key.Address, big.NewInt(10), 21000, big.NewInt(params.LaunchMinGasPrice), nil)
   554  		signedTx, err := types.SignTx(tx, types.NewEIP155Signer(vm.chainID), key.PrivateKey)
   555  		if err != nil {
   556  			t.Fatal(err)
   557  		}
   558  		txs[i] = signedTx
   559  	}
   560  	errs := vm.chain.AddRemoteTxs(txs)
   561  	for i, err := range errs {
   562  		if err != nil {
   563  			t.Fatalf("Failed to add tx at index %d: %s", i, err)
   564  		}
   565  	}
   566  
   567  	<-issuer
   568  
   569  	blk2, err := vm.BuildBlock()
   570  	if err != nil {
   571  		t.Fatal(err)
   572  	}
   573  
   574  	if err := blk2.Verify(); err != nil {
   575  		t.Fatal(err)
   576  	}
   577  
   578  	if status := blk2.Status(); status != choices.Processing {
   579  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
   580  	}
   581  
   582  	if err := blk2.Accept(); err != nil {
   583  		t.Fatal(err)
   584  	}
   585  
   586  	newHead = <-newTxPoolHeadChan
   587  	if newHead.Head.Hash() != common.Hash(blk2.ID()) {
   588  		t.Fatalf("Expected new block to match")
   589  	}
   590  
   591  	if status := blk2.Status(); status != choices.Accepted {
   592  		t.Fatalf("Expected status of accepted block to be %s, but found %s", choices.Accepted, status)
   593  	}
   594  
   595  	lastAcceptedID, err := vm.LastAccepted()
   596  	if err != nil {
   597  		t.Fatal(err)
   598  	}
   599  	if lastAcceptedID != blk2.ID() {
   600  		t.Fatalf("Expected last accepted blockID to be the accepted block: %s, but found %s", blk2.ID(), lastAcceptedID)
   601  	}
   602  
   603  	ethBlk1 := blk1.(*chain.BlockWrapper).Block.(*Block).ethBlock
   604  	if ethBlk1Root := ethBlk1.Root(); !vm.chain.BlockChain().HasState(ethBlk1Root) {
   605  		t.Fatalf("Expected blk1 state root to not yet be pruned after blk2 was accepted because of tip buffer")
   606  	}
   607  
   608  	// Clear the cache and ensure that GetBlock returns internal blocks with the correct status
   609  	vm.State.Flush()
   610  	blk2Refreshed, err := vm.GetBlockInternal(blk2.ID())
   611  	if err != nil {
   612  		t.Fatal(err)
   613  	}
   614  	if status := blk2Refreshed.Status(); status != choices.Accepted {
   615  		t.Fatalf("Expected refreshed blk2 to be Accepted, but found status: %s", status)
   616  	}
   617  
   618  	blk1RefreshedID := blk2Refreshed.Parent()
   619  	blk1Refreshed, err := vm.GetBlockInternal(blk1RefreshedID)
   620  	if err != nil {
   621  		t.Fatal(err)
   622  	}
   623  	if status := blk1Refreshed.Status(); status != choices.Accepted {
   624  		t.Fatalf("Expected refreshed blk1 to be Accepted, but found status: %s", status)
   625  	}
   626  
   627  	if blk1Refreshed.ID() != blk1.ID() {
   628  		t.Fatalf("Found unexpected blkID for parent of blk2")
   629  	}
   630  
   631  	restartedVM := &VM{}
   632  	if err := restartedVM.Initialize(
   633  		NewContext(),
   634  		dbManager,
   635  		[]byte(genesisJSONApricotPhase2),
   636  		[]byte(""),
   637  		[]byte("{\"pruning-enabled\":true}"),
   638  		issuer,
   639  		[]*engCommon.Fx{},
   640  	); err != nil {
   641  		t.Fatal(err)
   642  	}
   643  
   644  	// State root should not have been committed and discarded on restart
   645  	if ethBlk1Root := ethBlk1.Root(); restartedVM.chain.BlockChain().HasState(ethBlk1Root) {
   646  		t.Fatalf("Expected blk1 state root to be pruned after blk2 was accepted on top of it in pruning mode")
   647  	}
   648  
   649  	// State root should be committed when accepted tip on shutdown
   650  	ethBlk2 := blk2.(*chain.BlockWrapper).Block.(*Block).ethBlock
   651  	if ethBlk2Root := ethBlk2.Root(); !restartedVM.chain.BlockChain().HasState(ethBlk2Root) {
   652  		t.Fatalf("Expected blk2 state root to not be pruned after shutdown (last accepted tip should be committed)")
   653  	}
   654  }
   655  
   656  func TestConflictingImportTxs(t *testing.T) {
   657  	issuer, vm, _, sharedMemory := GenesisVM(t, true, genesisJSONApricotPhase0, "", "")
   658  
   659  	defer func() {
   660  		if err := vm.Shutdown(); err != nil {
   661  			t.Fatal(err)
   662  		}
   663  	}()
   664  
   665  	conflictKey, err := accountKeystore.NewKey(rand.Reader)
   666  	if err != nil {
   667  		t.Fatal(err)
   668  	}
   669  
   670  	xChainSharedMemory := sharedMemory.NewSharedMemory(vm.ctx.XChainID)
   671  	importTxs := make([]*Tx, 0, 3)
   672  	conflictTxs := make([]*Tx, 0, 3)
   673  	for i, key := range testKeys {
   674  		importAmount := uint64(10000000)
   675  		utxoID := avax.UTXOID{
   676  			TxID: ids.ID{byte(i)},
   677  		}
   678  
   679  		utxo := &avax.UTXO{
   680  			UTXOID: utxoID,
   681  			Asset:  avax.Asset{ID: vm.ctx.AVAXAssetID},
   682  			Out: &secp256k1fx.TransferOutput{
   683  				Amt: importAmount,
   684  				OutputOwners: secp256k1fx.OutputOwners{
   685  					Threshold: 1,
   686  					Addrs:     []ids.ShortID{key.PublicKey().Address()},
   687  				},
   688  			},
   689  		}
   690  		utxoBytes, err := vm.codec.Marshal(codecVersion, utxo)
   691  		if err != nil {
   692  			t.Fatal(err)
   693  		}
   694  
   695  		inputID := utxo.InputID()
   696  		if err := xChainSharedMemory.Apply(map[ids.ID]*atomic.Requests{vm.ctx.ChainID: {PutRequests: []*atomic.Element{{
   697  			Key:   inputID[:],
   698  			Value: utxoBytes,
   699  			Traits: [][]byte{
   700  				key.PublicKey().Address().Bytes(),
   701  			},
   702  		}}}}); err != nil {
   703  			t.Fatal(err)
   704  		}
   705  
   706  		importTx, err := vm.newImportTx(vm.ctx.XChainID, testEthAddrs[i], initialBaseFee, []*crypto.PrivateKeySECP256K1R{key})
   707  		if err != nil {
   708  			t.Fatal(err)
   709  		}
   710  		importTxs = append(importTxs, importTx)
   711  
   712  		conflictTx, err := vm.newImportTx(vm.ctx.XChainID, conflictKey.Address, initialBaseFee, []*crypto.PrivateKeySECP256K1R{key})
   713  		if err != nil {
   714  			t.Fatal(err)
   715  		}
   716  		conflictTxs = append(conflictTxs, conflictTx)
   717  	}
   718  
   719  	expectedParentBlkID, err := vm.LastAccepted()
   720  	if err != nil {
   721  		t.Fatal(err)
   722  	}
   723  	for i, tx := range importTxs {
   724  		if err := vm.issueTx(tx); err != nil {
   725  			t.Fatal(err)
   726  		}
   727  
   728  		<-issuer
   729  
   730  		blk, err := vm.BuildBlock()
   731  		if err != nil {
   732  			t.Fatal(err)
   733  		}
   734  
   735  		if err := blk.Verify(); err != nil {
   736  			t.Fatal(err)
   737  		}
   738  
   739  		if status := blk.Status(); status != choices.Processing {
   740  			t.Fatalf("Expected status of built block %d to be %s, but found %s", i, choices.Processing, status)
   741  		}
   742  
   743  		if parentID := blk.Parent(); parentID != expectedParentBlkID {
   744  			t.Fatalf("Expected parent to have blockID %s, but found %s", expectedParentBlkID, parentID)
   745  		}
   746  
   747  		expectedParentBlkID = blk.ID()
   748  		if err := vm.SetPreference(blk.ID()); err != nil {
   749  			t.Fatal(err)
   750  		}
   751  	}
   752  
   753  	for i, tx := range conflictTxs {
   754  		if err := vm.issueTx(tx); err == nil {
   755  			t.Fatal("Expected issueTx to fail due to conflicting transaction")
   756  		}
   757  		// Force issue transaction directly to the mempool
   758  		if err := vm.mempool.AddTx(tx); err != nil {
   759  			t.Fatal(err)
   760  		}
   761  		<-issuer
   762  
   763  		_, err := vm.BuildBlock()
   764  		// The new block is verified in BuildBlock, so
   765  		// BuildBlock should fail due to an attempt to
   766  		// double spend an atomic UTXO.
   767  		if err == nil {
   768  			t.Fatalf("Block verification should have failed in BuildBlock %d due to double spending atomic UTXO", i)
   769  		}
   770  	}
   771  }
   772  
   773  // Regression test to ensure that after accepting block A
   774  // then calling SetPreference on block B (when it becomes preferred)
   775  // and the head of a longer chain (block D) does not corrupt the
   776  // canonical chain.
   777  //  A
   778  // / \
   779  // B  C
   780  //    |
   781  //    D
   782  func TestSetPreferenceRace(t *testing.T) {
   783  	// Create two VMs which will agree on block A and then
   784  	// build the two distinct preferred chains above
   785  	issuer1, vm1, _, sharedMemory1 := GenesisVM(t, true, genesisJSONApricotPhase0, "", "")
   786  	issuer2, vm2, _, sharedMemory2 := GenesisVM(t, true, genesisJSONApricotPhase0, "", "")
   787  
   788  	defer func() {
   789  		if err := vm1.Shutdown(); err != nil {
   790  			t.Fatal(err)
   791  		}
   792  
   793  		if err := vm2.Shutdown(); err != nil {
   794  			t.Fatal(err)
   795  		}
   796  	}()
   797  
   798  	newTxPoolHeadChan1 := make(chan core.NewTxPoolReorgEvent, 1)
   799  	vm1.chain.GetTxPool().SubscribeNewReorgEvent(newTxPoolHeadChan1)
   800  	newTxPoolHeadChan2 := make(chan core.NewTxPoolReorgEvent, 1)
   801  	vm2.chain.GetTxPool().SubscribeNewReorgEvent(newTxPoolHeadChan2)
   802  
   803  	key, err := accountKeystore.NewKey(rand.Reader)
   804  	if err != nil {
   805  		t.Fatal(err)
   806  	}
   807  
   808  	// Import 1 AVAX
   809  	importAmount := uint64(1000000000)
   810  	utxoID := avax.UTXOID{
   811  		TxID: ids.ID{
   812  			0x0f, 0x2f, 0x4f, 0x6f, 0x8e, 0xae, 0xce, 0xee,
   813  			0x0d, 0x2d, 0x4d, 0x6d, 0x8c, 0xac, 0xcc, 0xec,
   814  			0x0b, 0x2b, 0x4b, 0x6b, 0x8a, 0xaa, 0xca, 0xea,
   815  			0x09, 0x29, 0x49, 0x69, 0x88, 0xa8, 0xc8, 0xe8,
   816  		},
   817  	}
   818  
   819  	utxo := &avax.UTXO{
   820  		UTXOID: utxoID,
   821  		Asset:  avax.Asset{ID: vm1.ctx.AVAXAssetID},
   822  		Out: &secp256k1fx.TransferOutput{
   823  			Amt: importAmount,
   824  			OutputOwners: secp256k1fx.OutputOwners{
   825  				Threshold: 1,
   826  				Addrs:     []ids.ShortID{testKeys[0].PublicKey().Address()},
   827  			},
   828  		},
   829  	}
   830  	utxoBytes, err := vm1.codec.Marshal(codecVersion, utxo)
   831  	if err != nil {
   832  		t.Fatal(err)
   833  	}
   834  
   835  	xChainSharedMemory1 := sharedMemory1.NewSharedMemory(vm1.ctx.XChainID)
   836  	xChainSharedMemory2 := sharedMemory2.NewSharedMemory(vm2.ctx.XChainID)
   837  	inputID := utxo.InputID()
   838  	if err := xChainSharedMemory1.Apply(map[ids.ID]*atomic.Requests{vm1.ctx.ChainID: {PutRequests: []*atomic.Element{{
   839  		Key:   inputID[:],
   840  		Value: utxoBytes,
   841  		Traits: [][]byte{
   842  			testKeys[0].PublicKey().Address().Bytes(),
   843  		},
   844  	}}}}); err != nil {
   845  		t.Fatal(err)
   846  	}
   847  	if err := xChainSharedMemory2.Apply(map[ids.ID]*atomic.Requests{vm2.ctx.ChainID: {PutRequests: []*atomic.Element{{
   848  		Key:   inputID[:],
   849  		Value: utxoBytes,
   850  		Traits: [][]byte{
   851  			testKeys[0].PublicKey().Address().Bytes(),
   852  		},
   853  	}}}}); err != nil {
   854  		t.Fatal(err)
   855  	}
   856  
   857  	importTx, err := vm1.newImportTx(vm1.ctx.XChainID, key.Address, initialBaseFee, []*crypto.PrivateKeySECP256K1R{testKeys[0]})
   858  	if err != nil {
   859  		t.Fatal(err)
   860  	}
   861  
   862  	if err := vm1.issueTx(importTx); err != nil {
   863  		t.Fatal(err)
   864  	}
   865  
   866  	<-issuer1
   867  
   868  	vm1BlkA, err := vm1.BuildBlock()
   869  	if err != nil {
   870  		t.Fatalf("Failed to build block with import transaction: %s", err)
   871  	}
   872  
   873  	if err := vm1BlkA.Verify(); err != nil {
   874  		t.Fatalf("Block failed verification on VM1: %s", err)
   875  	}
   876  
   877  	if status := vm1BlkA.Status(); status != choices.Processing {
   878  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
   879  	}
   880  
   881  	if err := vm1.SetPreference(vm1BlkA.ID()); err != nil {
   882  		t.Fatal(err)
   883  	}
   884  
   885  	vm2BlkA, err := vm2.ParseBlock(vm1BlkA.Bytes())
   886  	if err != nil {
   887  		t.Fatalf("Unexpected error parsing block from vm2: %s", err)
   888  	}
   889  	if err := vm2BlkA.Verify(); err != nil {
   890  		t.Fatalf("Block failed verification on VM2: %s", err)
   891  	}
   892  	if status := vm2BlkA.Status(); status != choices.Processing {
   893  		t.Fatalf("Expected status of block on VM2 to be %s, but found %s", choices.Processing, status)
   894  	}
   895  	if err := vm2.SetPreference(vm2BlkA.ID()); err != nil {
   896  		t.Fatal(err)
   897  	}
   898  
   899  	if err := vm1BlkA.Accept(); err != nil {
   900  		t.Fatalf("VM1 failed to accept block: %s", err)
   901  	}
   902  	if err := vm2BlkA.Accept(); err != nil {
   903  		t.Fatalf("VM2 failed to accept block: %s", err)
   904  	}
   905  
   906  	newHead := <-newTxPoolHeadChan1
   907  	if newHead.Head.Hash() != common.Hash(vm1BlkA.ID()) {
   908  		t.Fatalf("Expected new block to match")
   909  	}
   910  	newHead = <-newTxPoolHeadChan2
   911  	if newHead.Head.Hash() != common.Hash(vm2BlkA.ID()) {
   912  		t.Fatalf("Expected new block to match")
   913  	}
   914  
   915  	// Create list of 10 successive transactions to build block A on vm1
   916  	// and to be split into two separate blocks on VM2
   917  	txs := make([]*types.Transaction, 10)
   918  	for i := 0; i < 10; i++ {
   919  		tx := types.NewTransaction(uint64(i), key.Address, big.NewInt(10), 21000, big.NewInt(params.LaunchMinGasPrice), nil)
   920  		signedTx, err := types.SignTx(tx, types.NewEIP155Signer(vm1.chainID), key.PrivateKey)
   921  		if err != nil {
   922  			t.Fatal(err)
   923  		}
   924  		txs[i] = signedTx
   925  	}
   926  
   927  	var errs []error
   928  
   929  	// Add the remote transactions, build the block, and set VM1's preference for block A
   930  	errs = vm1.chain.AddRemoteTxs(txs)
   931  	for i, err := range errs {
   932  		if err != nil {
   933  			t.Fatalf("Failed to add transaction to VM1 at index %d: %s", i, err)
   934  		}
   935  	}
   936  
   937  	<-issuer1
   938  
   939  	vm1BlkB, err := vm1.BuildBlock()
   940  	if err != nil {
   941  		t.Fatal(err)
   942  	}
   943  
   944  	if err := vm1BlkB.Verify(); err != nil {
   945  		t.Fatal(err)
   946  	}
   947  
   948  	if status := vm1BlkB.Status(); status != choices.Processing {
   949  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
   950  	}
   951  
   952  	if err := vm1.SetPreference(vm1BlkB.ID()); err != nil {
   953  		t.Fatal(err)
   954  	}
   955  
   956  	// Split the transactions over two blocks, and set VM2's preference to them in sequence
   957  	// after building each block
   958  	// Block C
   959  	errs = vm2.chain.AddRemoteTxs(txs[0:5])
   960  	for i, err := range errs {
   961  		if err != nil {
   962  			t.Fatalf("Failed to add transaction to VM2 at index %d: %s", i, err)
   963  		}
   964  	}
   965  
   966  	<-issuer2
   967  	vm2BlkC, err := vm2.BuildBlock()
   968  	if err != nil {
   969  		t.Fatalf("Failed to build BlkC on VM2: %s", err)
   970  	}
   971  
   972  	if err := vm2BlkC.Verify(); err != nil {
   973  		t.Fatalf("BlkC failed verification on VM2: %s", err)
   974  	}
   975  
   976  	if status := vm2BlkC.Status(); status != choices.Processing {
   977  		t.Fatalf("Expected status of built block C to be %s, but found %s", choices.Processing, status)
   978  	}
   979  
   980  	if err := vm2.SetPreference(vm2BlkC.ID()); err != nil {
   981  		t.Fatal(err)
   982  	}
   983  
   984  	newHead = <-newTxPoolHeadChan2
   985  	if newHead.Head.Hash() != common.Hash(vm2BlkC.ID()) {
   986  		t.Fatalf("Expected new block to match")
   987  	}
   988  
   989  	// Block D
   990  	errs = vm2.chain.AddRemoteTxs(txs[5:10])
   991  	for i, err := range errs {
   992  		if err != nil {
   993  			t.Fatalf("Failed to add transaction to VM2 at index %d: %s", i, err)
   994  		}
   995  	}
   996  
   997  	<-issuer2
   998  	vm2BlkD, err := vm2.BuildBlock()
   999  	if err != nil {
  1000  		t.Fatalf("Failed to build BlkD on VM2: %s", err)
  1001  	}
  1002  
  1003  	if err := vm2BlkD.Verify(); err != nil {
  1004  		t.Fatalf("BlkD failed verification on VM2: %s", err)
  1005  	}
  1006  
  1007  	if status := vm2BlkD.Status(); status != choices.Processing {
  1008  		t.Fatalf("Expected status of built block D to be %s, but found %s", choices.Processing, status)
  1009  	}
  1010  
  1011  	if err := vm2.SetPreference(vm2BlkD.ID()); err != nil {
  1012  		t.Fatal(err)
  1013  	}
  1014  
  1015  	// VM1 receives blkC and blkD from VM1
  1016  	// and happens to call SetPreference on blkD without ever calling SetPreference
  1017  	// on blkC
  1018  	// Here we parse them in reverse order to simulate receiving a chain from the tip
  1019  	// back to the last accepted block as would typically be the case in the consensus
  1020  	// engine
  1021  	vm1BlkD, err := vm1.ParseBlock(vm2BlkD.Bytes())
  1022  	if err != nil {
  1023  		t.Fatalf("VM1 errored parsing blkD: %s", err)
  1024  	}
  1025  	vm1BlkC, err := vm1.ParseBlock(vm2BlkC.Bytes())
  1026  	if err != nil {
  1027  		t.Fatalf("VM1 errored parsing blkC: %s", err)
  1028  	}
  1029  
  1030  	// The blocks must be verified in order. This invariant is maintained
  1031  	// in the consensus engine.
  1032  	if err := vm1BlkC.Verify(); err != nil {
  1033  		t.Fatalf("VM1 BlkC failed verification: %s", err)
  1034  	}
  1035  	if err := vm1BlkD.Verify(); err != nil {
  1036  		t.Fatalf("VM1 BlkD failed verification: %s", err)
  1037  	}
  1038  
  1039  	// Set VM1's preference to blockD, skipping blockC
  1040  	if err := vm1.SetPreference(vm1BlkD.ID()); err != nil {
  1041  		t.Fatal(err)
  1042  	}
  1043  
  1044  	// Accept the longer chain on both VMs and ensure there are no errors
  1045  	// VM1 Accepts the blocks in order
  1046  	if err := vm1BlkC.Accept(); err != nil {
  1047  		t.Fatalf("VM1 BlkC failed on accept: %s", err)
  1048  	}
  1049  	if err := vm1BlkD.Accept(); err != nil {
  1050  		t.Fatalf("VM1 BlkC failed on accept: %s", err)
  1051  	}
  1052  
  1053  	// VM2 Accepts the blocks in order
  1054  	if err := vm2BlkC.Accept(); err != nil {
  1055  		t.Fatalf("VM2 BlkC failed on accept: %s", err)
  1056  	}
  1057  	if err := vm2BlkD.Accept(); err != nil {
  1058  		t.Fatalf("VM2 BlkC failed on accept: %s", err)
  1059  	}
  1060  
  1061  	log.Info("Validating canonical chain")
  1062  	// Verify the Canonical Chain for Both VMs
  1063  	if err := vm2.chain.ValidateCanonicalChain(); err != nil {
  1064  		t.Fatalf("VM2 failed canonical chain verification due to: %s", err)
  1065  	}
  1066  
  1067  	if err := vm1.chain.ValidateCanonicalChain(); err != nil {
  1068  		t.Fatalf("VM1 failed canonical chain verification due to: %s", err)
  1069  	}
  1070  }
  1071  
  1072  func TestConflictingTransitiveAncestryWithGap(t *testing.T) {
  1073  	issuer, vm, _, atomicMemory := GenesisVM(t, true, genesisJSONApricotPhase0, "", "")
  1074  
  1075  	defer func() {
  1076  		if err := vm.Shutdown(); err != nil {
  1077  			t.Fatal(err)
  1078  		}
  1079  	}()
  1080  
  1081  	newTxPoolHeadChan := make(chan core.NewTxPoolReorgEvent, 1)
  1082  	vm.chain.GetTxPool().SubscribeNewReorgEvent(newTxPoolHeadChan)
  1083  
  1084  	key, err := accountKeystore.NewKey(rand.Reader)
  1085  	if err != nil {
  1086  		t.Fatal(err)
  1087  	}
  1088  
  1089  	key0 := testKeys[0]
  1090  	addr0 := key0.PublicKey().Address()
  1091  
  1092  	key1 := testKeys[1]
  1093  	addr1 := key1.PublicKey().Address()
  1094  
  1095  	importAmount := uint64(1000000000)
  1096  
  1097  	utxo0ID := avax.UTXOID{}
  1098  	utxo1ID := avax.UTXOID{OutputIndex: 1}
  1099  
  1100  	input0ID := utxo0ID.InputID()
  1101  	input1ID := utxo1ID.InputID()
  1102  
  1103  	utxo0 := &avax.UTXO{
  1104  		UTXOID: utxo0ID,
  1105  		Asset:  avax.Asset{ID: vm.ctx.AVAXAssetID},
  1106  		Out: &secp256k1fx.TransferOutput{
  1107  			Amt: importAmount,
  1108  			OutputOwners: secp256k1fx.OutputOwners{
  1109  				Threshold: 1,
  1110  				Addrs:     []ids.ShortID{addr0},
  1111  			},
  1112  		},
  1113  	}
  1114  	utxo1 := &avax.UTXO{
  1115  		UTXOID: utxo1ID,
  1116  		Asset:  avax.Asset{ID: vm.ctx.AVAXAssetID},
  1117  		Out: &secp256k1fx.TransferOutput{
  1118  			Amt: importAmount,
  1119  			OutputOwners: secp256k1fx.OutputOwners{
  1120  				Threshold: 1,
  1121  				Addrs:     []ids.ShortID{addr1},
  1122  			},
  1123  		},
  1124  	}
  1125  	utxo0Bytes, err := vm.codec.Marshal(codecVersion, utxo0)
  1126  	if err != nil {
  1127  		t.Fatal(err)
  1128  	}
  1129  	utxo1Bytes, err := vm.codec.Marshal(codecVersion, utxo1)
  1130  	if err != nil {
  1131  		t.Fatal(err)
  1132  	}
  1133  
  1134  	xChainSharedMemory := atomicMemory.NewSharedMemory(vm.ctx.XChainID)
  1135  	if err := xChainSharedMemory.Apply(map[ids.ID]*atomic.Requests{vm.ctx.ChainID: {PutRequests: []*atomic.Element{
  1136  		{
  1137  			Key:   input0ID[:],
  1138  			Value: utxo0Bytes,
  1139  			Traits: [][]byte{
  1140  				addr0.Bytes(),
  1141  			},
  1142  		},
  1143  		{
  1144  			Key:   input1ID[:],
  1145  			Value: utxo1Bytes,
  1146  			Traits: [][]byte{
  1147  				addr1.Bytes(),
  1148  			},
  1149  		},
  1150  	}}}); err != nil {
  1151  		t.Fatal(err)
  1152  	}
  1153  
  1154  	importTx0A, err := vm.newImportTx(vm.ctx.XChainID, key.Address, initialBaseFee, []*crypto.PrivateKeySECP256K1R{key0})
  1155  	if err != nil {
  1156  		t.Fatal(err)
  1157  	}
  1158  	// Create a conflicting transaction
  1159  	importTx0B, err := vm.newImportTx(vm.ctx.XChainID, testEthAddrs[2], initialBaseFee, []*crypto.PrivateKeySECP256K1R{key0})
  1160  	if err != nil {
  1161  		t.Fatal(err)
  1162  	}
  1163  
  1164  	if err := vm.issueTx(importTx0A); err != nil {
  1165  		t.Fatalf("Failed to issue importTx0A: %s", err)
  1166  	}
  1167  
  1168  	<-issuer
  1169  
  1170  	blk0, err := vm.BuildBlock()
  1171  	if err != nil {
  1172  		t.Fatalf("Failed to build block with import transaction: %s", err)
  1173  	}
  1174  
  1175  	if err := blk0.Verify(); err != nil {
  1176  		t.Fatalf("Block failed verification: %s", err)
  1177  	}
  1178  
  1179  	if err := vm.SetPreference(blk0.ID()); err != nil {
  1180  		t.Fatal(err)
  1181  	}
  1182  
  1183  	newHead := <-newTxPoolHeadChan
  1184  	if newHead.Head.Hash() != common.Hash(blk0.ID()) {
  1185  		t.Fatalf("Expected new block to match")
  1186  	}
  1187  
  1188  	tx := types.NewTransaction(0, key.Address, big.NewInt(10), 21000, big.NewInt(params.LaunchMinGasPrice), nil)
  1189  	signedTx, err := types.SignTx(tx, types.NewEIP155Signer(vm.chainID), key.PrivateKey)
  1190  	if err != nil {
  1191  		t.Fatal(err)
  1192  	}
  1193  
  1194  	// Add the remote transactions, build the block, and set VM1's preference for block A
  1195  	errs := vm.chain.AddRemoteTxs([]*types.Transaction{signedTx})
  1196  	for i, err := range errs {
  1197  		if err != nil {
  1198  			t.Fatalf("Failed to add transaction to VM1 at index %d: %s", i, err)
  1199  		}
  1200  	}
  1201  
  1202  	<-issuer
  1203  
  1204  	blk1, err := vm.BuildBlock()
  1205  	if err != nil {
  1206  		t.Fatalf("Failed to build blk1: %s", err)
  1207  	}
  1208  
  1209  	if err := blk1.Verify(); err != nil {
  1210  		t.Fatalf("blk1 failed verification due to %s", err)
  1211  	}
  1212  
  1213  	if err := vm.SetPreference(blk1.ID()); err != nil {
  1214  		t.Fatal(err)
  1215  	}
  1216  
  1217  	importTx1, err := vm.newImportTx(vm.ctx.XChainID, key.Address, initialBaseFee, []*crypto.PrivateKeySECP256K1R{key1})
  1218  	if err != nil {
  1219  		t.Fatalf("Failed to issue importTx1 due to: %s", err)
  1220  	}
  1221  
  1222  	if err := vm.issueTx(importTx1); err != nil {
  1223  		t.Fatal(err)
  1224  	}
  1225  
  1226  	<-issuer
  1227  
  1228  	blk2, err := vm.BuildBlock()
  1229  	if err != nil {
  1230  		t.Fatalf("Failed to build block with import transaction: %s", err)
  1231  	}
  1232  
  1233  	if err := blk2.Verify(); err != nil {
  1234  		t.Fatalf("Block failed verification: %s", err)
  1235  	}
  1236  
  1237  	if err := vm.SetPreference(blk2.ID()); err != nil {
  1238  		t.Fatal(err)
  1239  	}
  1240  
  1241  	if err := vm.issueTx(importTx0B); err == nil {
  1242  		t.Fatalf("Should not have been able to issue import tx with conflict")
  1243  	}
  1244  	// Force issue transaction directly into the mempool
  1245  	if err := vm.mempool.AddTx(importTx0B); err != nil {
  1246  		t.Fatal(err)
  1247  	}
  1248  
  1249  	<-issuer
  1250  
  1251  	_, err = vm.BuildBlock()
  1252  	if err == nil {
  1253  		t.Fatal("Shouldn't have been able to build an invalid block")
  1254  	}
  1255  }
  1256  
  1257  func TestBonusBlocksTxs(t *testing.T) {
  1258  	issuer, vm, _, sharedMemory := GenesisVM(t, true, genesisJSONApricotPhase0, "", "")
  1259  
  1260  	defer func() {
  1261  		if err := vm.Shutdown(); err != nil {
  1262  			t.Fatal(err)
  1263  		}
  1264  	}()
  1265  
  1266  	importAmount := uint64(10000000)
  1267  	utxoID := avax.UTXOID{
  1268  		TxID: ids.ID{
  1269  			0x0f, 0x2f, 0x4f, 0x6f, 0x8e, 0xae, 0xce, 0xee,
  1270  			0x0d, 0x2d, 0x4d, 0x6d, 0x8c, 0xac, 0xcc, 0xec,
  1271  			0x0b, 0x2b, 0x4b, 0x6b, 0x8a, 0xaa, 0xca, 0xea,
  1272  			0x09, 0x29, 0x49, 0x69, 0x88, 0xa8, 0xc8, 0xe8,
  1273  		},
  1274  	}
  1275  
  1276  	utxo := &avax.UTXO{
  1277  		UTXOID: utxoID,
  1278  		Asset:  avax.Asset{ID: vm.ctx.AVAXAssetID},
  1279  		Out: &secp256k1fx.TransferOutput{
  1280  			Amt: importAmount,
  1281  			OutputOwners: secp256k1fx.OutputOwners{
  1282  				Threshold: 1,
  1283  				Addrs:     []ids.ShortID{testKeys[0].PublicKey().Address()},
  1284  			},
  1285  		},
  1286  	}
  1287  	utxoBytes, err := vm.codec.Marshal(codecVersion, utxo)
  1288  	if err != nil {
  1289  		t.Fatal(err)
  1290  	}
  1291  
  1292  	xChainSharedMemory := sharedMemory.NewSharedMemory(vm.ctx.XChainID)
  1293  	inputID := utxo.InputID()
  1294  	if err := xChainSharedMemory.Apply(map[ids.ID]*atomic.Requests{vm.ctx.ChainID: {PutRequests: []*atomic.Element{{
  1295  		Key:   inputID[:],
  1296  		Value: utxoBytes,
  1297  		Traits: [][]byte{
  1298  			testKeys[0].PublicKey().Address().Bytes(),
  1299  		},
  1300  	}}}}); err != nil {
  1301  		t.Fatal(err)
  1302  	}
  1303  
  1304  	importTx, err := vm.newImportTx(vm.ctx.XChainID, testEthAddrs[0], initialBaseFee, []*crypto.PrivateKeySECP256K1R{testKeys[0]})
  1305  	if err != nil {
  1306  		t.Fatal(err)
  1307  	}
  1308  
  1309  	if err := vm.issueTx(importTx); err != nil {
  1310  		t.Fatal(err)
  1311  	}
  1312  
  1313  	<-issuer
  1314  
  1315  	blk, err := vm.BuildBlock()
  1316  	if err != nil {
  1317  		t.Fatal(err)
  1318  	}
  1319  
  1320  	bonusBlocks.Add(blk.ID())
  1321  
  1322  	// Remove the UTXOs from shared memory, so that non-bonus blocks will fail verification
  1323  	if err := vm.ctx.SharedMemory.Apply(map[ids.ID]*atomic.Requests{vm.ctx.XChainID: {RemoveRequests: [][]byte{inputID[:]}}}); err != nil {
  1324  		t.Fatal(err)
  1325  	}
  1326  
  1327  	if err := blk.Verify(); err != nil {
  1328  		t.Fatal(err)
  1329  	}
  1330  
  1331  	if status := blk.Status(); status != choices.Processing {
  1332  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
  1333  	}
  1334  
  1335  	if err := vm.SetPreference(blk.ID()); err != nil {
  1336  		t.Fatal(err)
  1337  	}
  1338  
  1339  	if err := blk.Accept(); err != nil {
  1340  		t.Fatal(err)
  1341  	}
  1342  
  1343  	if status := blk.Status(); status != choices.Accepted {
  1344  		t.Fatalf("Expected status of accepted block to be %s, but found %s", choices.Accepted, status)
  1345  	}
  1346  
  1347  	lastAcceptedID, err := vm.LastAccepted()
  1348  	if err != nil {
  1349  		t.Fatal(err)
  1350  	}
  1351  	if lastAcceptedID != blk.ID() {
  1352  		t.Fatalf("Expected last accepted blockID to be the accepted block: %s, but found %s", blk.ID(), lastAcceptedID)
  1353  	}
  1354  }
  1355  
  1356  // Regression test to ensure that a VM that accepts block A and B
  1357  // will not attempt to orphan either when verifying blocks C and D
  1358  // from another VM (which have a common ancestor under the finalized
  1359  // frontier).
  1360  //   A
  1361  //  / \
  1362  // B   C
  1363  //
  1364  // verifies block B and C, then Accepts block B. Then we test to ensure
  1365  // that the VM defends against any attempt to set the preference or to
  1366  // accept block C, which should be an orphaned block at this point and
  1367  // get rejected.
  1368  func TestReorgProtection(t *testing.T) {
  1369  	issuer1, vm1, _, sharedMemory1 := GenesisVM(t, true, genesisJSONApricotPhase0, "{\"pruning-enabled\":false}", "")
  1370  	issuer2, vm2, _, sharedMemory2 := GenesisVM(t, true, genesisJSONApricotPhase0, "{\"pruning-enabled\":false}", "")
  1371  
  1372  	defer func() {
  1373  		if err := vm1.Shutdown(); err != nil {
  1374  			t.Fatal(err)
  1375  		}
  1376  
  1377  		if err := vm2.Shutdown(); err != nil {
  1378  			t.Fatal(err)
  1379  		}
  1380  	}()
  1381  
  1382  	newTxPoolHeadChan1 := make(chan core.NewTxPoolReorgEvent, 1)
  1383  	vm1.chain.GetTxPool().SubscribeNewReorgEvent(newTxPoolHeadChan1)
  1384  	newTxPoolHeadChan2 := make(chan core.NewTxPoolReorgEvent, 1)
  1385  	vm2.chain.GetTxPool().SubscribeNewReorgEvent(newTxPoolHeadChan2)
  1386  
  1387  	key, err := accountKeystore.NewKey(rand.Reader)
  1388  	if err != nil {
  1389  		t.Fatal(err)
  1390  	}
  1391  
  1392  	// Import 1 AVAX
  1393  	importAmount := uint64(1000000000)
  1394  	utxoID := avax.UTXOID{
  1395  		TxID: ids.ID{
  1396  			0x0f, 0x2f, 0x4f, 0x6f, 0x8e, 0xae, 0xce, 0xee,
  1397  			0x0d, 0x2d, 0x4d, 0x6d, 0x8c, 0xac, 0xcc, 0xec,
  1398  			0x0b, 0x2b, 0x4b, 0x6b, 0x8a, 0xaa, 0xca, 0xea,
  1399  			0x09, 0x29, 0x49, 0x69, 0x88, 0xa8, 0xc8, 0xe8,
  1400  		},
  1401  	}
  1402  
  1403  	utxo := &avax.UTXO{
  1404  		UTXOID: utxoID,
  1405  		Asset:  avax.Asset{ID: vm1.ctx.AVAXAssetID},
  1406  		Out: &secp256k1fx.TransferOutput{
  1407  			Amt: importAmount,
  1408  			OutputOwners: secp256k1fx.OutputOwners{
  1409  				Threshold: 1,
  1410  				Addrs:     []ids.ShortID{testKeys[0].PublicKey().Address()},
  1411  			},
  1412  		},
  1413  	}
  1414  	utxoBytes, err := vm1.codec.Marshal(codecVersion, utxo)
  1415  	if err != nil {
  1416  		t.Fatal(err)
  1417  	}
  1418  
  1419  	xChainSharedMemory1 := sharedMemory1.NewSharedMemory(vm1.ctx.XChainID)
  1420  	xChainSharedMemory2 := sharedMemory2.NewSharedMemory(vm2.ctx.XChainID)
  1421  	inputID := utxo.InputID()
  1422  	if err := xChainSharedMemory1.Apply(map[ids.ID]*atomic.Requests{vm1.ctx.ChainID: {PutRequests: []*atomic.Element{{
  1423  		Key:   inputID[:],
  1424  		Value: utxoBytes,
  1425  		Traits: [][]byte{
  1426  			testKeys[0].PublicKey().Address().Bytes(),
  1427  		},
  1428  	}}}}); err != nil {
  1429  		t.Fatal(err)
  1430  	}
  1431  	if err := xChainSharedMemory2.Apply(map[ids.ID]*atomic.Requests{vm2.ctx.ChainID: {PutRequests: []*atomic.Element{{
  1432  		Key:   inputID[:],
  1433  		Value: utxoBytes,
  1434  		Traits: [][]byte{
  1435  			testKeys[0].PublicKey().Address().Bytes(),
  1436  		},
  1437  	}}}}); err != nil {
  1438  		t.Fatal(err)
  1439  	}
  1440  
  1441  	importTx, err := vm1.newImportTx(vm1.ctx.XChainID, key.Address, initialBaseFee, []*crypto.PrivateKeySECP256K1R{testKeys[0]})
  1442  	if err != nil {
  1443  		t.Fatal(err)
  1444  	}
  1445  
  1446  	if err := vm1.issueTx(importTx); err != nil {
  1447  		t.Fatal(err)
  1448  	}
  1449  
  1450  	<-issuer1
  1451  
  1452  	vm1BlkA, err := vm1.BuildBlock()
  1453  	if err != nil {
  1454  		t.Fatalf("Failed to build block with import transaction: %s", err)
  1455  	}
  1456  
  1457  	if err := vm1BlkA.Verify(); err != nil {
  1458  		t.Fatalf("Block failed verification on VM1: %s", err)
  1459  	}
  1460  
  1461  	if status := vm1BlkA.Status(); status != choices.Processing {
  1462  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
  1463  	}
  1464  
  1465  	if err := vm1.SetPreference(vm1BlkA.ID()); err != nil {
  1466  		t.Fatal(err)
  1467  	}
  1468  
  1469  	vm2BlkA, err := vm2.ParseBlock(vm1BlkA.Bytes())
  1470  	if err != nil {
  1471  		t.Fatalf("Unexpected error parsing block from vm2: %s", err)
  1472  	}
  1473  	if err := vm2BlkA.Verify(); err != nil {
  1474  		t.Fatalf("Block failed verification on VM2: %s", err)
  1475  	}
  1476  	if status := vm2BlkA.Status(); status != choices.Processing {
  1477  		t.Fatalf("Expected status of block on VM2 to be %s, but found %s", choices.Processing, status)
  1478  	}
  1479  	if err := vm2.SetPreference(vm2BlkA.ID()); err != nil {
  1480  		t.Fatal(err)
  1481  	}
  1482  
  1483  	if err := vm1BlkA.Accept(); err != nil {
  1484  		t.Fatalf("VM1 failed to accept block: %s", err)
  1485  	}
  1486  	if err := vm2BlkA.Accept(); err != nil {
  1487  		t.Fatalf("VM2 failed to accept block: %s", err)
  1488  	}
  1489  
  1490  	newHead := <-newTxPoolHeadChan1
  1491  	if newHead.Head.Hash() != common.Hash(vm1BlkA.ID()) {
  1492  		t.Fatalf("Expected new block to match")
  1493  	}
  1494  	newHead = <-newTxPoolHeadChan2
  1495  	if newHead.Head.Hash() != common.Hash(vm2BlkA.ID()) {
  1496  		t.Fatalf("Expected new block to match")
  1497  	}
  1498  
  1499  	// Create list of 10 successive transactions to build block A on vm1
  1500  	// and to be split into two separate blocks on VM2
  1501  	txs := make([]*types.Transaction, 10)
  1502  	for i := 0; i < 10; i++ {
  1503  		tx := types.NewTransaction(uint64(i), key.Address, big.NewInt(10), 21000, big.NewInt(params.LaunchMinGasPrice), nil)
  1504  		signedTx, err := types.SignTx(tx, types.NewEIP155Signer(vm1.chainID), key.PrivateKey)
  1505  		if err != nil {
  1506  			t.Fatal(err)
  1507  		}
  1508  		txs[i] = signedTx
  1509  	}
  1510  
  1511  	var errs []error
  1512  
  1513  	// Add the remote transactions, build the block, and set VM1's preference for block A
  1514  	errs = vm1.chain.AddRemoteTxs(txs)
  1515  	for i, err := range errs {
  1516  		if err != nil {
  1517  			t.Fatalf("Failed to add transaction to VM1 at index %d: %s", i, err)
  1518  		}
  1519  	}
  1520  
  1521  	<-issuer1
  1522  
  1523  	vm1BlkB, err := vm1.BuildBlock()
  1524  	if err != nil {
  1525  		t.Fatal(err)
  1526  	}
  1527  
  1528  	if err := vm1BlkB.Verify(); err != nil {
  1529  		t.Fatal(err)
  1530  	}
  1531  
  1532  	if status := vm1BlkB.Status(); status != choices.Processing {
  1533  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
  1534  	}
  1535  
  1536  	if err := vm1.SetPreference(vm1BlkB.ID()); err != nil {
  1537  		t.Fatal(err)
  1538  	}
  1539  
  1540  	// Split the transactions over two blocks, and set VM2's preference to them in sequence
  1541  	// after building each block
  1542  	// Block C
  1543  	errs = vm2.chain.AddRemoteTxs(txs[0:5])
  1544  	for i, err := range errs {
  1545  		if err != nil {
  1546  			t.Fatalf("Failed to add transaction to VM2 at index %d: %s", i, err)
  1547  		}
  1548  	}
  1549  
  1550  	<-issuer2
  1551  	vm2BlkC, err := vm2.BuildBlock()
  1552  	if err != nil {
  1553  		t.Fatalf("Failed to build BlkC on VM2: %s", err)
  1554  	}
  1555  
  1556  	if err := vm2BlkC.Verify(); err != nil {
  1557  		t.Fatalf("Block failed verification on VM2: %s", err)
  1558  	}
  1559  	if status := vm2BlkC.Status(); status != choices.Processing {
  1560  		t.Fatalf("Expected status of block on VM2 to be %s, but found %s", choices.Processing, status)
  1561  	}
  1562  
  1563  	vm1BlkC, err := vm1.ParseBlock(vm2BlkC.Bytes())
  1564  	if err != nil {
  1565  		t.Fatalf("Unexpected error parsing block from vm2: %s", err)
  1566  	}
  1567  
  1568  	if err := vm1BlkC.Verify(); err != nil {
  1569  		t.Fatalf("Block failed verification on VM1: %s", err)
  1570  	}
  1571  
  1572  	// Accept B, such that block C should get Rejected.
  1573  	if err := vm1BlkB.Accept(); err != nil {
  1574  		t.Fatalf("VM1 failed to accept block: %s", err)
  1575  	}
  1576  
  1577  	// The below (setting preference blocks that have a common ancestor
  1578  	// with the preferred chain lower than the last finalized block)
  1579  	// should NEVER happen. However, the VM defends against this
  1580  	// just in case.
  1581  	if err := vm1.SetPreference(vm1BlkC.ID()); !strings.Contains(err.Error(), "cannot orphan finalized block") {
  1582  		t.Fatalf("Unexpected error when setting preference that would trigger reorg: %s", err)
  1583  	}
  1584  
  1585  	if err := vm1BlkC.Accept(); !strings.Contains(err.Error(), "expected accepted block to have parent") {
  1586  		t.Fatalf("Unexpected error when setting block at finalized height: %s", err)
  1587  	}
  1588  }
  1589  
  1590  // Regression test to ensure that a VM that accepts block C while preferring
  1591  // block B will trigger a reorg.
  1592  //   A
  1593  //  / \
  1594  // B   C
  1595  func TestNonCanonicalAccept(t *testing.T) {
  1596  	issuer1, vm1, _, sharedMemory1 := GenesisVM(t, true, genesisJSONApricotPhase0, "", "")
  1597  	issuer2, vm2, _, sharedMemory2 := GenesisVM(t, true, genesisJSONApricotPhase0, "", "")
  1598  
  1599  	defer func() {
  1600  		if err := vm1.Shutdown(); err != nil {
  1601  			t.Fatal(err)
  1602  		}
  1603  
  1604  		if err := vm2.Shutdown(); err != nil {
  1605  			t.Fatal(err)
  1606  		}
  1607  	}()
  1608  
  1609  	newTxPoolHeadChan1 := make(chan core.NewTxPoolReorgEvent, 1)
  1610  	vm1.chain.GetTxPool().SubscribeNewReorgEvent(newTxPoolHeadChan1)
  1611  	newTxPoolHeadChan2 := make(chan core.NewTxPoolReorgEvent, 1)
  1612  	vm2.chain.GetTxPool().SubscribeNewReorgEvent(newTxPoolHeadChan2)
  1613  
  1614  	key, err := accountKeystore.NewKey(rand.Reader)
  1615  	if err != nil {
  1616  		t.Fatal(err)
  1617  	}
  1618  
  1619  	// Import 1 AVAX
  1620  	importAmount := uint64(1000000000)
  1621  	utxoID := avax.UTXOID{
  1622  		TxID: ids.ID{
  1623  			0x0f, 0x2f, 0x4f, 0x6f, 0x8e, 0xae, 0xce, 0xee,
  1624  			0x0d, 0x2d, 0x4d, 0x6d, 0x8c, 0xac, 0xcc, 0xec,
  1625  			0x0b, 0x2b, 0x4b, 0x6b, 0x8a, 0xaa, 0xca, 0xea,
  1626  			0x09, 0x29, 0x49, 0x69, 0x88, 0xa8, 0xc8, 0xe8,
  1627  		},
  1628  	}
  1629  
  1630  	utxo := &avax.UTXO{
  1631  		UTXOID: utxoID,
  1632  		Asset:  avax.Asset{ID: vm1.ctx.AVAXAssetID},
  1633  		Out: &secp256k1fx.TransferOutput{
  1634  			Amt: importAmount,
  1635  			OutputOwners: secp256k1fx.OutputOwners{
  1636  				Threshold: 1,
  1637  				Addrs:     []ids.ShortID{testKeys[0].PublicKey().Address()},
  1638  			},
  1639  		},
  1640  	}
  1641  	utxoBytes, err := vm1.codec.Marshal(codecVersion, utxo)
  1642  	if err != nil {
  1643  		t.Fatal(err)
  1644  	}
  1645  
  1646  	xChainSharedMemory1 := sharedMemory1.NewSharedMemory(vm1.ctx.XChainID)
  1647  	xChainSharedMemory2 := sharedMemory2.NewSharedMemory(vm2.ctx.XChainID)
  1648  	inputID := utxo.InputID()
  1649  	if err := xChainSharedMemory1.Apply(map[ids.ID]*atomic.Requests{vm1.ctx.ChainID: {PutRequests: []*atomic.Element{{
  1650  		Key:   inputID[:],
  1651  		Value: utxoBytes,
  1652  		Traits: [][]byte{
  1653  			testKeys[0].PublicKey().Address().Bytes(),
  1654  		},
  1655  	}}}}); err != nil {
  1656  		t.Fatal(err)
  1657  	}
  1658  	if err := xChainSharedMemory2.Apply(map[ids.ID]*atomic.Requests{vm2.ctx.ChainID: {PutRequests: []*atomic.Element{{
  1659  		Key:   inputID[:],
  1660  		Value: utxoBytes,
  1661  		Traits: [][]byte{
  1662  			testKeys[0].PublicKey().Address().Bytes(),
  1663  		},
  1664  	}}}}); err != nil {
  1665  		t.Fatal(err)
  1666  	}
  1667  
  1668  	importTx, err := vm1.newImportTx(vm1.ctx.XChainID, key.Address, initialBaseFee, []*crypto.PrivateKeySECP256K1R{testKeys[0]})
  1669  	if err != nil {
  1670  		t.Fatal(err)
  1671  	}
  1672  
  1673  	if err := vm1.issueTx(importTx); err != nil {
  1674  		t.Fatal(err)
  1675  	}
  1676  
  1677  	<-issuer1
  1678  
  1679  	vm1BlkA, err := vm1.BuildBlock()
  1680  	if err != nil {
  1681  		t.Fatalf("Failed to build block with import transaction: %s", err)
  1682  	}
  1683  
  1684  	if err := vm1BlkA.Verify(); err != nil {
  1685  		t.Fatalf("Block failed verification on VM1: %s", err)
  1686  	}
  1687  
  1688  	if status := vm1BlkA.Status(); status != choices.Processing {
  1689  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
  1690  	}
  1691  
  1692  	if err := vm1.SetPreference(vm1BlkA.ID()); err != nil {
  1693  		t.Fatal(err)
  1694  	}
  1695  
  1696  	vm2BlkA, err := vm2.ParseBlock(vm1BlkA.Bytes())
  1697  	if err != nil {
  1698  		t.Fatalf("Unexpected error parsing block from vm2: %s", err)
  1699  	}
  1700  	if err := vm2BlkA.Verify(); err != nil {
  1701  		t.Fatalf("Block failed verification on VM2: %s", err)
  1702  	}
  1703  	if status := vm2BlkA.Status(); status != choices.Processing {
  1704  		t.Fatalf("Expected status of block on VM2 to be %s, but found %s", choices.Processing, status)
  1705  	}
  1706  	if err := vm2.SetPreference(vm2BlkA.ID()); err != nil {
  1707  		t.Fatal(err)
  1708  	}
  1709  
  1710  	if err := vm1BlkA.Accept(); err != nil {
  1711  		t.Fatalf("VM1 failed to accept block: %s", err)
  1712  	}
  1713  	if err := vm2BlkA.Accept(); err != nil {
  1714  		t.Fatalf("VM2 failed to accept block: %s", err)
  1715  	}
  1716  
  1717  	newHead := <-newTxPoolHeadChan1
  1718  	if newHead.Head.Hash() != common.Hash(vm1BlkA.ID()) {
  1719  		t.Fatalf("Expected new block to match")
  1720  	}
  1721  	newHead = <-newTxPoolHeadChan2
  1722  	if newHead.Head.Hash() != common.Hash(vm2BlkA.ID()) {
  1723  		t.Fatalf("Expected new block to match")
  1724  	}
  1725  
  1726  	// Create list of 10 successive transactions to build block A on vm1
  1727  	// and to be split into two separate blocks on VM2
  1728  	txs := make([]*types.Transaction, 10)
  1729  	for i := 0; i < 10; i++ {
  1730  		tx := types.NewTransaction(uint64(i), key.Address, big.NewInt(10), 21000, big.NewInt(params.LaunchMinGasPrice), nil)
  1731  		signedTx, err := types.SignTx(tx, types.NewEIP155Signer(vm1.chainID), key.PrivateKey)
  1732  		if err != nil {
  1733  			t.Fatal(err)
  1734  		}
  1735  		txs[i] = signedTx
  1736  	}
  1737  
  1738  	var errs []error
  1739  
  1740  	// Add the remote transactions, build the block, and set VM1's preference for block A
  1741  	errs = vm1.chain.AddRemoteTxs(txs)
  1742  	for i, err := range errs {
  1743  		if err != nil {
  1744  			t.Fatalf("Failed to add transaction to VM1 at index %d: %s", i, err)
  1745  		}
  1746  	}
  1747  
  1748  	<-issuer1
  1749  
  1750  	vm1BlkB, err := vm1.BuildBlock()
  1751  	if err != nil {
  1752  		t.Fatal(err)
  1753  	}
  1754  
  1755  	if err := vm1BlkB.Verify(); err != nil {
  1756  		t.Fatal(err)
  1757  	}
  1758  
  1759  	if status := vm1BlkB.Status(); status != choices.Processing {
  1760  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
  1761  	}
  1762  
  1763  	if err := vm1.SetPreference(vm1BlkB.ID()); err != nil {
  1764  		t.Fatal(err)
  1765  	}
  1766  
  1767  	vm1.chain.BlockChain().GetVMConfig().AllowUnfinalizedQueries = true
  1768  
  1769  	blkBHeight := vm1BlkB.Height()
  1770  	blkBHash := vm1BlkB.(*chain.BlockWrapper).Block.(*Block).ethBlock.Hash()
  1771  	if b := vm1.chain.GetBlockByNumber(blkBHeight); b.Hash() != blkBHash {
  1772  		t.Fatalf("expected block at %d to have hash %s but got %s", blkBHeight, blkBHash.Hex(), b.Hash().Hex())
  1773  	}
  1774  
  1775  	errs = vm2.chain.AddRemoteTxs(txs[0:5])
  1776  	for i, err := range errs {
  1777  		if err != nil {
  1778  			t.Fatalf("Failed to add transaction to VM2 at index %d: %s", i, err)
  1779  		}
  1780  	}
  1781  
  1782  	<-issuer2
  1783  	vm2BlkC, err := vm2.BuildBlock()
  1784  	if err != nil {
  1785  		t.Fatalf("Failed to build BlkC on VM2: %s", err)
  1786  	}
  1787  
  1788  	vm1BlkC, err := vm1.ParseBlock(vm2BlkC.Bytes())
  1789  	if err != nil {
  1790  		t.Fatalf("Unexpected error parsing block from vm2: %s", err)
  1791  	}
  1792  
  1793  	if err := vm1BlkC.Verify(); err != nil {
  1794  		t.Fatalf("Block failed verification on VM1: %s", err)
  1795  	}
  1796  
  1797  	if err := vm1BlkC.Accept(); err != nil {
  1798  		t.Fatalf("VM1 failed to accept block: %s", err)
  1799  	}
  1800  
  1801  	blkCHash := vm1BlkC.(*chain.BlockWrapper).Block.(*Block).ethBlock.Hash()
  1802  	if b := vm1.chain.GetBlockByNumber(blkBHeight); b.Hash() != blkCHash {
  1803  		t.Fatalf("expected block at %d to have hash %s but got %s", blkBHeight, blkCHash.Hex(), b.Hash().Hex())
  1804  	}
  1805  }
  1806  
  1807  // Regression test to ensure that a VM that verifies block B, C, then
  1808  // D (preferring block B) does not trigger a reorg through the re-verification
  1809  // of block C or D.
  1810  //   A
  1811  //  / \
  1812  // B   C
  1813  //     |
  1814  //     D
  1815  func TestStickyPreference(t *testing.T) {
  1816  	issuer1, vm1, _, sharedMemory1 := GenesisVM(t, true, genesisJSONApricotPhase0, "", "")
  1817  	issuer2, vm2, _, sharedMemory2 := GenesisVM(t, true, genesisJSONApricotPhase0, "", "")
  1818  
  1819  	defer func() {
  1820  		if err := vm1.Shutdown(); err != nil {
  1821  			t.Fatal(err)
  1822  		}
  1823  
  1824  		if err := vm2.Shutdown(); err != nil {
  1825  			t.Fatal(err)
  1826  		}
  1827  	}()
  1828  
  1829  	newTxPoolHeadChan1 := make(chan core.NewTxPoolReorgEvent, 1)
  1830  	vm1.chain.GetTxPool().SubscribeNewReorgEvent(newTxPoolHeadChan1)
  1831  	newTxPoolHeadChan2 := make(chan core.NewTxPoolReorgEvent, 1)
  1832  	vm2.chain.GetTxPool().SubscribeNewReorgEvent(newTxPoolHeadChan2)
  1833  
  1834  	key, err := accountKeystore.NewKey(rand.Reader)
  1835  	if err != nil {
  1836  		t.Fatal(err)
  1837  	}
  1838  
  1839  	// Import 1 AVAX
  1840  	importAmount := uint64(1000000000)
  1841  	utxoID := avax.UTXOID{
  1842  		TxID: ids.ID{
  1843  			0x0f, 0x2f, 0x4f, 0x6f, 0x8e, 0xae, 0xce, 0xee,
  1844  			0x0d, 0x2d, 0x4d, 0x6d, 0x8c, 0xac, 0xcc, 0xec,
  1845  			0x0b, 0x2b, 0x4b, 0x6b, 0x8a, 0xaa, 0xca, 0xea,
  1846  			0x09, 0x29, 0x49, 0x69, 0x88, 0xa8, 0xc8, 0xe8,
  1847  		},
  1848  	}
  1849  
  1850  	utxo := &avax.UTXO{
  1851  		UTXOID: utxoID,
  1852  		Asset:  avax.Asset{ID: vm1.ctx.AVAXAssetID},
  1853  		Out: &secp256k1fx.TransferOutput{
  1854  			Amt: importAmount,
  1855  			OutputOwners: secp256k1fx.OutputOwners{
  1856  				Threshold: 1,
  1857  				Addrs:     []ids.ShortID{testKeys[0].PublicKey().Address()},
  1858  			},
  1859  		},
  1860  	}
  1861  	utxoBytes, err := vm1.codec.Marshal(codecVersion, utxo)
  1862  	if err != nil {
  1863  		t.Fatal(err)
  1864  	}
  1865  
  1866  	xChainSharedMemory1 := sharedMemory1.NewSharedMemory(vm1.ctx.XChainID)
  1867  	xChainSharedMemory2 := sharedMemory2.NewSharedMemory(vm2.ctx.XChainID)
  1868  	inputID := utxo.InputID()
  1869  	if err := xChainSharedMemory1.Apply(map[ids.ID]*atomic.Requests{vm1.ctx.ChainID: {PutRequests: []*atomic.Element{{
  1870  		Key:   inputID[:],
  1871  		Value: utxoBytes,
  1872  		Traits: [][]byte{
  1873  			testKeys[0].PublicKey().Address().Bytes(),
  1874  		},
  1875  	}}}}); err != nil {
  1876  		t.Fatal(err)
  1877  	}
  1878  	if err := xChainSharedMemory2.Apply(map[ids.ID]*atomic.Requests{vm2.ctx.ChainID: {PutRequests: []*atomic.Element{{
  1879  		Key:   inputID[:],
  1880  		Value: utxoBytes,
  1881  		Traits: [][]byte{
  1882  			testKeys[0].PublicKey().Address().Bytes(),
  1883  		},
  1884  	}}}}); err != nil {
  1885  		t.Fatal(err)
  1886  	}
  1887  
  1888  	importTx, err := vm1.newImportTx(vm1.ctx.XChainID, key.Address, initialBaseFee, []*crypto.PrivateKeySECP256K1R{testKeys[0]})
  1889  	if err != nil {
  1890  		t.Fatal(err)
  1891  	}
  1892  
  1893  	if err := vm1.issueTx(importTx); err != nil {
  1894  		t.Fatal(err)
  1895  	}
  1896  
  1897  	<-issuer1
  1898  
  1899  	vm1BlkA, err := vm1.BuildBlock()
  1900  	if err != nil {
  1901  		t.Fatalf("Failed to build block with import transaction: %s", err)
  1902  	}
  1903  
  1904  	if err := vm1BlkA.Verify(); err != nil {
  1905  		t.Fatalf("Block failed verification on VM1: %s", err)
  1906  	}
  1907  
  1908  	if status := vm1BlkA.Status(); status != choices.Processing {
  1909  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
  1910  	}
  1911  
  1912  	if err := vm1.SetPreference(vm1BlkA.ID()); err != nil {
  1913  		t.Fatal(err)
  1914  	}
  1915  
  1916  	vm2BlkA, err := vm2.ParseBlock(vm1BlkA.Bytes())
  1917  	if err != nil {
  1918  		t.Fatalf("Unexpected error parsing block from vm2: %s", err)
  1919  	}
  1920  	if err := vm2BlkA.Verify(); err != nil {
  1921  		t.Fatalf("Block failed verification on VM2: %s", err)
  1922  	}
  1923  	if status := vm2BlkA.Status(); status != choices.Processing {
  1924  		t.Fatalf("Expected status of block on VM2 to be %s, but found %s", choices.Processing, status)
  1925  	}
  1926  	if err := vm2.SetPreference(vm2BlkA.ID()); err != nil {
  1927  		t.Fatal(err)
  1928  	}
  1929  
  1930  	if err := vm1BlkA.Accept(); err != nil {
  1931  		t.Fatalf("VM1 failed to accept block: %s", err)
  1932  	}
  1933  	if err := vm2BlkA.Accept(); err != nil {
  1934  		t.Fatalf("VM2 failed to accept block: %s", err)
  1935  	}
  1936  
  1937  	newHead := <-newTxPoolHeadChan1
  1938  	if newHead.Head.Hash() != common.Hash(vm1BlkA.ID()) {
  1939  		t.Fatalf("Expected new block to match")
  1940  	}
  1941  	newHead = <-newTxPoolHeadChan2
  1942  	if newHead.Head.Hash() != common.Hash(vm2BlkA.ID()) {
  1943  		t.Fatalf("Expected new block to match")
  1944  	}
  1945  
  1946  	// Create list of 10 successive transactions to build block A on vm1
  1947  	// and to be split into two separate blocks on VM2
  1948  	txs := make([]*types.Transaction, 10)
  1949  	for i := 0; i < 10; i++ {
  1950  		tx := types.NewTransaction(uint64(i), key.Address, big.NewInt(10), 21000, big.NewInt(params.LaunchMinGasPrice), nil)
  1951  		signedTx, err := types.SignTx(tx, types.NewEIP155Signer(vm1.chainID), key.PrivateKey)
  1952  		if err != nil {
  1953  			t.Fatal(err)
  1954  		}
  1955  		txs[i] = signedTx
  1956  	}
  1957  
  1958  	var errs []error
  1959  
  1960  	// Add the remote transactions, build the block, and set VM1's preference for block A
  1961  	errs = vm1.chain.AddRemoteTxs(txs)
  1962  	for i, err := range errs {
  1963  		if err != nil {
  1964  			t.Fatalf("Failed to add transaction to VM1 at index %d: %s", i, err)
  1965  		}
  1966  	}
  1967  
  1968  	<-issuer1
  1969  
  1970  	vm1BlkB, err := vm1.BuildBlock()
  1971  	if err != nil {
  1972  		t.Fatal(err)
  1973  	}
  1974  
  1975  	if err := vm1BlkB.Verify(); err != nil {
  1976  		t.Fatal(err)
  1977  	}
  1978  
  1979  	if status := vm1BlkB.Status(); status != choices.Processing {
  1980  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
  1981  	}
  1982  
  1983  	if err := vm1.SetPreference(vm1BlkB.ID()); err != nil {
  1984  		t.Fatal(err)
  1985  	}
  1986  
  1987  	vm1.chain.BlockChain().GetVMConfig().AllowUnfinalizedQueries = true
  1988  
  1989  	blkBHeight := vm1BlkB.Height()
  1990  	blkBHash := vm1BlkB.(*chain.BlockWrapper).Block.(*Block).ethBlock.Hash()
  1991  	if b := vm1.chain.GetBlockByNumber(blkBHeight); b.Hash() != blkBHash {
  1992  		t.Fatalf("expected block at %d to have hash %s but got %s", blkBHeight, blkBHash.Hex(), b.Hash().Hex())
  1993  	}
  1994  
  1995  	errs = vm2.chain.AddRemoteTxs(txs[0:5])
  1996  	for i, err := range errs {
  1997  		if err != nil {
  1998  			t.Fatalf("Failed to add transaction to VM2 at index %d: %s", i, err)
  1999  		}
  2000  	}
  2001  
  2002  	<-issuer2
  2003  	vm2BlkC, err := vm2.BuildBlock()
  2004  	if err != nil {
  2005  		t.Fatalf("Failed to build BlkC on VM2: %s", err)
  2006  	}
  2007  
  2008  	if err := vm2BlkC.Verify(); err != nil {
  2009  		t.Fatalf("BlkC failed verification on VM2: %s", err)
  2010  	}
  2011  
  2012  	if status := vm2BlkC.Status(); status != choices.Processing {
  2013  		t.Fatalf("Expected status of built block C to be %s, but found %s", choices.Processing, status)
  2014  	}
  2015  
  2016  	if err := vm2.SetPreference(vm2BlkC.ID()); err != nil {
  2017  		t.Fatal(err)
  2018  	}
  2019  
  2020  	newHead = <-newTxPoolHeadChan2
  2021  	if newHead.Head.Hash() != common.Hash(vm2BlkC.ID()) {
  2022  		t.Fatalf("Expected new block to match")
  2023  	}
  2024  
  2025  	errs = vm2.chain.AddRemoteTxs(txs[5:])
  2026  	for i, err := range errs {
  2027  		if err != nil {
  2028  			t.Fatalf("Failed to add transaction to VM2 at index %d: %s", i, err)
  2029  		}
  2030  	}
  2031  
  2032  	<-issuer2
  2033  	vm2BlkD, err := vm2.BuildBlock()
  2034  	if err != nil {
  2035  		t.Fatalf("Failed to build BlkD on VM2: %s", err)
  2036  	}
  2037  
  2038  	// Parse blocks produced in vm2
  2039  	vm1BlkC, err := vm1.ParseBlock(vm2BlkC.Bytes())
  2040  	if err != nil {
  2041  		t.Fatalf("Unexpected error parsing block from vm2: %s", err)
  2042  	}
  2043  	blkCHash := vm1BlkC.(*chain.BlockWrapper).Block.(*Block).ethBlock.Hash()
  2044  
  2045  	vm1BlkD, err := vm1.ParseBlock(vm2BlkD.Bytes())
  2046  	if err != nil {
  2047  		t.Fatalf("Unexpected error parsing block from vm2: %s", err)
  2048  	}
  2049  	blkDHeight := vm1BlkD.Height()
  2050  	blkDHash := vm1BlkD.(*chain.BlockWrapper).Block.(*Block).ethBlock.Hash()
  2051  
  2052  	// Should be no-ops
  2053  	if err := vm1BlkC.Verify(); err != nil {
  2054  		t.Fatalf("Block failed verification on VM1: %s", err)
  2055  	}
  2056  	if err := vm1BlkD.Verify(); err != nil {
  2057  		t.Fatalf("Block failed verification on VM1: %s", err)
  2058  	}
  2059  	if b := vm1.chain.GetBlockByNumber(blkBHeight); b.Hash() != blkBHash {
  2060  		t.Fatalf("expected block at %d to have hash %s but got %s", blkBHeight, blkBHash.Hex(), b.Hash().Hex())
  2061  	}
  2062  	if b := vm1.chain.GetBlockByNumber(blkDHeight); b != nil {
  2063  		t.Fatalf("expected block at %d to be nil but got %s", blkDHeight, b.Hash().Hex())
  2064  	}
  2065  	if b := vm1.chain.BlockChain().CurrentBlock(); b.Hash() != blkBHash {
  2066  		t.Fatalf("expected current block to have hash %s but got %s", blkBHash.Hex(), b.Hash().Hex())
  2067  	}
  2068  
  2069  	// Should still be no-ops on re-verify
  2070  	if err := vm1BlkC.Verify(); err != nil {
  2071  		t.Fatalf("Block failed verification on VM1: %s", err)
  2072  	}
  2073  	if err := vm1BlkD.Verify(); err != nil {
  2074  		t.Fatalf("Block failed verification on VM1: %s", err)
  2075  	}
  2076  	if b := vm1.chain.GetBlockByNumber(blkBHeight); b.Hash() != blkBHash {
  2077  		t.Fatalf("expected block at %d to have hash %s but got %s", blkBHeight, blkBHash.Hex(), b.Hash().Hex())
  2078  	}
  2079  	if b := vm1.chain.GetBlockByNumber(blkDHeight); b != nil {
  2080  		t.Fatalf("expected block at %d to be nil but got %s", blkDHeight, b.Hash().Hex())
  2081  	}
  2082  	if b := vm1.chain.BlockChain().CurrentBlock(); b.Hash() != blkBHash {
  2083  		t.Fatalf("expected current block to have hash %s but got %s", blkBHash.Hex(), b.Hash().Hex())
  2084  	}
  2085  
  2086  	// Should be queryable after setting preference to side chain
  2087  	if err := vm1.SetPreference(vm1BlkD.ID()); err != nil {
  2088  		t.Fatal(err)
  2089  	}
  2090  
  2091  	if b := vm1.chain.GetBlockByNumber(blkBHeight); b.Hash() != blkCHash {
  2092  		t.Fatalf("expected block at %d to have hash %s but got %s", blkBHeight, blkCHash.Hex(), b.Hash().Hex())
  2093  	}
  2094  	if b := vm1.chain.GetBlockByNumber(blkDHeight); b.Hash() != blkDHash {
  2095  		t.Fatalf("expected block at %d to have hash %s but got %s", blkDHeight, blkDHash.Hex(), b.Hash().Hex())
  2096  	}
  2097  	if b := vm1.chain.BlockChain().CurrentBlock(); b.Hash() != blkDHash {
  2098  		t.Fatalf("expected current block to have hash %s but got %s", blkDHash.Hex(), b.Hash().Hex())
  2099  	}
  2100  
  2101  	// Attempt to accept out of order
  2102  	if err := vm1BlkD.Accept(); !strings.Contains(err.Error(), "expected accepted block to have parent") {
  2103  		t.Fatalf("unexpected error when accepting out of order block: %s", err)
  2104  	}
  2105  
  2106  	// Accept in order
  2107  	if err := vm1BlkC.Accept(); err != nil {
  2108  		t.Fatalf("Block failed verification on VM1: %s", err)
  2109  	}
  2110  	if err := vm1BlkD.Accept(); err != nil {
  2111  		t.Fatalf("Block failed acceptance on VM1: %s", err)
  2112  	}
  2113  
  2114  	// Ensure queryable after accepting
  2115  	if b := vm1.chain.GetBlockByNumber(blkBHeight); b.Hash() != blkCHash {
  2116  		t.Fatalf("expected block at %d to have hash %s but got %s", blkBHeight, blkCHash.Hex(), b.Hash().Hex())
  2117  	}
  2118  	if b := vm1.chain.GetBlockByNumber(blkDHeight); b.Hash() != blkDHash {
  2119  		t.Fatalf("expected block at %d to have hash %s but got %s", blkDHeight, blkDHash.Hex(), b.Hash().Hex())
  2120  	}
  2121  	if b := vm1.chain.BlockChain().CurrentBlock(); b.Hash() != blkDHash {
  2122  		t.Fatalf("expected current block to have hash %s but got %s", blkDHash.Hex(), b.Hash().Hex())
  2123  	}
  2124  }
  2125  
  2126  // Regression test to ensure that a VM that prefers block B is able to parse
  2127  // block C but unable to parse block D because it names B as an uncle, which
  2128  // are not supported.
  2129  //   A
  2130  //  / \
  2131  // B   C
  2132  //     |
  2133  //     D
  2134  func TestUncleBlock(t *testing.T) {
  2135  	issuer1, vm1, _, sharedMemory1 := GenesisVM(t, true, genesisJSONApricotPhase0, "", "")
  2136  	issuer2, vm2, _, sharedMemory2 := GenesisVM(t, true, genesisJSONApricotPhase0, "", "")
  2137  
  2138  	defer func() {
  2139  		if err := vm1.Shutdown(); err != nil {
  2140  			t.Fatal(err)
  2141  		}
  2142  		if err := vm2.Shutdown(); err != nil {
  2143  			t.Fatal(err)
  2144  		}
  2145  	}()
  2146  
  2147  	newTxPoolHeadChan1 := make(chan core.NewTxPoolReorgEvent, 1)
  2148  	vm1.chain.GetTxPool().SubscribeNewReorgEvent(newTxPoolHeadChan1)
  2149  	newTxPoolHeadChan2 := make(chan core.NewTxPoolReorgEvent, 1)
  2150  	vm2.chain.GetTxPool().SubscribeNewReorgEvent(newTxPoolHeadChan2)
  2151  
  2152  	key, err := accountKeystore.NewKey(rand.Reader)
  2153  	if err != nil {
  2154  		t.Fatal(err)
  2155  	}
  2156  
  2157  	// Import 1 AVAX
  2158  	importAmount := uint64(1000000000)
  2159  	utxoID := avax.UTXOID{
  2160  		TxID: ids.ID{
  2161  			0x0f, 0x2f, 0x4f, 0x6f, 0x8e, 0xae, 0xce, 0xee,
  2162  			0x0d, 0x2d, 0x4d, 0x6d, 0x8c, 0xac, 0xcc, 0xec,
  2163  			0x0b, 0x2b, 0x4b, 0x6b, 0x8a, 0xaa, 0xca, 0xea,
  2164  			0x09, 0x29, 0x49, 0x69, 0x88, 0xa8, 0xc8, 0xe8,
  2165  		},
  2166  	}
  2167  
  2168  	utxo := &avax.UTXO{
  2169  		UTXOID: utxoID,
  2170  		Asset:  avax.Asset{ID: vm1.ctx.AVAXAssetID},
  2171  		Out: &secp256k1fx.TransferOutput{
  2172  			Amt: importAmount,
  2173  			OutputOwners: secp256k1fx.OutputOwners{
  2174  				Threshold: 1,
  2175  				Addrs:     []ids.ShortID{testKeys[0].PublicKey().Address()},
  2176  			},
  2177  		},
  2178  	}
  2179  	utxoBytes, err := vm1.codec.Marshal(codecVersion, utxo)
  2180  	if err != nil {
  2181  		t.Fatal(err)
  2182  	}
  2183  
  2184  	xChainSharedMemory1 := sharedMemory1.NewSharedMemory(vm1.ctx.XChainID)
  2185  	xChainSharedMemory2 := sharedMemory2.NewSharedMemory(vm2.ctx.XChainID)
  2186  	inputID := utxo.InputID()
  2187  	if err := xChainSharedMemory1.Apply(map[ids.ID]*atomic.Requests{vm1.ctx.ChainID: {PutRequests: []*atomic.Element{{
  2188  		Key:   inputID[:],
  2189  		Value: utxoBytes,
  2190  		Traits: [][]byte{
  2191  			testKeys[0].PublicKey().Address().Bytes(),
  2192  		},
  2193  	}}}}); err != nil {
  2194  		t.Fatal(err)
  2195  	}
  2196  	if err := xChainSharedMemory2.Apply(map[ids.ID]*atomic.Requests{vm2.ctx.ChainID: {PutRequests: []*atomic.Element{{
  2197  		Key:   inputID[:],
  2198  		Value: utxoBytes,
  2199  		Traits: [][]byte{
  2200  			testKeys[0].PublicKey().Address().Bytes(),
  2201  		},
  2202  	}}}}); err != nil {
  2203  		t.Fatal(err)
  2204  	}
  2205  
  2206  	importTx, err := vm1.newImportTx(vm1.ctx.XChainID, key.Address, initialBaseFee, []*crypto.PrivateKeySECP256K1R{testKeys[0]})
  2207  	if err != nil {
  2208  		t.Fatal(err)
  2209  	}
  2210  
  2211  	if err := vm1.issueTx(importTx); err != nil {
  2212  		t.Fatal(err)
  2213  	}
  2214  
  2215  	<-issuer1
  2216  
  2217  	vm1BlkA, err := vm1.BuildBlock()
  2218  	if err != nil {
  2219  		t.Fatalf("Failed to build block with import transaction: %s", err)
  2220  	}
  2221  
  2222  	if err := vm1BlkA.Verify(); err != nil {
  2223  		t.Fatalf("Block failed verification on VM1: %s", err)
  2224  	}
  2225  
  2226  	if status := vm1BlkA.Status(); status != choices.Processing {
  2227  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
  2228  	}
  2229  
  2230  	if err := vm1.SetPreference(vm1BlkA.ID()); err != nil {
  2231  		t.Fatal(err)
  2232  	}
  2233  
  2234  	vm2BlkA, err := vm2.ParseBlock(vm1BlkA.Bytes())
  2235  	if err != nil {
  2236  		t.Fatalf("Unexpected error parsing block from vm2: %s", err)
  2237  	}
  2238  	if err := vm2BlkA.Verify(); err != nil {
  2239  		t.Fatalf("Block failed verification on VM2: %s", err)
  2240  	}
  2241  	if status := vm2BlkA.Status(); status != choices.Processing {
  2242  		t.Fatalf("Expected status of block on VM2 to be %s, but found %s", choices.Processing, status)
  2243  	}
  2244  	if err := vm2.SetPreference(vm2BlkA.ID()); err != nil {
  2245  		t.Fatal(err)
  2246  	}
  2247  
  2248  	if err := vm1BlkA.Accept(); err != nil {
  2249  		t.Fatalf("VM1 failed to accept block: %s", err)
  2250  	}
  2251  	if err := vm2BlkA.Accept(); err != nil {
  2252  		t.Fatalf("VM2 failed to accept block: %s", err)
  2253  	}
  2254  
  2255  	newHead := <-newTxPoolHeadChan1
  2256  	if newHead.Head.Hash() != common.Hash(vm1BlkA.ID()) {
  2257  		t.Fatalf("Expected new block to match")
  2258  	}
  2259  	newHead = <-newTxPoolHeadChan2
  2260  	if newHead.Head.Hash() != common.Hash(vm2BlkA.ID()) {
  2261  		t.Fatalf("Expected new block to match")
  2262  	}
  2263  
  2264  	txs := make([]*types.Transaction, 10)
  2265  	for i := 0; i < 10; i++ {
  2266  		tx := types.NewTransaction(uint64(i), key.Address, big.NewInt(10), 21000, big.NewInt(params.LaunchMinGasPrice), nil)
  2267  		signedTx, err := types.SignTx(tx, types.NewEIP155Signer(vm1.chainID), key.PrivateKey)
  2268  		if err != nil {
  2269  			t.Fatal(err)
  2270  		}
  2271  		txs[i] = signedTx
  2272  	}
  2273  
  2274  	var errs []error
  2275  
  2276  	errs = vm1.chain.AddRemoteTxs(txs)
  2277  	for i, err := range errs {
  2278  		if err != nil {
  2279  			t.Fatalf("Failed to add transaction to VM1 at index %d: %s", i, err)
  2280  		}
  2281  	}
  2282  
  2283  	<-issuer1
  2284  
  2285  	vm1BlkB, err := vm1.BuildBlock()
  2286  	if err != nil {
  2287  		t.Fatal(err)
  2288  	}
  2289  
  2290  	if err := vm1BlkB.Verify(); err != nil {
  2291  		t.Fatal(err)
  2292  	}
  2293  
  2294  	if status := vm1BlkB.Status(); status != choices.Processing {
  2295  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
  2296  	}
  2297  
  2298  	if err := vm1.SetPreference(vm1BlkB.ID()); err != nil {
  2299  		t.Fatal(err)
  2300  	}
  2301  
  2302  	errs = vm2.chain.AddRemoteTxs(txs[0:5])
  2303  	for i, err := range errs {
  2304  		if err != nil {
  2305  			t.Fatalf("Failed to add transaction to VM2 at index %d: %s", i, err)
  2306  		}
  2307  	}
  2308  
  2309  	<-issuer2
  2310  	vm2BlkC, err := vm2.BuildBlock()
  2311  	if err != nil {
  2312  		t.Fatalf("Failed to build BlkC on VM2: %s", err)
  2313  	}
  2314  
  2315  	if err := vm2BlkC.Verify(); err != nil {
  2316  		t.Fatalf("BlkC failed verification on VM2: %s", err)
  2317  	}
  2318  
  2319  	if status := vm2BlkC.Status(); status != choices.Processing {
  2320  		t.Fatalf("Expected status of built block C to be %s, but found %s", choices.Processing, status)
  2321  	}
  2322  
  2323  	if err := vm2.SetPreference(vm2BlkC.ID()); err != nil {
  2324  		t.Fatal(err)
  2325  	}
  2326  
  2327  	newHead = <-newTxPoolHeadChan2
  2328  	if newHead.Head.Hash() != common.Hash(vm2BlkC.ID()) {
  2329  		t.Fatalf("Expected new block to match")
  2330  	}
  2331  
  2332  	errs = vm2.chain.AddRemoteTxs(txs[5:10])
  2333  	for i, err := range errs {
  2334  		if err != nil {
  2335  			t.Fatalf("Failed to add transaction to VM2 at index %d: %s", i, err)
  2336  		}
  2337  	}
  2338  
  2339  	<-issuer2
  2340  	vm2BlkD, err := vm2.BuildBlock()
  2341  	if err != nil {
  2342  		t.Fatalf("Failed to build BlkD on VM2: %s", err)
  2343  	}
  2344  
  2345  	// Create uncle block from blkD
  2346  	blkDEthBlock := vm2BlkD.(*chain.BlockWrapper).Block.(*Block).ethBlock
  2347  	uncles := []*types.Header{vm1BlkB.(*chain.BlockWrapper).Block.(*Block).ethBlock.Header()}
  2348  	uncleBlockHeader := types.CopyHeader(blkDEthBlock.Header())
  2349  	uncleBlockHeader.UncleHash = types.CalcUncleHash(uncles)
  2350  
  2351  	uncleEthBlock := types.NewBlock(
  2352  		uncleBlockHeader,
  2353  		blkDEthBlock.Transactions(),
  2354  		uncles,
  2355  		nil,
  2356  		new(trie.Trie),
  2357  		blkDEthBlock.ExtData(),
  2358  		false,
  2359  	)
  2360  	uncleBlock := &Block{
  2361  		vm:       vm2,
  2362  		ethBlock: uncleEthBlock,
  2363  		id:       ids.ID(uncleEthBlock.Hash()),
  2364  	}
  2365  	if err := uncleBlock.Verify(); !errors.Is(err, errUnclesUnsupported) {
  2366  		t.Fatalf("VM2 should have failed with %q but got %q", errUnclesUnsupported, err.Error())
  2367  	}
  2368  	if _, err := vm1.ParseBlock(vm2BlkC.Bytes()); err != nil {
  2369  		t.Fatalf("VM1 errored parsing blkC: %s", err)
  2370  	}
  2371  	if _, err := vm1.ParseBlock(uncleBlock.Bytes()); !errors.Is(err, errUnclesUnsupported) {
  2372  		t.Fatalf("VM1 should have failed with %q but got %q", errUnclesUnsupported, err.Error())
  2373  	}
  2374  }
  2375  
  2376  // Regression test to ensure that a VM that is not able to parse a block that
  2377  // contains no transactions.
  2378  func TestEmptyBlock(t *testing.T) {
  2379  	issuer, vm, _, sharedMemory := GenesisVM(t, true, genesisJSONApricotPhase0, "", "")
  2380  
  2381  	defer func() {
  2382  		if err := vm.Shutdown(); err != nil {
  2383  			t.Fatal(err)
  2384  		}
  2385  	}()
  2386  
  2387  	key, err := accountKeystore.NewKey(rand.Reader)
  2388  	if err != nil {
  2389  		t.Fatal(err)
  2390  	}
  2391  
  2392  	// Import 1 AVAX
  2393  	importAmount := uint64(1000000000)
  2394  	utxoID := avax.UTXOID{
  2395  		TxID: ids.ID{
  2396  			0x0f, 0x2f, 0x4f, 0x6f, 0x8e, 0xae, 0xce, 0xee,
  2397  			0x0d, 0x2d, 0x4d, 0x6d, 0x8c, 0xac, 0xcc, 0xec,
  2398  			0x0b, 0x2b, 0x4b, 0x6b, 0x8a, 0xaa, 0xca, 0xea,
  2399  			0x09, 0x29, 0x49, 0x69, 0x88, 0xa8, 0xc8, 0xe8,
  2400  		},
  2401  	}
  2402  
  2403  	utxo := &avax.UTXO{
  2404  		UTXOID: utxoID,
  2405  		Asset:  avax.Asset{ID: vm.ctx.AVAXAssetID},
  2406  		Out: &secp256k1fx.TransferOutput{
  2407  			Amt: importAmount,
  2408  			OutputOwners: secp256k1fx.OutputOwners{
  2409  				Threshold: 1,
  2410  				Addrs:     []ids.ShortID{testKeys[0].PublicKey().Address()},
  2411  			},
  2412  		},
  2413  	}
  2414  	utxoBytes, err := vm.codec.Marshal(codecVersion, utxo)
  2415  	if err != nil {
  2416  		t.Fatal(err)
  2417  	}
  2418  
  2419  	xChainSharedMemory1 := sharedMemory.NewSharedMemory(vm.ctx.XChainID)
  2420  	inputID := utxo.InputID()
  2421  	if err := xChainSharedMemory1.Apply(map[ids.ID]*atomic.Requests{vm.ctx.ChainID: {PutRequests: []*atomic.Element{{
  2422  		Key:   inputID[:],
  2423  		Value: utxoBytes,
  2424  		Traits: [][]byte{
  2425  			testKeys[0].PublicKey().Address().Bytes(),
  2426  		},
  2427  	}}}}); err != nil {
  2428  		t.Fatal(err)
  2429  	}
  2430  
  2431  	importTx, err := vm.newImportTx(vm.ctx.XChainID, key.Address, initialBaseFee, []*crypto.PrivateKeySECP256K1R{testKeys[0]})
  2432  	if err != nil {
  2433  		t.Fatal(err)
  2434  	}
  2435  
  2436  	if err := vm.issueTx(importTx); err != nil {
  2437  		t.Fatal(err)
  2438  	}
  2439  
  2440  	<-issuer
  2441  
  2442  	blk, err := vm.BuildBlock()
  2443  	if err != nil {
  2444  		t.Fatalf("Failed to build block with import transaction: %s", err)
  2445  	}
  2446  
  2447  	// Create empty block from blkA
  2448  	ethBlock := blk.(*chain.BlockWrapper).Block.(*Block).ethBlock
  2449  
  2450  	emptyEthBlock := types.NewBlock(
  2451  		types.CopyHeader(ethBlock.Header()),
  2452  		nil,
  2453  		nil,
  2454  		nil,
  2455  		new(trie.Trie),
  2456  		nil,
  2457  		false,
  2458  	)
  2459  
  2460  	if len(emptyEthBlock.ExtData()) != 0 || emptyEthBlock.Header().ExtDataHash != (common.Hash{}) {
  2461  		t.Fatalf("emptyEthBlock should not have any extra data")
  2462  	}
  2463  
  2464  	emptyBlock := &Block{
  2465  		vm:       vm,
  2466  		ethBlock: emptyEthBlock,
  2467  		id:       ids.ID(emptyEthBlock.Hash()),
  2468  	}
  2469  
  2470  	if _, err := vm.ParseBlock(emptyBlock.Bytes()); !errors.Is(err, errEmptyBlock) {
  2471  		t.Fatalf("VM should have failed with errEmptyBlock but got %s", err.Error())
  2472  	}
  2473  	if err := emptyBlock.Verify(); !errors.Is(err, errEmptyBlock) {
  2474  		t.Fatalf("block should have failed verification with errEmptyBlock but got %s", err.Error())
  2475  	}
  2476  }
  2477  
  2478  // Regression test to ensure that a VM that verifies block B, C, then
  2479  // D (preferring block B) reorgs when C and then D are accepted.
  2480  //   A
  2481  //  / \
  2482  // B   C
  2483  //     |
  2484  //     D
  2485  func TestAcceptReorg(t *testing.T) {
  2486  	issuer1, vm1, _, sharedMemory1 := GenesisVM(t, true, genesisJSONApricotPhase0, "", "")
  2487  	issuer2, vm2, _, sharedMemory2 := GenesisVM(t, true, genesisJSONApricotPhase0, "", "")
  2488  
  2489  	defer func() {
  2490  		if err := vm1.Shutdown(); err != nil {
  2491  			t.Fatal(err)
  2492  		}
  2493  
  2494  		if err := vm2.Shutdown(); err != nil {
  2495  			t.Fatal(err)
  2496  		}
  2497  	}()
  2498  
  2499  	newTxPoolHeadChan1 := make(chan core.NewTxPoolReorgEvent, 1)
  2500  	vm1.chain.GetTxPool().SubscribeNewReorgEvent(newTxPoolHeadChan1)
  2501  	newTxPoolHeadChan2 := make(chan core.NewTxPoolReorgEvent, 1)
  2502  	vm2.chain.GetTxPool().SubscribeNewReorgEvent(newTxPoolHeadChan2)
  2503  
  2504  	key, err := accountKeystore.NewKey(rand.Reader)
  2505  	if err != nil {
  2506  		t.Fatal(err)
  2507  	}
  2508  
  2509  	// Import 1 AVAX
  2510  	importAmount := uint64(1000000000)
  2511  	utxoID := avax.UTXOID{
  2512  		TxID: ids.ID{
  2513  			0x0f, 0x2f, 0x4f, 0x6f, 0x8e, 0xae, 0xce, 0xee,
  2514  			0x0d, 0x2d, 0x4d, 0x6d, 0x8c, 0xac, 0xcc, 0xec,
  2515  			0x0b, 0x2b, 0x4b, 0x6b, 0x8a, 0xaa, 0xca, 0xea,
  2516  			0x09, 0x29, 0x49, 0x69, 0x88, 0xa8, 0xc8, 0xe8,
  2517  		},
  2518  	}
  2519  
  2520  	utxo := &avax.UTXO{
  2521  		UTXOID: utxoID,
  2522  		Asset:  avax.Asset{ID: vm1.ctx.AVAXAssetID},
  2523  		Out: &secp256k1fx.TransferOutput{
  2524  			Amt: importAmount,
  2525  			OutputOwners: secp256k1fx.OutputOwners{
  2526  				Threshold: 1,
  2527  				Addrs:     []ids.ShortID{testKeys[0].PublicKey().Address()},
  2528  			},
  2529  		},
  2530  	}
  2531  	utxoBytes, err := vm1.codec.Marshal(codecVersion, utxo)
  2532  	if err != nil {
  2533  		t.Fatal(err)
  2534  	}
  2535  
  2536  	xChainSharedMemory1 := sharedMemory1.NewSharedMemory(vm1.ctx.XChainID)
  2537  	xChainSharedMemory2 := sharedMemory2.NewSharedMemory(vm2.ctx.XChainID)
  2538  	inputID := utxo.InputID()
  2539  	if err := xChainSharedMemory1.Apply(map[ids.ID]*atomic.Requests{vm1.ctx.ChainID: {PutRequests: []*atomic.Element{{
  2540  		Key:   inputID[:],
  2541  		Value: utxoBytes,
  2542  		Traits: [][]byte{
  2543  			testKeys[0].PublicKey().Address().Bytes(),
  2544  		},
  2545  	}}}}); err != nil {
  2546  		t.Fatal(err)
  2547  	}
  2548  	if err := xChainSharedMemory2.Apply(map[ids.ID]*atomic.Requests{vm2.ctx.ChainID: {PutRequests: []*atomic.Element{{
  2549  		Key:   inputID[:],
  2550  		Value: utxoBytes,
  2551  		Traits: [][]byte{
  2552  			testKeys[0].PublicKey().Address().Bytes(),
  2553  		},
  2554  	}}}}); err != nil {
  2555  		t.Fatal(err)
  2556  	}
  2557  
  2558  	importTx, err := vm1.newImportTx(vm1.ctx.XChainID, key.Address, initialBaseFee, []*crypto.PrivateKeySECP256K1R{testKeys[0]})
  2559  	if err != nil {
  2560  		t.Fatal(err)
  2561  	}
  2562  
  2563  	if err := vm1.issueTx(importTx); err != nil {
  2564  		t.Fatal(err)
  2565  	}
  2566  
  2567  	<-issuer1
  2568  
  2569  	vm1BlkA, err := vm1.BuildBlock()
  2570  	if err != nil {
  2571  		t.Fatalf("Failed to build block with import transaction: %s", err)
  2572  	}
  2573  
  2574  	if err := vm1BlkA.Verify(); err != nil {
  2575  		t.Fatalf("Block failed verification on VM1: %s", err)
  2576  	}
  2577  
  2578  	if status := vm1BlkA.Status(); status != choices.Processing {
  2579  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
  2580  	}
  2581  
  2582  	if err := vm1.SetPreference(vm1BlkA.ID()); err != nil {
  2583  		t.Fatal(err)
  2584  	}
  2585  
  2586  	vm2BlkA, err := vm2.ParseBlock(vm1BlkA.Bytes())
  2587  	if err != nil {
  2588  		t.Fatalf("Unexpected error parsing block from vm2: %s", err)
  2589  	}
  2590  	if err := vm2BlkA.Verify(); err != nil {
  2591  		t.Fatalf("Block failed verification on VM2: %s", err)
  2592  	}
  2593  	if status := vm2BlkA.Status(); status != choices.Processing {
  2594  		t.Fatalf("Expected status of block on VM2 to be %s, but found %s", choices.Processing, status)
  2595  	}
  2596  	if err := vm2.SetPreference(vm2BlkA.ID()); err != nil {
  2597  		t.Fatal(err)
  2598  	}
  2599  
  2600  	if err := vm1BlkA.Accept(); err != nil {
  2601  		t.Fatalf("VM1 failed to accept block: %s", err)
  2602  	}
  2603  	if err := vm2BlkA.Accept(); err != nil {
  2604  		t.Fatalf("VM2 failed to accept block: %s", err)
  2605  	}
  2606  
  2607  	newHead := <-newTxPoolHeadChan1
  2608  	if newHead.Head.Hash() != common.Hash(vm1BlkA.ID()) {
  2609  		t.Fatalf("Expected new block to match")
  2610  	}
  2611  	newHead = <-newTxPoolHeadChan2
  2612  	if newHead.Head.Hash() != common.Hash(vm2BlkA.ID()) {
  2613  		t.Fatalf("Expected new block to match")
  2614  	}
  2615  
  2616  	// Create list of 10 successive transactions to build block A on vm1
  2617  	// and to be split into two separate blocks on VM2
  2618  	txs := make([]*types.Transaction, 10)
  2619  	for i := 0; i < 10; i++ {
  2620  		tx := types.NewTransaction(uint64(i), key.Address, big.NewInt(10), 21000, big.NewInt(params.LaunchMinGasPrice), nil)
  2621  		signedTx, err := types.SignTx(tx, types.NewEIP155Signer(vm1.chainID), key.PrivateKey)
  2622  		if err != nil {
  2623  			t.Fatal(err)
  2624  		}
  2625  		txs[i] = signedTx
  2626  	}
  2627  
  2628  	// Add the remote transactions, build the block, and set VM1's preference
  2629  	// for block B
  2630  	errs := vm1.chain.AddRemoteTxs(txs)
  2631  	for i, err := range errs {
  2632  		if err != nil {
  2633  			t.Fatalf("Failed to add transaction to VM1 at index %d: %s", i, err)
  2634  		}
  2635  	}
  2636  
  2637  	<-issuer1
  2638  
  2639  	vm1BlkB, err := vm1.BuildBlock()
  2640  	if err != nil {
  2641  		t.Fatal(err)
  2642  	}
  2643  
  2644  	if err := vm1BlkB.Verify(); err != nil {
  2645  		t.Fatal(err)
  2646  	}
  2647  
  2648  	if status := vm1BlkB.Status(); status != choices.Processing {
  2649  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
  2650  	}
  2651  
  2652  	if err := vm1.SetPreference(vm1BlkB.ID()); err != nil {
  2653  		t.Fatal(err)
  2654  	}
  2655  
  2656  	errs = vm2.chain.AddRemoteTxs(txs[0:5])
  2657  	for i, err := range errs {
  2658  		if err != nil {
  2659  			t.Fatalf("Failed to add transaction to VM2 at index %d: %s", i, err)
  2660  		}
  2661  	}
  2662  
  2663  	<-issuer2
  2664  
  2665  	vm2BlkC, err := vm2.BuildBlock()
  2666  	if err != nil {
  2667  		t.Fatalf("Failed to build BlkC on VM2: %s", err)
  2668  	}
  2669  
  2670  	if err := vm2BlkC.Verify(); err != nil {
  2671  		t.Fatalf("BlkC failed verification on VM2: %s", err)
  2672  	}
  2673  
  2674  	if err := vm2.SetPreference(vm2BlkC.ID()); err != nil {
  2675  		t.Fatal(err)
  2676  	}
  2677  
  2678  	newHead = <-newTxPoolHeadChan2
  2679  	if newHead.Head.Hash() != common.Hash(vm2BlkC.ID()) {
  2680  		t.Fatalf("Expected new block to match")
  2681  	}
  2682  
  2683  	errs = vm2.chain.AddRemoteTxs(txs[5:])
  2684  	for i, err := range errs {
  2685  		if err != nil {
  2686  			t.Fatalf("Failed to add transaction to VM2 at index %d: %s", i, err)
  2687  		}
  2688  	}
  2689  
  2690  	<-issuer2
  2691  
  2692  	vm2BlkD, err := vm2.BuildBlock()
  2693  	if err != nil {
  2694  		t.Fatalf("Failed to build BlkD on VM2: %s", err)
  2695  	}
  2696  
  2697  	// Parse blocks produced in vm2
  2698  	vm1BlkC, err := vm1.ParseBlock(vm2BlkC.Bytes())
  2699  	if err != nil {
  2700  		t.Fatalf("Unexpected error parsing block from vm2: %s", err)
  2701  	}
  2702  
  2703  	vm1BlkD, err := vm1.ParseBlock(vm2BlkD.Bytes())
  2704  	if err != nil {
  2705  		t.Fatalf("Unexpected error parsing block from vm2: %s", err)
  2706  	}
  2707  
  2708  	if err := vm1BlkC.Verify(); err != nil {
  2709  		t.Fatalf("Block failed verification on VM1: %s", err)
  2710  	}
  2711  	if err := vm1BlkD.Verify(); err != nil {
  2712  		t.Fatalf("Block failed verification on VM1: %s", err)
  2713  	}
  2714  
  2715  	blkBHash := vm1BlkB.(*chain.BlockWrapper).Block.(*Block).ethBlock.Hash()
  2716  	if b := vm1.chain.BlockChain().CurrentBlock(); b.Hash() != blkBHash {
  2717  		t.Fatalf("expected current block to have hash %s but got %s", blkBHash.Hex(), b.Hash().Hex())
  2718  	}
  2719  
  2720  	if err := vm1BlkC.Accept(); err != nil {
  2721  		t.Fatal(err)
  2722  	}
  2723  
  2724  	blkCHash := vm1BlkC.(*chain.BlockWrapper).Block.(*Block).ethBlock.Hash()
  2725  	if b := vm1.chain.BlockChain().CurrentBlock(); b.Hash() != blkCHash {
  2726  		t.Fatalf("expected current block to have hash %s but got %s", blkCHash.Hex(), b.Hash().Hex())
  2727  	}
  2728  
  2729  	if err := vm1BlkB.Reject(); err != nil {
  2730  		t.Fatal(err)
  2731  	}
  2732  
  2733  	if err := vm1BlkD.Accept(); err != nil {
  2734  		t.Fatal(err)
  2735  	}
  2736  
  2737  	blkDHash := vm1BlkD.(*chain.BlockWrapper).Block.(*Block).ethBlock.Hash()
  2738  	if b := vm1.chain.BlockChain().CurrentBlock(); b.Hash() != blkDHash {
  2739  		t.Fatalf("expected current block to have hash %s but got %s", blkDHash.Hex(), b.Hash().Hex())
  2740  	}
  2741  }
  2742  
  2743  func TestFutureBlock(t *testing.T) {
  2744  	issuer, vm, _, sharedMemory := GenesisVM(t, true, genesisJSONApricotPhase0, "", "")
  2745  
  2746  	defer func() {
  2747  		if err := vm.Shutdown(); err != nil {
  2748  			t.Fatal(err)
  2749  		}
  2750  	}()
  2751  
  2752  	key, err := accountKeystore.NewKey(rand.Reader)
  2753  	if err != nil {
  2754  		t.Fatal(err)
  2755  	}
  2756  
  2757  	// Import 1 AVAX
  2758  	importAmount := uint64(1000000000)
  2759  	utxoID := avax.UTXOID{
  2760  		TxID: ids.ID{
  2761  			0x0f, 0x2f, 0x4f, 0x6f, 0x8e, 0xae, 0xce, 0xee,
  2762  			0x0d, 0x2d, 0x4d, 0x6d, 0x8c, 0xac, 0xcc, 0xec,
  2763  			0x0b, 0x2b, 0x4b, 0x6b, 0x8a, 0xaa, 0xca, 0xea,
  2764  			0x09, 0x29, 0x49, 0x69, 0x88, 0xa8, 0xc8, 0xe8,
  2765  		},
  2766  	}
  2767  
  2768  	utxo := &avax.UTXO{
  2769  		UTXOID: utxoID,
  2770  		Asset:  avax.Asset{ID: vm.ctx.AVAXAssetID},
  2771  		Out: &secp256k1fx.TransferOutput{
  2772  			Amt: importAmount,
  2773  			OutputOwners: secp256k1fx.OutputOwners{
  2774  				Threshold: 1,
  2775  				Addrs:     []ids.ShortID{testKeys[0].PublicKey().Address()},
  2776  			},
  2777  		},
  2778  	}
  2779  	utxoBytes, err := vm.codec.Marshal(codecVersion, utxo)
  2780  	if err != nil {
  2781  		t.Fatal(err)
  2782  	}
  2783  
  2784  	xChainSharedMemory := sharedMemory.NewSharedMemory(vm.ctx.XChainID)
  2785  	inputID := utxo.InputID()
  2786  	if err := xChainSharedMemory.Apply(map[ids.ID]*atomic.Requests{vm.ctx.ChainID: {PutRequests: []*atomic.Element{{
  2787  		Key:   inputID[:],
  2788  		Value: utxoBytes,
  2789  		Traits: [][]byte{
  2790  			testKeys[0].PublicKey().Address().Bytes(),
  2791  		},
  2792  	}}}}); err != nil {
  2793  		t.Fatal(err)
  2794  	}
  2795  
  2796  	importTx, err := vm.newImportTx(vm.ctx.XChainID, key.Address, initialBaseFee, []*crypto.PrivateKeySECP256K1R{testKeys[0]})
  2797  	if err != nil {
  2798  		t.Fatal(err)
  2799  	}
  2800  
  2801  	if err := vm.issueTx(importTx); err != nil {
  2802  		t.Fatal(err)
  2803  	}
  2804  
  2805  	<-issuer
  2806  
  2807  	blkA, err := vm.BuildBlock()
  2808  	if err != nil {
  2809  		t.Fatalf("Failed to build block with import transaction: %s", err)
  2810  	}
  2811  
  2812  	// Create empty block from blkA
  2813  	blkAEthBlock := blkA.(*chain.BlockWrapper).Block.(*Block).ethBlock
  2814  
  2815  	modifiedHeader := types.CopyHeader(blkAEthBlock.Header())
  2816  	// Set the VM's clock to the time of the produced block
  2817  	vm.clock.Set(time.Unix(int64(modifiedHeader.Time), 0))
  2818  	// Set the modified time to exceed the allowed future time
  2819  	modifiedTime := modifiedHeader.Time + uint64(maxFutureBlockTime.Seconds()+1)
  2820  	modifiedHeader.Time = modifiedTime
  2821  	modifiedBlock := types.NewBlock(
  2822  		modifiedHeader,
  2823  		nil,
  2824  		nil,
  2825  		nil,
  2826  		new(trie.Trie),
  2827  		blkAEthBlock.ExtData(),
  2828  		false,
  2829  	)
  2830  
  2831  	futureBlock := &Block{
  2832  		vm:       vm,
  2833  		ethBlock: modifiedBlock,
  2834  		id:       ids.ID(modifiedBlock.Hash()),
  2835  	}
  2836  
  2837  	if err := futureBlock.Verify(); err == nil {
  2838  		t.Fatal("Future block should have failed verification due to block timestamp too far in the future")
  2839  	} else if !strings.Contains(err.Error(), "block timestamp is too far in the future") {
  2840  		t.Fatalf("Expected error to be block timestamp too far in the future but found %s", err)
  2841  	}
  2842  }
  2843  
  2844  // Regression test to ensure we can build blocks if we are starting with the
  2845  // Apricot Phase 1 ruleset in genesis.
  2846  func TestBuildApricotPhase1Block(t *testing.T) {
  2847  	issuer, vm, _, sharedMemory := GenesisVM(t, true, genesisJSONApricotPhase1, "", "")
  2848  
  2849  	defer func() {
  2850  		if err := vm.Shutdown(); err != nil {
  2851  			t.Fatal(err)
  2852  		}
  2853  	}()
  2854  
  2855  	newTxPoolHeadChan := make(chan core.NewTxPoolReorgEvent, 1)
  2856  	vm.chain.GetTxPool().SubscribeNewReorgEvent(newTxPoolHeadChan)
  2857  
  2858  	key, err := accountKeystore.NewKey(rand.Reader)
  2859  	if err != nil {
  2860  		t.Fatal(err)
  2861  	}
  2862  
  2863  	importAmount := uint64(1000000000)
  2864  	utxoID := avax.UTXOID{
  2865  		TxID: ids.ID{
  2866  			0x0f, 0x2f, 0x4f, 0x6f, 0x8e, 0xae, 0xce, 0xee,
  2867  			0x0d, 0x2d, 0x4d, 0x6d, 0x8c, 0xac, 0xcc, 0xec,
  2868  			0x0b, 0x2b, 0x4b, 0x6b, 0x8a, 0xaa, 0xca, 0xea,
  2869  			0x09, 0x29, 0x49, 0x69, 0x88, 0xa8, 0xc8, 0xe8,
  2870  		},
  2871  	}
  2872  
  2873  	utxo := &avax.UTXO{
  2874  		UTXOID: utxoID,
  2875  		Asset:  avax.Asset{ID: vm.ctx.AVAXAssetID},
  2876  		Out: &secp256k1fx.TransferOutput{
  2877  			Amt: importAmount,
  2878  			OutputOwners: secp256k1fx.OutputOwners{
  2879  				Threshold: 1,
  2880  				Addrs:     []ids.ShortID{testKeys[0].PublicKey().Address()},
  2881  			},
  2882  		},
  2883  	}
  2884  	utxoBytes, err := vm.codec.Marshal(codecVersion, utxo)
  2885  	if err != nil {
  2886  		t.Fatal(err)
  2887  	}
  2888  
  2889  	xChainSharedMemory := sharedMemory.NewSharedMemory(vm.ctx.XChainID)
  2890  	inputID := utxo.InputID()
  2891  	if err := xChainSharedMemory.Apply(map[ids.ID]*atomic.Requests{vm.ctx.ChainID: {PutRequests: []*atomic.Element{{
  2892  		Key:   inputID[:],
  2893  		Value: utxoBytes,
  2894  		Traits: [][]byte{
  2895  			testKeys[0].PublicKey().Address().Bytes(),
  2896  		},
  2897  	}}}}); err != nil {
  2898  		t.Fatal(err)
  2899  	}
  2900  
  2901  	importTx, err := vm.newImportTx(vm.ctx.XChainID, key.Address, initialBaseFee, []*crypto.PrivateKeySECP256K1R{testKeys[0]})
  2902  	if err != nil {
  2903  		t.Fatal(err)
  2904  	}
  2905  
  2906  	if err := vm.issueTx(importTx); err != nil {
  2907  		t.Fatal(err)
  2908  	}
  2909  
  2910  	<-issuer
  2911  
  2912  	blk, err := vm.BuildBlock()
  2913  	if err != nil {
  2914  		t.Fatal(err)
  2915  	}
  2916  
  2917  	if err := blk.Verify(); err != nil {
  2918  		t.Fatal(err)
  2919  	}
  2920  
  2921  	if status := blk.Status(); status != choices.Processing {
  2922  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
  2923  	}
  2924  
  2925  	if err := vm.SetPreference(blk.ID()); err != nil {
  2926  		t.Fatal(err)
  2927  	}
  2928  
  2929  	if err := blk.Accept(); err != nil {
  2930  		t.Fatal(err)
  2931  	}
  2932  
  2933  	newHead := <-newTxPoolHeadChan
  2934  	if newHead.Head.Hash() != common.Hash(blk.ID()) {
  2935  		t.Fatalf("Expected new block to match")
  2936  	}
  2937  
  2938  	txs := make([]*types.Transaction, 10)
  2939  	for i := 0; i < 5; i++ {
  2940  		tx := types.NewTransaction(uint64(i), key.Address, big.NewInt(10), 21000, big.NewInt(params.LaunchMinGasPrice), nil)
  2941  		signedTx, err := types.SignTx(tx, types.NewEIP155Signer(vm.chainID), key.PrivateKey)
  2942  		if err != nil {
  2943  			t.Fatal(err)
  2944  		}
  2945  		txs[i] = signedTx
  2946  	}
  2947  	for i := 5; i < 10; i++ {
  2948  		tx := types.NewTransaction(uint64(i), key.Address, big.NewInt(10), 21000, big.NewInt(params.ApricotPhase1MinGasPrice), nil)
  2949  		signedTx, err := types.SignTx(tx, types.NewEIP155Signer(vm.chainID), key.PrivateKey)
  2950  		if err != nil {
  2951  			t.Fatal(err)
  2952  		}
  2953  		txs[i] = signedTx
  2954  	}
  2955  	errs := vm.chain.AddRemoteTxs(txs)
  2956  	for i, err := range errs {
  2957  		if err != nil {
  2958  			t.Fatalf("Failed to add tx at index %d: %s", i, err)
  2959  		}
  2960  	}
  2961  
  2962  	<-issuer
  2963  
  2964  	blk, err = vm.BuildBlock()
  2965  	if err != nil {
  2966  		t.Fatal(err)
  2967  	}
  2968  
  2969  	if err := blk.Verify(); err != nil {
  2970  		t.Fatal(err)
  2971  	}
  2972  
  2973  	if status := blk.Status(); status != choices.Processing {
  2974  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
  2975  	}
  2976  
  2977  	if err := blk.Accept(); err != nil {
  2978  		t.Fatal(err)
  2979  	}
  2980  
  2981  	if status := blk.Status(); status != choices.Accepted {
  2982  		t.Fatalf("Expected status of accepted block to be %s, but found %s", choices.Accepted, status)
  2983  	}
  2984  
  2985  	lastAcceptedID, err := vm.LastAccepted()
  2986  	if err != nil {
  2987  		t.Fatal(err)
  2988  	}
  2989  	if lastAcceptedID != blk.ID() {
  2990  		t.Fatalf("Expected last accepted blockID to be the accepted block: %s, but found %s", blk.ID(), lastAcceptedID)
  2991  	}
  2992  
  2993  	// Confirm all txs are present
  2994  	ethBlkTxs := vm.chain.GetBlockByNumber(2).Transactions()
  2995  	for i, tx := range txs {
  2996  		if len(ethBlkTxs) <= i {
  2997  			t.Fatalf("missing transactions expected: %d but found: %d", len(txs), len(ethBlkTxs))
  2998  		}
  2999  		if ethBlkTxs[i].Hash() != tx.Hash() {
  3000  			t.Fatalf("expected tx at index %d to have hash: %x but has: %x", i, txs[i].Hash(), tx.Hash())
  3001  		}
  3002  	}
  3003  }
  3004  
  3005  // Regression test to ensure we can continue producing blocks across a transition from
  3006  // Apricot Phase 0 to Apricot Phase 1. This test all ensures another VM can
  3007  // sync blocks across a transition (where different verifications are applied).
  3008  func TestApricotPhase1Transition(t *testing.T) {
  3009  	// Setup custom JSON
  3010  	genesis := &core.Genesis{}
  3011  	if err := json.Unmarshal([]byte(genesisJSONApricotPhase1), genesis); err != nil {
  3012  		t.Fatalf("Problem unmarshaling genesis JSON: %s", err)
  3013  	}
  3014  	apricotPhase1Time := time.Now().Add(5 * time.Second)
  3015  	genesis.Config.ApricotPhase1BlockTimestamp = big.NewInt(apricotPhase1Time.Unix())
  3016  	customGenesisJSON, err := json.Marshal(genesis)
  3017  	if err != nil {
  3018  		t.Fatalf("Problem marshaling custom genesis JSON: %s", err)
  3019  	}
  3020  
  3021  	// Initialize VMs
  3022  	issuer1, vm1, _, sharedMemory1 := GenesisVM(t, true, string(customGenesisJSON), "", "")
  3023  	defer func() {
  3024  		if err := vm1.Shutdown(); err != nil {
  3025  			t.Fatal(err)
  3026  		}
  3027  	}()
  3028  
  3029  	newTxPoolHeadChan := make(chan core.NewTxPoolReorgEvent, 1)
  3030  	vm1.chain.GetTxPool().SubscribeNewReorgEvent(newTxPoolHeadChan)
  3031  
  3032  	key, err := accountKeystore.NewKey(rand.Reader)
  3033  	if err != nil {
  3034  		t.Fatal(err)
  3035  	}
  3036  
  3037  	importAmount := uint64(1000000000)
  3038  	utxoID := avax.UTXOID{
  3039  		TxID: ids.ID{
  3040  			0x0f, 0x2f, 0x4f, 0x6f, 0x8e, 0xae, 0xce, 0xee,
  3041  			0x0d, 0x2d, 0x4d, 0x6d, 0x8c, 0xac, 0xcc, 0xec,
  3042  			0x0b, 0x2b, 0x4b, 0x6b, 0x8a, 0xaa, 0xca, 0xea,
  3043  			0x09, 0x29, 0x49, 0x69, 0x88, 0xa8, 0xc8, 0xe8,
  3044  		},
  3045  	}
  3046  
  3047  	utxo := &avax.UTXO{
  3048  		UTXOID: utxoID,
  3049  		Asset:  avax.Asset{ID: vm1.ctx.AVAXAssetID},
  3050  		Out: &secp256k1fx.TransferOutput{
  3051  			Amt: importAmount,
  3052  			OutputOwners: secp256k1fx.OutputOwners{
  3053  				Threshold: 1,
  3054  				Addrs:     []ids.ShortID{testKeys[0].PublicKey().Address()},
  3055  			},
  3056  		},
  3057  	}
  3058  	utxoBytes, err := vm1.codec.Marshal(codecVersion, utxo)
  3059  	if err != nil {
  3060  		t.Fatal(err)
  3061  	}
  3062  
  3063  	xChainSharedMemory1 := sharedMemory1.NewSharedMemory(vm1.ctx.XChainID)
  3064  	inputID := utxo.InputID()
  3065  	if err := xChainSharedMemory1.Apply(map[ids.ID]*atomic.Requests{vm1.ctx.ChainID: {PutRequests: []*atomic.Element{{
  3066  		Key:   inputID[:],
  3067  		Value: utxoBytes,
  3068  		Traits: [][]byte{
  3069  			testKeys[0].PublicKey().Address().Bytes(),
  3070  		},
  3071  	}}}}); err != nil {
  3072  		t.Fatal(err)
  3073  	}
  3074  
  3075  	importTx, err := vm1.newImportTx(vm1.ctx.XChainID, key.Address, initialBaseFee, []*crypto.PrivateKeySECP256K1R{testKeys[0]})
  3076  	if err != nil {
  3077  		t.Fatal(err)
  3078  	}
  3079  
  3080  	if err := vm1.issueTx(importTx); err != nil {
  3081  		t.Fatal(err)
  3082  	}
  3083  
  3084  	<-issuer1
  3085  
  3086  	blkA, err := vm1.BuildBlock()
  3087  	if err != nil {
  3088  		t.Fatal(err)
  3089  	}
  3090  
  3091  	if err := blkA.Verify(); err != nil {
  3092  		t.Fatal(err)
  3093  	}
  3094  
  3095  	if status := blkA.Status(); status != choices.Processing {
  3096  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
  3097  	}
  3098  
  3099  	if err := vm1.SetPreference(blkA.ID()); err != nil {
  3100  		t.Fatal(err)
  3101  	}
  3102  
  3103  	if err := blkA.Accept(); err != nil {
  3104  		t.Fatal(err)
  3105  	}
  3106  
  3107  	newHead := <-newTxPoolHeadChan
  3108  	if newHead.Head.Hash() != common.Hash(blkA.ID()) {
  3109  		t.Fatalf("Expected new block to match")
  3110  	}
  3111  
  3112  	txs := make([]*types.Transaction, 10)
  3113  	for i := 0; i < 5; i++ {
  3114  		tx := types.NewTransaction(uint64(i), key.Address, big.NewInt(10), 21000, big.NewInt(params.LaunchMinGasPrice), nil)
  3115  		signedTx, err := types.SignTx(tx, types.NewEIP155Signer(vm1.chainID), key.PrivateKey)
  3116  		if err != nil {
  3117  			t.Fatal(err)
  3118  		}
  3119  		txs[i] = signedTx
  3120  	}
  3121  	for i := 5; i < 10; i++ {
  3122  		tx := types.NewTransaction(uint64(i), key.Address, big.NewInt(10), 21000, big.NewInt(params.ApricotPhase1MinGasPrice), nil)
  3123  		signedTx, err := types.SignTx(tx, types.NewEIP155Signer(vm1.chainID), key.PrivateKey)
  3124  		if err != nil {
  3125  			t.Fatal(err)
  3126  		}
  3127  		txs[i] = signedTx
  3128  	}
  3129  	errs := vm1.chain.AddRemoteTxs(txs[:5])
  3130  	for i, err := range errs {
  3131  		if err != nil {
  3132  			t.Fatalf("Failed to add tx at index %d: %s", i, err)
  3133  		}
  3134  	}
  3135  
  3136  	<-issuer1
  3137  
  3138  	blkB, err := vm1.BuildBlock()
  3139  	if err != nil {
  3140  		t.Fatal(err)
  3141  	}
  3142  
  3143  	if err := blkB.Verify(); err != nil {
  3144  		t.Fatal(err)
  3145  	}
  3146  
  3147  	// Wait for transition
  3148  	time.Sleep(time.Until(apricotPhase1Time) + time.Second)
  3149  
  3150  	if status := blkB.Status(); status != choices.Processing {
  3151  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
  3152  	}
  3153  
  3154  	if err := blkB.Accept(); err != nil {
  3155  		t.Fatal(err)
  3156  	}
  3157  
  3158  	if status := blkB.Status(); status != choices.Accepted {
  3159  		t.Fatalf("Expected status of accepted block to be %s, but found %s", choices.Accepted, status)
  3160  	}
  3161  
  3162  	lastAcceptedID, err := vm1.LastAccepted()
  3163  	if err != nil {
  3164  		t.Fatal(err)
  3165  	}
  3166  	if lastAcceptedID != blkB.ID() {
  3167  		t.Fatalf("Expected last accepted blockID to be the accepted block: %s, but found %s", blkB.ID(), lastAcceptedID)
  3168  	}
  3169  
  3170  	// Confirm all txs are present
  3171  	ethBlkTxs := vm1.chain.GetBlockByNumber(2).Transactions()
  3172  	if len(ethBlkTxs) != 5 {
  3173  		t.Fatalf("Expected 5 transactions in block, but found %d", len(ethBlkTxs))
  3174  	}
  3175  	for i, tx := range txs[:5] {
  3176  		if ethBlkTxs[i].Hash() != tx.Hash() {
  3177  			t.Fatalf("expected tx at index %d to have hash: %x but has: %x", i, txs[i].Hash(), tx.Hash())
  3178  		}
  3179  	}
  3180  
  3181  	newHead = <-newTxPoolHeadChan
  3182  	if newHead.Head.Hash() != common.Hash(blkB.ID()) {
  3183  		t.Fatalf("Expected new block to match")
  3184  	}
  3185  
  3186  	errs = vm1.chain.AddRemoteTxs(txs[5:])
  3187  	for i, err := range errs {
  3188  		if err != nil {
  3189  			t.Fatalf("Failed to add tx at index %d: %s", i, err)
  3190  		}
  3191  	}
  3192  
  3193  	<-issuer1
  3194  
  3195  	blkC, err := vm1.BuildBlock()
  3196  	if err != nil {
  3197  		t.Fatal(err)
  3198  	}
  3199  
  3200  	if err := blkC.Verify(); err != nil {
  3201  		t.Fatal(err)
  3202  	}
  3203  
  3204  	if status := blkC.Status(); status != choices.Processing {
  3205  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
  3206  	}
  3207  
  3208  	if err := blkC.Accept(); err != nil {
  3209  		t.Fatal(err)
  3210  	}
  3211  
  3212  	if status := blkC.Status(); status != choices.Accepted {
  3213  		t.Fatalf("Expected status of accepted block to be %s, but found %s", choices.Accepted, status)
  3214  	}
  3215  
  3216  	lastAcceptedID, err = vm1.LastAccepted()
  3217  	if err != nil {
  3218  		t.Fatal(err)
  3219  	}
  3220  	if lastAcceptedID != blkC.ID() {
  3221  		t.Fatalf("Expected last accepted blockID to be the accepted block: %s, but found %s", blkC.ID(), lastAcceptedID)
  3222  	}
  3223  
  3224  	// Confirm all txs are present
  3225  	ethBlkTxs = vm1.chain.GetBlockByNumber(3).Transactions()
  3226  	for i, tx := range txs[5:] {
  3227  		if len(ethBlkTxs) <= i {
  3228  			t.Fatalf("missing transactions expected: %d but found: %d", len(txs), len(ethBlkTxs))
  3229  		}
  3230  		if ethBlkTxs[i].Hash() != tx.Hash() {
  3231  			t.Fatalf("expected tx at index %d to have hash: %x but has: %x", i, txs[i].Hash(), tx.Hash())
  3232  		}
  3233  	}
  3234  
  3235  	// Sync up other genesis VM (after transition)
  3236  	_, vm2, _, sharedMemory2 := GenesisVM(t, true, string(customGenesisJSON), "", "")
  3237  	defer func() {
  3238  		if err := vm2.Shutdown(); err != nil {
  3239  			t.Fatal(err)
  3240  		}
  3241  	}()
  3242  	xChainSharedMemory2 := sharedMemory2.NewSharedMemory(vm2.ctx.XChainID)
  3243  	if err := xChainSharedMemory2.Apply(map[ids.ID]*atomic.Requests{vm2.ctx.ChainID: {PutRequests: []*atomic.Element{{
  3244  		Key:   inputID[:],
  3245  		Value: utxoBytes,
  3246  		Traits: [][]byte{
  3247  			testKeys[0].PublicKey().Address().Bytes(),
  3248  		},
  3249  	}}}}); err != nil {
  3250  		t.Fatal(err)
  3251  	}
  3252  
  3253  	vm2BlkA, err := vm2.ParseBlock(blkA.Bytes())
  3254  	if err != nil {
  3255  		t.Fatalf("Unexpected error parsing block from vm2: %s", err)
  3256  	}
  3257  	if err := vm2BlkA.Verify(); err != nil {
  3258  		t.Fatalf("Block failed verification on VM2: %s", err)
  3259  	}
  3260  	if status := vm2BlkA.Status(); status != choices.Processing {
  3261  		t.Fatalf("Expected status of block on VM2 to be %s, but found %s", choices.Processing, status)
  3262  	}
  3263  	if err := vm2.SetPreference(vm2BlkA.ID()); err != nil {
  3264  		t.Fatal(err)
  3265  	}
  3266  	if err := vm2BlkA.Accept(); err != nil {
  3267  		t.Fatalf("VM2 failed to accept block: %s", err)
  3268  	}
  3269  
  3270  	vm2BlkB, err := vm2.ParseBlock(blkB.Bytes())
  3271  	if err != nil {
  3272  		t.Fatalf("Unexpected error parsing block from vm2: %s", err)
  3273  	}
  3274  	if err := vm2BlkB.Verify(); err != nil {
  3275  		t.Fatalf("Block failed verification on VM2: %s", err)
  3276  	}
  3277  	if status := vm2BlkB.Status(); status != choices.Processing {
  3278  		t.Fatalf("Expected status of block on VM2 to be %s, but found %s", choices.Processing, status)
  3279  	}
  3280  	if err := vm2.SetPreference(vm2BlkB.ID()); err != nil {
  3281  		t.Fatal(err)
  3282  	}
  3283  	if err := vm2BlkB.Accept(); err != nil {
  3284  		t.Fatalf("VM2 failed to accept block: %s", err)
  3285  	}
  3286  
  3287  	vm2BlkC, err := vm2.ParseBlock(blkC.Bytes())
  3288  	if err != nil {
  3289  		t.Fatalf("Unexpected error parsing block from vm2: %s", err)
  3290  	}
  3291  	if err := vm2BlkC.Verify(); err != nil {
  3292  		t.Fatalf("Block failed verification on VM2: %s", err)
  3293  	}
  3294  	if status := vm2BlkC.Status(); status != choices.Processing {
  3295  		t.Fatalf("Expected status of block on VM2 to be %s, but found %s", choices.Processing, status)
  3296  	}
  3297  	if err := vm2.SetPreference(vm2BlkC.ID()); err != nil {
  3298  		t.Fatal(err)
  3299  	}
  3300  	if err := vm2BlkC.Accept(); err != nil {
  3301  		t.Fatalf("VM2 failed to accept block: %s", err)
  3302  	}
  3303  }
  3304  
  3305  func TestLastAcceptedBlockNumberAllow(t *testing.T) {
  3306  	issuer, vm, _, sharedMemory := GenesisVM(t, true, genesisJSONApricotPhase0, "", "")
  3307  
  3308  	defer func() {
  3309  		if err := vm.Shutdown(); err != nil {
  3310  			t.Fatal(err)
  3311  		}
  3312  	}()
  3313  
  3314  	key, err := accountKeystore.NewKey(rand.Reader)
  3315  	if err != nil {
  3316  		t.Fatal(err)
  3317  	}
  3318  
  3319  	// Import 1 AVAX
  3320  	importAmount := uint64(1000000000)
  3321  	utxoID := avax.UTXOID{
  3322  		TxID: ids.ID{
  3323  			0x0f, 0x2f, 0x4f, 0x6f, 0x8e, 0xae, 0xce, 0xee,
  3324  			0x0d, 0x2d, 0x4d, 0x6d, 0x8c, 0xac, 0xcc, 0xec,
  3325  			0x0b, 0x2b, 0x4b, 0x6b, 0x8a, 0xaa, 0xca, 0xea,
  3326  			0x09, 0x29, 0x49, 0x69, 0x88, 0xa8, 0xc8, 0xe8,
  3327  		},
  3328  	}
  3329  
  3330  	utxo := &avax.UTXO{
  3331  		UTXOID: utxoID,
  3332  		Asset:  avax.Asset{ID: vm.ctx.AVAXAssetID},
  3333  		Out: &secp256k1fx.TransferOutput{
  3334  			Amt: importAmount,
  3335  			OutputOwners: secp256k1fx.OutputOwners{
  3336  				Threshold: 1,
  3337  				Addrs:     []ids.ShortID{testKeys[0].PublicKey().Address()},
  3338  			},
  3339  		},
  3340  	}
  3341  	utxoBytes, err := vm.codec.Marshal(codecVersion, utxo)
  3342  	if err != nil {
  3343  		t.Fatal(err)
  3344  	}
  3345  
  3346  	xChainSharedMemory := sharedMemory.NewSharedMemory(vm.ctx.XChainID)
  3347  	inputID := utxo.InputID()
  3348  	if err := xChainSharedMemory.Apply(map[ids.ID]*atomic.Requests{vm.ctx.ChainID: {PutRequests: []*atomic.Element{{
  3349  		Key:   inputID[:],
  3350  		Value: utxoBytes,
  3351  		Traits: [][]byte{
  3352  			testKeys[0].PublicKey().Address().Bytes(),
  3353  		},
  3354  	}}}}); err != nil {
  3355  		t.Fatal(err)
  3356  	}
  3357  
  3358  	importTx, err := vm.newImportTx(vm.ctx.XChainID, key.Address, initialBaseFee, []*crypto.PrivateKeySECP256K1R{testKeys[0]})
  3359  	if err != nil {
  3360  		t.Fatal(err)
  3361  	}
  3362  
  3363  	if err := vm.issueTx(importTx); err != nil {
  3364  		t.Fatal(err)
  3365  	}
  3366  
  3367  	<-issuer
  3368  
  3369  	blk, err := vm.BuildBlock()
  3370  	if err != nil {
  3371  		t.Fatalf("Failed to build block with import transaction: %s", err)
  3372  	}
  3373  
  3374  	if err := blk.Verify(); err != nil {
  3375  		t.Fatalf("Block failed verification on VM: %s", err)
  3376  	}
  3377  
  3378  	if status := blk.Status(); status != choices.Processing {
  3379  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
  3380  	}
  3381  
  3382  	if err := vm.SetPreference(blk.ID()); err != nil {
  3383  		t.Fatal(err)
  3384  	}
  3385  
  3386  	blkHeight := blk.Height()
  3387  	blkHash := blk.(*chain.BlockWrapper).Block.(*Block).ethBlock.Hash()
  3388  
  3389  	vm.chain.BlockChain().GetVMConfig().AllowUnfinalizedQueries = true
  3390  
  3391  	ctx := context.Background()
  3392  	b, err := vm.chain.APIBackend().BlockByNumber(ctx, rpc.BlockNumber(blkHeight))
  3393  	if err != nil {
  3394  		t.Fatal(err)
  3395  	}
  3396  	if b.Hash() != blkHash {
  3397  		t.Fatalf("expected block at %d to have hash %s but got %s", blkHeight, blkHash.Hex(), b.Hash().Hex())
  3398  	}
  3399  
  3400  	vm.chain.BlockChain().GetVMConfig().AllowUnfinalizedQueries = false
  3401  
  3402  	_, err = vm.chain.APIBackend().BlockByNumber(ctx, rpc.BlockNumber(blkHeight))
  3403  	if !errors.Is(err, eth.ErrUnfinalizedData) {
  3404  		t.Fatalf("expected ErrUnfinalizedData but got %s", err.Error())
  3405  	}
  3406  
  3407  	if err := blk.Accept(); err != nil {
  3408  		t.Fatalf("VM failed to accept block: %s", err)
  3409  	}
  3410  
  3411  	if b := vm.chain.GetBlockByNumber(blkHeight); b.Hash() != blkHash {
  3412  		t.Fatalf("expected block at %d to have hash %s but got %s", blkHeight, blkHash.Hex(), b.Hash().Hex())
  3413  	}
  3414  }
  3415  
  3416  func TestReissueAtomicTx(t *testing.T) {
  3417  	issuer, vm, _, sharedMemory := GenesisVM(t, true, genesisJSONApricotPhase1, "", "")
  3418  
  3419  	defer func() {
  3420  		if err := vm.Shutdown(); err != nil {
  3421  			t.Fatal(err)
  3422  		}
  3423  	}()
  3424  
  3425  	genesisBlkID, err := vm.LastAccepted()
  3426  	if err != nil {
  3427  		t.Fatal(err)
  3428  	}
  3429  
  3430  	importAmount := uint64(10000000)
  3431  	utxoID := avax.UTXOID{
  3432  		TxID: ids.ID{
  3433  			0x0f, 0x2f, 0x4f, 0x6f, 0x8e, 0xae, 0xce, 0xee,
  3434  			0x0d, 0x2d, 0x4d, 0x6d, 0x8c, 0xac, 0xcc, 0xec,
  3435  			0x0b, 0x2b, 0x4b, 0x6b, 0x8a, 0xaa, 0xca, 0xea,
  3436  			0x09, 0x29, 0x49, 0x69, 0x88, 0xa8, 0xc8, 0xe8,
  3437  		},
  3438  	}
  3439  
  3440  	utxo := &avax.UTXO{
  3441  		UTXOID: utxoID,
  3442  		Asset:  avax.Asset{ID: vm.ctx.AVAXAssetID},
  3443  		Out: &secp256k1fx.TransferOutput{
  3444  			Amt: importAmount,
  3445  			OutputOwners: secp256k1fx.OutputOwners{
  3446  				Threshold: 1,
  3447  				Addrs:     []ids.ShortID{testKeys[0].PublicKey().Address()},
  3448  			},
  3449  		},
  3450  	}
  3451  	utxoBytes, err := vm.codec.Marshal(codecVersion, utxo)
  3452  	if err != nil {
  3453  		t.Fatal(err)
  3454  	}
  3455  
  3456  	xChainSharedMemory := sharedMemory.NewSharedMemory(vm.ctx.XChainID)
  3457  	inputID := utxo.InputID()
  3458  	if err := xChainSharedMemory.Apply(map[ids.ID]*atomic.Requests{vm.ctx.ChainID: {PutRequests: []*atomic.Element{{
  3459  		Key:   inputID[:],
  3460  		Value: utxoBytes,
  3461  		Traits: [][]byte{
  3462  			testKeys[0].PublicKey().Address().Bytes(),
  3463  		},
  3464  	}}}}); err != nil {
  3465  		t.Fatal(err)
  3466  	}
  3467  
  3468  	importTx, err := vm.newImportTx(vm.ctx.XChainID, testEthAddrs[0], initialBaseFee, []*crypto.PrivateKeySECP256K1R{testKeys[0]})
  3469  	if err != nil {
  3470  		t.Fatal(err)
  3471  	}
  3472  
  3473  	if err := vm.issueTx(importTx); err != nil {
  3474  		t.Fatal(err)
  3475  	}
  3476  
  3477  	<-issuer
  3478  
  3479  	blk, err := vm.BuildBlock()
  3480  	if err != nil {
  3481  		t.Fatal(err)
  3482  	}
  3483  
  3484  	if err := blk.Verify(); err != nil {
  3485  		t.Fatal(err)
  3486  	}
  3487  
  3488  	if status := blk.Status(); status != choices.Processing {
  3489  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
  3490  	}
  3491  
  3492  	if err := vm.SetPreference(blk.ID()); err != nil {
  3493  		t.Fatal(err)
  3494  	}
  3495  
  3496  	if err := blk.Reject(); err != nil {
  3497  		t.Fatal(err)
  3498  	}
  3499  
  3500  	if status := blk.Status(); status != choices.Rejected {
  3501  		t.Fatalf("Expected status of rejected block to be %s, but found %s", choices.Rejected, status)
  3502  	}
  3503  
  3504  	if err := vm.SetPreference(genesisBlkID); err != nil {
  3505  		t.Fatal(err)
  3506  	}
  3507  
  3508  	<-issuer
  3509  	blk, err = vm.BuildBlock()
  3510  	if err != nil {
  3511  		t.Fatal(err)
  3512  	}
  3513  
  3514  	if err := blk.Verify(); err != nil {
  3515  		t.Fatal(err)
  3516  	}
  3517  
  3518  	if status := blk.Status(); status != choices.Processing {
  3519  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
  3520  	}
  3521  
  3522  	if err := vm.SetPreference(blk.ID()); err != nil {
  3523  		t.Fatal(err)
  3524  	}
  3525  
  3526  	if err := blk.Accept(); err != nil {
  3527  		t.Fatal(err)
  3528  	}
  3529  
  3530  	if status := blk.Status(); status != choices.Accepted {
  3531  		t.Fatalf("Expected status of accepted block to be %s, but found %s", choices.Accepted, status)
  3532  	}
  3533  
  3534  	if lastAcceptedID, err := vm.LastAccepted(); err != nil {
  3535  		t.Fatal(err)
  3536  	} else if lastAcceptedID != blk.ID() {
  3537  		t.Fatalf("Expected last accepted blockID to be the accepted block: %s, but found %s", blk.ID(), lastAcceptedID)
  3538  	}
  3539  }
  3540  
  3541  func TestAtomicTxFailsEVMStateTransferBuildBlock(t *testing.T) {
  3542  	issuer, vm, _, sharedMemory := GenesisVM(t, true, genesisJSONApricotPhase1, "", "")
  3543  
  3544  	defer func() {
  3545  		if err := vm.Shutdown(); err != nil {
  3546  			t.Fatal(err)
  3547  		}
  3548  	}()
  3549  
  3550  	importAmount := uint64(10000000)
  3551  	utxoID := avax.UTXOID{
  3552  		TxID: ids.ID{
  3553  			0x0f, 0x2f, 0x4f, 0x6f, 0x8e, 0xae, 0xce, 0xee,
  3554  			0x0d, 0x2d, 0x4d, 0x6d, 0x8c, 0xac, 0xcc, 0xec,
  3555  			0x0b, 0x2b, 0x4b, 0x6b, 0x8a, 0xaa, 0xca, 0xea,
  3556  			0x09, 0x29, 0x49, 0x69, 0x88, 0xa8, 0xc8, 0xe8,
  3557  		},
  3558  	}
  3559  
  3560  	utxo := &avax.UTXO{
  3561  		UTXOID: utxoID,
  3562  		Asset:  avax.Asset{ID: vm.ctx.AVAXAssetID},
  3563  		Out: &secp256k1fx.TransferOutput{
  3564  			Amt: importAmount,
  3565  			OutputOwners: secp256k1fx.OutputOwners{
  3566  				Threshold: 1,
  3567  				Addrs:     []ids.ShortID{testKeys[0].PublicKey().Address()},
  3568  			},
  3569  		},
  3570  	}
  3571  	utxoBytes, err := vm.codec.Marshal(codecVersion, utxo)
  3572  	if err != nil {
  3573  		t.Fatal(err)
  3574  	}
  3575  
  3576  	xChainSharedMemory := sharedMemory.NewSharedMemory(vm.ctx.XChainID)
  3577  	inputID := utxo.InputID()
  3578  	if err := xChainSharedMemory.Apply(map[ids.ID]*atomic.Requests{vm.ctx.ChainID: {PutRequests: []*atomic.Element{{
  3579  		Key:   inputID[:],
  3580  		Value: utxoBytes,
  3581  		Traits: [][]byte{
  3582  			testKeys[0].PublicKey().Address().Bytes(),
  3583  		},
  3584  	}}}}); err != nil {
  3585  		t.Fatal(err)
  3586  	}
  3587  
  3588  	importTx, err := vm.newImportTx(vm.ctx.XChainID, testEthAddrs[0], initialBaseFee, []*crypto.PrivateKeySECP256K1R{testKeys[0]})
  3589  	if err != nil {
  3590  		t.Fatal(err)
  3591  	}
  3592  
  3593  	if err := vm.issueTx(importTx); err != nil {
  3594  		t.Fatal(err)
  3595  	}
  3596  
  3597  	<-issuer
  3598  
  3599  	blk, err := vm.BuildBlock()
  3600  	if err != nil {
  3601  		t.Fatal(err)
  3602  	}
  3603  
  3604  	if err := blk.Verify(); err != nil {
  3605  		t.Fatal(err)
  3606  	}
  3607  
  3608  	if status := blk.Status(); status != choices.Processing {
  3609  		t.Fatalf("Expected status of built block to be %s, but found %s", choices.Processing, status)
  3610  	}
  3611  
  3612  	if err := vm.SetPreference(blk.ID()); err != nil {
  3613  		t.Fatal(err)
  3614  	}
  3615  
  3616  	if err := blk.Accept(); err != nil {
  3617  		t.Fatal(err)
  3618  	}
  3619  
  3620  	if status := blk.Status(); status != choices.Accepted {
  3621  		t.Fatalf("Expected status of accepted block to be %s, but found %s", choices.Accepted, status)
  3622  	}
  3623  
  3624  	if lastAcceptedID, err := vm.LastAccepted(); err != nil {
  3625  		t.Fatal(err)
  3626  	} else if lastAcceptedID != blk.ID() {
  3627  		t.Fatalf("Expected last accepted blockID to be the accepted block: %s, but found %s", blk.ID(), lastAcceptedID)
  3628  	}
  3629  
  3630  	exportTx1, err := vm.newExportTx(vm.ctx.AVAXAssetID, importAmount-2*params.AvalancheAtomicTxFee, vm.ctx.XChainID, testShortIDAddrs[0], initialBaseFee, []*crypto.PrivateKeySECP256K1R{testKeys[0]})
  3631  	if err != nil {
  3632  		t.Fatal(err)
  3633  	}
  3634  	exportTx2, err := vm.newExportTx(vm.ctx.AVAXAssetID, importAmount-2*params.AvalancheAtomicTxFee, vm.ctx.XChainID, testShortIDAddrs[1], initialBaseFee, []*crypto.PrivateKeySECP256K1R{testKeys[0]})
  3635  	if err != nil {
  3636  		t.Fatal(err)
  3637  	}
  3638  
  3639  	if err := vm.issueTx(exportTx1); err != nil {
  3640  		t.Fatal(err)
  3641  	}
  3642  	<-issuer
  3643  	exportBlk1, err := vm.BuildBlock()
  3644  	if err != nil {
  3645  		t.Fatal(err)
  3646  	}
  3647  	if err := exportBlk1.Verify(); err != nil {
  3648  		t.Fatal(err)
  3649  	}
  3650  
  3651  	if err := vm.SetPreference(exportBlk1.ID()); err != nil {
  3652  		t.Fatal(err)
  3653  	}
  3654  
  3655  	if err := vm.issueTx(exportTx2); err == nil {
  3656  		t.Fatal("Should have failed to issue due to an invalid export tx")
  3657  	}
  3658  	// Force add transaction directly to the mempool to ensure it fails during build block
  3659  	// as well.
  3660  	if err := vm.mempool.AddTx(exportTx2); err != nil {
  3661  		t.Fatal(err)
  3662  	}
  3663  	<-issuer
  3664  
  3665  	_, err = vm.BuildBlock()
  3666  	if err == nil {
  3667  		t.Fatal("BuildBlock should have returned an error due to invalid export transaction")
  3668  	}
  3669  }
  3670  
  3671  func TestBuildInvalidBlockHead(t *testing.T) {
  3672  	issuer, vm, _, _ := GenesisVM(t, true, genesisJSONApricotPhase0, "", "")
  3673  
  3674  	defer func() {
  3675  		if err := vm.Shutdown(); err != nil {
  3676  			t.Fatal(err)
  3677  		}
  3678  	}()
  3679  
  3680  	key0 := testKeys[0]
  3681  	addr0 := key0.PublicKey().Address()
  3682  
  3683  	// Create the transaction
  3684  	utx := &UnsignedImportTx{
  3685  		NetworkID:    vm.ctx.NetworkID,
  3686  		BlockchainID: vm.ctx.ChainID,
  3687  		Outs: []EVMOutput{{
  3688  			Address: common.Address(addr0),
  3689  			Amount:  1 * units.Avax,
  3690  			AssetID: vm.ctx.AVAXAssetID,
  3691  		}},
  3692  		ImportedInputs: []*avax.TransferableInput{
  3693  			{
  3694  				Asset: avax.Asset{ID: vm.ctx.AVAXAssetID},
  3695  				In: &secp256k1fx.TransferInput{
  3696  					Amt: 1 * units.Avax,
  3697  					Input: secp256k1fx.Input{
  3698  						SigIndices: []uint32{0},
  3699  					},
  3700  				},
  3701  			},
  3702  		},
  3703  		SourceChain: vm.ctx.XChainID,
  3704  	}
  3705  	tx := &Tx{UnsignedAtomicTx: utx}
  3706  	if err := tx.Sign(vm.codec, [][]*crypto.PrivateKeySECP256K1R{{key0}}); err != nil {
  3707  		t.Fatal(err)
  3708  	}
  3709  
  3710  	currentBlock := vm.chain.BlockChain().CurrentBlock()
  3711  
  3712  	// Verify that the transaction fails verification when attempting to issue
  3713  	// it into the atomic mempool.
  3714  	if err := vm.issueTx(tx); err == nil {
  3715  		t.Fatal("Should have failed to issue invalid transaction")
  3716  	}
  3717  	// Force issue the transaction directly to the mempool
  3718  	if err := vm.mempool.AddTx(tx); err != nil {
  3719  		t.Fatal(err)
  3720  	}
  3721  
  3722  	<-issuer
  3723  
  3724  	if _, err := vm.BuildBlock(); err == nil {
  3725  		t.Fatalf("Unexpectedly created a block")
  3726  	}
  3727  
  3728  	newCurrentBlock := vm.chain.BlockChain().CurrentBlock()
  3729  
  3730  	if currentBlock.Hash() != newCurrentBlock.Hash() {
  3731  		t.Fatal("current block changed")
  3732  	}
  3733  }