github.com/MetalBlockchain/subnet-evm@v0.4.9/plugin/evm/vm_upgrade_bytes_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  	"encoding/json"
     9  	"errors"
    10  	"math/big"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/MetalBlockchain/metalgo/snow"
    15  	"github.com/MetalBlockchain/metalgo/snow/engine/common"
    16  	"github.com/MetalBlockchain/metalgo/vms/components/chain"
    17  	"github.com/MetalBlockchain/subnet-evm/core"
    18  	"github.com/MetalBlockchain/subnet-evm/core/types"
    19  	"github.com/MetalBlockchain/subnet-evm/metrics"
    20  	"github.com/MetalBlockchain/subnet-evm/params"
    21  	"github.com/MetalBlockchain/subnet-evm/precompile"
    22  	"github.com/stretchr/testify/assert"
    23  )
    24  
    25  func TestVMUpgradeBytesPrecompile(t *testing.T) {
    26  	// Make a TxAllowListConfig upgrade at genesis and convert it to JSON to apply as upgradeBytes.
    27  	enableAllowListTimestamp := time.Unix(0, 0) // enable at genesis
    28  	upgradeConfig := &params.UpgradeConfig{
    29  		PrecompileUpgrades: []params.PrecompileUpgrade{
    30  			{
    31  				TxAllowListConfig: precompile.NewTxAllowListConfig(big.NewInt(enableAllowListTimestamp.Unix()), testEthAddrs[0:1], nil),
    32  			},
    33  		},
    34  	}
    35  	upgradeBytesJSON, err := json.Marshal(upgradeConfig)
    36  	if err != nil {
    37  		t.Fatalf("could not marshal upgradeConfig to json: %s", err)
    38  	}
    39  
    40  	// initialize the VM with these upgrade bytes
    41  	issuer, vm, dbManager, appSender := GenesisVM(t, true, genesisJSONSubnetEVM, "", string(upgradeBytesJSON))
    42  
    43  	// Submit a successful transaction
    44  	tx0 := types.NewTransaction(uint64(0), testEthAddrs[0], big.NewInt(1), 21000, big.NewInt(testMinGasPrice), nil)
    45  	signedTx0, err := types.SignTx(tx0, types.NewEIP155Signer(vm.chainConfig.ChainID), testKeys[0])
    46  	assert.NoError(t, err)
    47  
    48  	errs := vm.txPool.AddRemotesSync([]*types.Transaction{signedTx0})
    49  	if err := errs[0]; err != nil {
    50  		t.Fatalf("Failed to add tx at index: %s", err)
    51  	}
    52  
    53  	// Submit a rejected transaction, should throw an error
    54  	tx1 := types.NewTransaction(uint64(0), testEthAddrs[1], big.NewInt(2), 21000, big.NewInt(testMinGasPrice), nil)
    55  	signedTx1, err := types.SignTx(tx1, types.NewEIP155Signer(vm.chainConfig.ChainID), testKeys[1])
    56  	if err != nil {
    57  		t.Fatal(err)
    58  	}
    59  	errs = vm.txPool.AddRemotesSync([]*types.Transaction{signedTx1})
    60  	if err := errs[0]; !errors.Is(err, precompile.ErrSenderAddressNotAllowListed) {
    61  		t.Fatalf("expected ErrSenderAddressNotAllowListed, got: %s", err)
    62  	}
    63  
    64  	// shutdown the vm
    65  	if err := vm.Shutdown(context.Background()); err != nil {
    66  		t.Fatal(err)
    67  	}
    68  
    69  	// prepare the new upgrade bytes to disable the TxAllowList
    70  	disableAllowListTimestamp := enableAllowListTimestamp.Add(10 * time.Hour) // arbitrary choice
    71  	upgradeConfig.PrecompileUpgrades = append(
    72  		upgradeConfig.PrecompileUpgrades,
    73  		params.PrecompileUpgrade{
    74  			TxAllowListConfig: precompile.NewDisableTxAllowListConfig(big.NewInt(disableAllowListTimestamp.Unix())),
    75  		},
    76  	)
    77  	upgradeBytesJSON, err = json.Marshal(upgradeConfig)
    78  	if err != nil {
    79  		t.Fatalf("could not marshal upgradeConfig to json: %s", err)
    80  	}
    81  
    82  	// restart the vm
    83  	ctx := NewContext()
    84  	if err := vm.Initialize(
    85  		context.Background(), ctx, dbManager, []byte(genesisJSONSubnetEVM), upgradeBytesJSON, []byte{}, issuer, []*common.Fx{}, appSender,
    86  	); err != nil {
    87  		t.Fatal(err)
    88  	}
    89  	defer func() {
    90  		if err := vm.Shutdown(context.Background()); err != nil {
    91  			t.Fatal(err)
    92  		}
    93  	}()
    94  	// Set the VM's state to NormalOp to initialize the tx pool.
    95  	if err := vm.SetState(context.Background(), snow.NormalOp); err != nil {
    96  		t.Fatal(err)
    97  	}
    98  	newTxPoolHeadChan := make(chan core.NewTxPoolReorgEvent, 1)
    99  	vm.txPool.SubscribeNewReorgEvent(newTxPoolHeadChan)
   100  	vm.clock.Set(disableAllowListTimestamp)
   101  
   102  	// Make a block, previous rules still apply (TxAllowList is active)
   103  	// Submit a successful transaction
   104  	errs = vm.txPool.AddRemotesSync([]*types.Transaction{signedTx0})
   105  	if err := errs[0]; err != nil {
   106  		t.Fatalf("Failed to add tx at index: %s", err)
   107  	}
   108  
   109  	// Submit a rejected transaction, should throw an error
   110  	errs = vm.txPool.AddRemotesSync([]*types.Transaction{signedTx1})
   111  	if err := errs[0]; !errors.Is(err, precompile.ErrSenderAddressNotAllowListed) {
   112  		t.Fatalf("expected ErrSenderAddressNotAllowListed, got: %s", err)
   113  	}
   114  
   115  	blk := issueAndAccept(t, issuer, vm)
   116  
   117  	// Verify that the constructed block only has the whitelisted tx
   118  	block := blk.(*chain.BlockWrapper).Block.(*Block).ethBlock
   119  	txs := block.Transactions()
   120  	if txs.Len() != 1 {
   121  		t.Fatalf("Expected number of txs to be %d, but found %d", 1, txs.Len())
   122  	}
   123  	assert.Equal(t, signedTx0.Hash(), txs[0].Hash())
   124  
   125  	// verify the issued block is after the network upgrade
   126  	assert.True(t, block.Timestamp().Cmp(big.NewInt(disableAllowListTimestamp.Unix())) >= 0)
   127  
   128  	<-newTxPoolHeadChan // wait for new head in tx pool
   129  
   130  	// retry the rejected Tx, which should now succeed
   131  	errs = vm.txPool.AddRemotesSync([]*types.Transaction{signedTx1})
   132  	if err := errs[0]; err != nil {
   133  		t.Fatalf("Failed to add tx at index: %s", err)
   134  	}
   135  
   136  	vm.clock.Set(vm.clock.Time().Add(2 * time.Second)) // add 2 seconds for gas fee to adjust
   137  	blk = issueAndAccept(t, issuer, vm)
   138  
   139  	// Verify that the constructed block only has the previously rejected tx
   140  	block = blk.(*chain.BlockWrapper).Block.(*Block).ethBlock
   141  	txs = block.Transactions()
   142  	if txs.Len() != 1 {
   143  		t.Fatalf("Expected number of txs to be %d, but found %d", 1, txs.Len())
   144  	}
   145  	assert.Equal(t, signedTx1.Hash(), txs[0].Hash())
   146  }
   147  
   148  func TestVMUpgradeBytesNetworkUpgrades(t *testing.T) {
   149  	// Hack: registering metrics uses global variables, so we need to disable metrics here so that we can initialize the VM twice.
   150  	metrics.Enabled = false
   151  	defer func() {
   152  		metrics.Enabled = true
   153  	}()
   154  
   155  	// Get a json specifying a Network upgrade at genesis
   156  	// to apply as upgradeBytes.
   157  	subnetEVMTimestamp := time.Unix(10, 0)
   158  	upgradeConfig := &params.UpgradeConfig{
   159  		NetworkUpgrades: &params.NetworkUpgrades{
   160  			SubnetEVMTimestamp: big.NewInt(subnetEVMTimestamp.Unix()),
   161  		},
   162  	}
   163  	upgradeBytesJSON, err := json.Marshal(upgradeConfig)
   164  	if err != nil {
   165  		t.Fatalf("could not marshal upgradeConfig to json: %s", err)
   166  	}
   167  	configJSON := "{\"skip-subnet-evm-upgrade-check\": true}"
   168  
   169  	// initialize the VM with these upgrade bytes
   170  	issuer, vm, dbManager, appSender := GenesisVM(t, true, genesisJSONPreSubnetEVM, configJSON, string(upgradeBytesJSON))
   171  	vm.clock.Set(subnetEVMTimestamp)
   172  
   173  	// verify upgrade is applied
   174  	if !vm.chainConfig.IsSubnetEVM(big.NewInt(subnetEVMTimestamp.Unix())) {
   175  		t.Fatal("expected subnet-evm network upgrade to have been enabled")
   176  	}
   177  
   178  	// Submit a successful transaction and build a block to move the chain head past the SubnetEVMTimestamp network upgrade
   179  	tx0 := types.NewTransaction(uint64(0), testEthAddrs[0], big.NewInt(1), 21000, big.NewInt(testMinGasPrice), nil)
   180  	signedTx0, err := types.SignTx(tx0, types.NewEIP155Signer(vm.chainConfig.ChainID), testKeys[0])
   181  	assert.NoError(t, err)
   182  	errs := vm.txPool.AddRemotesSync([]*types.Transaction{signedTx0})
   183  	if err := errs[0]; err != nil {
   184  		t.Fatalf("Failed to add tx at index: %s", err)
   185  	}
   186  
   187  	issueAndAccept(t, issuer, vm) // make a block
   188  
   189  	if err := vm.Shutdown(context.Background()); err != nil {
   190  		t.Fatal(err)
   191  	}
   192  
   193  	// VM should not start again without proper upgrade bytes.
   194  	err = vm.Initialize(context.Background(), vm.ctx, dbManager, []byte(genesisJSONPreSubnetEVM), []byte{}, []byte{}, issuer, []*common.Fx{}, appSender)
   195  	assert.ErrorContains(t, err, "mismatching SubnetEVM fork block timestamp in database")
   196  
   197  	// VM should not start if fork is moved back
   198  	upgradeConfig.NetworkUpgrades.SubnetEVMTimestamp = big.NewInt(2)
   199  	upgradeBytesJSON, err = json.Marshal(upgradeConfig)
   200  	if err != nil {
   201  		t.Fatalf("could not marshal upgradeConfig to json: %s", err)
   202  	}
   203  	err = vm.Initialize(context.Background(), vm.ctx, dbManager, []byte(genesisJSONPreSubnetEVM), upgradeBytesJSON, []byte{}, issuer, []*common.Fx{}, appSender)
   204  	assert.ErrorContains(t, err, "mismatching SubnetEVM fork block timestamp in database")
   205  
   206  	// VM should not start if fork is moved forward
   207  	upgradeConfig.NetworkUpgrades.SubnetEVMTimestamp = big.NewInt(30)
   208  	upgradeBytesJSON, err = json.Marshal(upgradeConfig)
   209  	if err != nil {
   210  		t.Fatalf("could not marshal upgradeConfig to json: %s", err)
   211  	}
   212  	err = vm.Initialize(context.Background(), vm.ctx, dbManager, []byte(genesisJSONPreSubnetEVM), upgradeBytesJSON, []byte{}, issuer, []*common.Fx{}, appSender)
   213  	assert.ErrorContains(t, err, "mismatching SubnetEVM fork block timestamp in database")
   214  }
   215  
   216  func TestVMUpgradeBytesNetworkUpgradesWithGenesis(t *testing.T) {
   217  	// make genesis w/ fork at block 5
   218  	var genesis core.Genesis
   219  	if err := json.Unmarshal([]byte(genesisJSONPreSubnetEVM), &genesis); err != nil {
   220  		t.Fatalf("could not unmarshal genesis bytes: %s", err)
   221  	}
   222  	genesisSubnetEVMTimestamp := big.NewInt(5)
   223  	genesis.Config.SubnetEVMTimestamp = genesisSubnetEVMTimestamp
   224  	genesisBytes, err := json.Marshal(&genesis)
   225  	if err != nil {
   226  		t.Fatalf("could not unmarshal genesis bytes: %s", err)
   227  	}
   228  
   229  	// Get a json specifying a Network upgrade at genesis
   230  	// to apply as upgradeBytes.
   231  	subnetEVMTimestamp := time.Unix(10, 0)
   232  	upgradeConfig := &params.UpgradeConfig{
   233  		NetworkUpgrades: &params.NetworkUpgrades{
   234  			SubnetEVMTimestamp: big.NewInt(subnetEVMTimestamp.Unix()),
   235  		},
   236  	}
   237  	upgradeBytesJSON, err := json.Marshal(upgradeConfig)
   238  	if err != nil {
   239  		t.Fatalf("could not marshal upgradeConfig to json: %s", err)
   240  	}
   241  	configJSON := "{\"skip-subnet-evm-upgrade-check\": true}"
   242  
   243  	// initialize the VM with these upgrade bytes
   244  	_, vm, _, _ := GenesisVM(t, true, string(genesisBytes), configJSON, string(upgradeBytesJSON))
   245  
   246  	// verify upgrade is rescheduled
   247  	assert.False(t, vm.chainConfig.IsSubnetEVM(genesisSubnetEVMTimestamp))
   248  	assert.True(t, vm.chainConfig.IsSubnetEVM(big.NewInt(subnetEVMTimestamp.Unix())))
   249  
   250  	if err := vm.Shutdown(context.Background()); err != nil {
   251  		t.Fatal(err)
   252  	}
   253  
   254  	// abort a fork specified in genesis
   255  	upgradeConfig.NetworkUpgrades.SubnetEVMTimestamp = nil
   256  	upgradeBytesJSON, err = json.Marshal(upgradeConfig)
   257  	if err != nil {
   258  		t.Fatalf("could not marshal upgradeConfig to json: %s", err)
   259  	}
   260  
   261  	// initialize the VM with these upgrade bytes
   262  	_, vm, _, _ = GenesisVM(t, true, string(genesisBytes), configJSON, string(upgradeBytesJSON))
   263  
   264  	// verify upgrade is aborted
   265  	assert.False(t, vm.chainConfig.IsSubnetEVM(genesisSubnetEVMTimestamp))
   266  	assert.False(t, vm.chainConfig.IsSubnetEVM(big.NewInt(subnetEVMTimestamp.Unix())))
   267  
   268  	if err := vm.Shutdown(context.Background()); err != nil {
   269  		t.Fatal(err)
   270  	}
   271  }