github.com/MetalBlockchain/subnet-evm@v0.6.3/params/state_upgrade.go (about)

     1  // (c) 2023 Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package params
     5  
     6  import (
     7  	"fmt"
     8  	"reflect"
     9  
    10  	"github.com/MetalBlockchain/subnet-evm/utils"
    11  	"github.com/ethereum/go-ethereum/common"
    12  	"github.com/ethereum/go-ethereum/common/hexutil"
    13  	"github.com/ethereum/go-ethereum/common/math"
    14  )
    15  
    16  // StateUpgrade describes the modifications to be made to the state during
    17  // a state upgrade.
    18  type StateUpgrade struct {
    19  	BlockTimestamp *uint64 `json:"blockTimestamp,omitempty"`
    20  
    21  	// map from account address to the modification to be made to the account.
    22  	StateUpgradeAccounts map[common.Address]StateUpgradeAccount `json:"accounts"`
    23  }
    24  
    25  // StateUpgradeAccount describes the modifications to be made to an account during
    26  // a state upgrade.
    27  type StateUpgradeAccount struct {
    28  	Code          hexutil.Bytes               `json:"code,omitempty"`
    29  	Storage       map[common.Hash]common.Hash `json:"storage,omitempty"`
    30  	BalanceChange *math.HexOrDecimal256       `json:"balanceChange,omitempty"`
    31  }
    32  
    33  func (s *StateUpgrade) Equal(other *StateUpgrade) bool {
    34  	return reflect.DeepEqual(s, other)
    35  }
    36  
    37  // verifyStateUpgrades checks [c.StateUpgrades] is well formed:
    38  // - the specified blockTimestamps must monotonically increase
    39  func (c *ChainConfig) verifyStateUpgrades() error {
    40  	var previousUpgradeTimestamp *uint64
    41  	for i, upgrade := range c.StateUpgrades {
    42  		upgradeTimestamp := upgrade.BlockTimestamp
    43  		if upgradeTimestamp == nil {
    44  			return fmt.Errorf("StateUpgrade[%d]: config block timestamp cannot be nil ", i)
    45  		}
    46  		// Verify the upgrade's timestamp is equal 0 (to avoid confusion with genesis).
    47  		if *upgradeTimestamp == 0 {
    48  			return fmt.Errorf("StateUpgrade[%d]: config block timestamp (%v) must be greater than 0", i, *upgradeTimestamp)
    49  		}
    50  
    51  		// Verify specified timestamps are strictly monotonically increasing.
    52  		if previousUpgradeTimestamp != nil && *upgradeTimestamp <= *previousUpgradeTimestamp {
    53  			return fmt.Errorf("StateUpgrade[%d]: config block timestamp (%v) <= previous timestamp (%v)", i, *upgradeTimestamp, *previousUpgradeTimestamp)
    54  		}
    55  		previousUpgradeTimestamp = upgradeTimestamp
    56  	}
    57  	return nil
    58  }
    59  
    60  // GetActivatingStateUpgrades returns all state upgrades configured to activate during the
    61  // state transition from a block with timestamp [from] to a block with timestamp [to].
    62  func (c *ChainConfig) GetActivatingStateUpgrades(from *uint64, to uint64, upgrades []StateUpgrade) []StateUpgrade {
    63  	activating := make([]StateUpgrade, 0)
    64  	for _, upgrade := range upgrades {
    65  		if utils.IsForkTransition(upgrade.BlockTimestamp, from, to) {
    66  			activating = append(activating, upgrade)
    67  		}
    68  	}
    69  	return activating
    70  }
    71  
    72  // CheckStateUpgradesCompatible checks if [stateUpgrades] are compatible with [c] at [headTimestamp].
    73  func (c *ChainConfig) CheckStateUpgradesCompatible(stateUpgrades []StateUpgrade, lastTimestamp uint64) *ConfigCompatError {
    74  	// All active upgrades (from nil to [lastTimestamp]) must match.
    75  	activeUpgrades := c.GetActivatingStateUpgrades(nil, lastTimestamp, c.StateUpgrades)
    76  	newUpgrades := c.GetActivatingStateUpgrades(nil, lastTimestamp, stateUpgrades)
    77  
    78  	// Check activated upgrades are still present.
    79  	for i, upgrade := range activeUpgrades {
    80  		if len(newUpgrades) <= i {
    81  			// missing upgrade
    82  			return newTimestampCompatError(
    83  				fmt.Sprintf("missing StateUpgrade[%d]", i),
    84  				upgrade.BlockTimestamp,
    85  				nil,
    86  			)
    87  		}
    88  		// All upgrades that have activated must be identical.
    89  		if !upgrade.Equal(&newUpgrades[i]) {
    90  			return newTimestampCompatError(
    91  				fmt.Sprintf("StateUpgrade[%d]", i),
    92  				upgrade.BlockTimestamp,
    93  				newUpgrades[i].BlockTimestamp,
    94  			)
    95  		}
    96  	}
    97  	// then, make sure newUpgrades does not have additional upgrades
    98  	// that are already activated. (cannot perform retroactive upgrade)
    99  	if len(newUpgrades) > len(activeUpgrades) {
   100  		return newTimestampCompatError(
   101  			fmt.Sprintf("cannot retroactively enable StateUpgrade[%d]", len(activeUpgrades)),
   102  			nil,
   103  			newUpgrades[len(activeUpgrades)].BlockTimestamp, // this indexes to the first element in newUpgrades after the end of activeUpgrades
   104  		)
   105  	}
   106  
   107  	return nil
   108  }