github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/evm/types/chain_config.go (about)

     1  package types
     2  
     3  import (
     4  	"fmt"
     5  	"math/big"
     6  	"strings"
     7  
     8  	"github.com/tendermint/go-amino"
     9  
    10  	"gopkg.in/yaml.v2"
    11  
    12  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    13  	sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors"
    14  
    15  	"github.com/ethereum/go-ethereum/common"
    16  	"github.com/ethereum/go-ethereum/params"
    17  )
    18  
    19  // ChainConfig defines the Ethereum ChainConfig parameters using sdk.Int values instead of big.Int.
    20  //
    21  // NOTE 1: Since empty/uninitialized Ints (i.e with a nil big.Int value) are parsed to zero, we need to manually
    22  // specify that negative Int values will be considered as nil. See getBlockValue for reference.
    23  //
    24  // NOTE 2: This type is not a configurable Param since the SDK does not allow for validation against
    25  // a previous stored parameter values or the current block height (retrieved from context). If you
    26  // want to update the config values, use an software upgrade procedure.
    27  type ChainConfig struct {
    28  	HomesteadBlock sdk.Int `json:"homestead_block" yaml:"homestead_block"` // Homestead switch block (< 0 no fork, 0 = already homestead)
    29  
    30  	DAOForkBlock   sdk.Int `json:"dao_fork_block" yaml:"dao_fork_block"`     // TheDAO hard-fork switch block (< 0 no fork)
    31  	DAOForkSupport bool    `json:"dao_fork_support" yaml:"dao_fork_support"` // Whether the nodes supports or opposes the DAO hard-fork
    32  
    33  	// EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150)
    34  	EIP150Block sdk.Int `json:"eip150_block" yaml:"eip150_block"` // EIP150 HF block (< 0 no fork)
    35  	EIP150Hash  string  `json:"eip150_hash" yaml:"eip150_hash"`   // EIP150 HF hash (needed for header only clients as only gas pricing changed)
    36  
    37  	EIP155Block sdk.Int `json:"eip155_block" yaml:"eip155_block"` // EIP155 HF block
    38  	EIP158Block sdk.Int `json:"eip158_block" yaml:"eip158_block"` // EIP158 HF block
    39  
    40  	ByzantiumBlock      sdk.Int `json:"byzantium_block" yaml:"byzantium_block"`           // Byzantium switch block (< 0 no fork, 0 = already on byzantium)
    41  	ConstantinopleBlock sdk.Int `json:"constantinople_block" yaml:"constantinople_block"` // Constantinople switch block (< 0 no fork, 0 = already activated)
    42  	PetersburgBlock     sdk.Int `json:"petersburg_block" yaml:"petersburg_block"`         // Petersburg switch block (< 0 same as Constantinople)
    43  	IstanbulBlock       sdk.Int `json:"istanbul_block" yaml:"istanbul_block"`             // Istanbul switch block (< 0 no fork, 0 = already on istanbul)
    44  	MuirGlacierBlock    sdk.Int `json:"muir_glacier_block" yaml:"muir_glacier_block"`     // Eip-2384 (bomb delay) switch block (< 0 no fork, 0 = already activated)
    45  
    46  	YoloV2Block sdk.Int `json:"yoloV2_block" yaml:"yoloV2_block"` // YOLO v1: https://github.com/ethereum/EIPs/pull/2657 (Ephemeral testnet)
    47  	EWASMBlock  sdk.Int `json:"ewasm_block" yaml:"ewasm_block"`   // EWASM switch block (< 0 no fork, 0 = already activated)
    48  }
    49  
    50  // EthereumConfig returns an Ethereum ChainConfig for EVM state transitions.
    51  // All the negative or nil values are converted to nil
    52  func (cc ChainConfig) EthereumConfig(chainID *big.Int) *params.ChainConfig {
    53  	return &params.ChainConfig{
    54  		ChainID:             chainID,
    55  		HomesteadBlock:      getBlockValue(cc.HomesteadBlock),
    56  		DAOForkBlock:        getBlockValue(cc.DAOForkBlock),
    57  		DAOForkSupport:      cc.DAOForkSupport,
    58  		EIP150Block:         getBlockValue(cc.EIP150Block),
    59  		EIP150Hash:          common.HexToHash(cc.EIP150Hash),
    60  		EIP155Block:         getBlockValue(cc.EIP155Block),
    61  		EIP158Block:         getBlockValue(cc.EIP158Block),
    62  		ByzantiumBlock:      getBlockValue(cc.ByzantiumBlock),
    63  		ConstantinopleBlock: getBlockValue(cc.ConstantinopleBlock),
    64  		PetersburgBlock:     getBlockValue(cc.PetersburgBlock),
    65  		IstanbulBlock:       getBlockValue(cc.IstanbulBlock),
    66  		MuirGlacierBlock:    getBlockValue(cc.MuirGlacierBlock),
    67  	}
    68  }
    69  
    70  // IsIstanbul returns whether the Istanbul version is enabled.
    71  func (cc ChainConfig) IsIstanbul() bool {
    72  	return getBlockValue(cc.IstanbulBlock) != nil
    73  }
    74  
    75  // IsHomestead returns whether the Homestead version is enabled.
    76  func (cc ChainConfig) IsHomestead() bool {
    77  	return getBlockValue(cc.HomesteadBlock) != nil
    78  }
    79  
    80  // String implements the fmt.Stringer interface
    81  func (cc ChainConfig) String() string {
    82  	out, _ := yaml.Marshal(cc)
    83  	return string(out)
    84  }
    85  
    86  // DefaultChainConfig returns default evm parameters. Th
    87  func DefaultChainConfig() ChainConfig {
    88  	return ChainConfig{
    89  		HomesteadBlock:      sdk.ZeroInt(),
    90  		DAOForkBlock:        sdk.ZeroInt(),
    91  		DAOForkSupport:      true,
    92  		EIP150Block:         sdk.ZeroInt(),
    93  		EIP150Hash:          common.Hash{}.String(),
    94  		EIP155Block:         sdk.ZeroInt(),
    95  		EIP158Block:         sdk.ZeroInt(),
    96  		ByzantiumBlock:      sdk.ZeroInt(),
    97  		ConstantinopleBlock: sdk.ZeroInt(),
    98  		PetersburgBlock:     sdk.ZeroInt(),
    99  		IstanbulBlock:       sdk.ZeroInt(),
   100  		MuirGlacierBlock:    sdk.ZeroInt(),
   101  		YoloV2Block:         sdk.NewInt(-1),
   102  		EWASMBlock:          sdk.NewInt(-1),
   103  	}
   104  }
   105  
   106  func getBlockValue(block sdk.Int) *big.Int {
   107  	if block.IsNegative() {
   108  		return nil
   109  	}
   110  
   111  	return block.BigInt()
   112  }
   113  
   114  // Validate performs a basic validation of the ChainConfig params. The function will return an error
   115  // if any of the block values is uninitialized (i.e nil) or if the EIP150Hash is an invalid hash.
   116  func (cc ChainConfig) Validate() error {
   117  	if err := validateBlock(cc.HomesteadBlock); err != nil {
   118  		return sdkerrors.Wrap(err, "homesteadBlock")
   119  	}
   120  	if err := validateBlock(cc.DAOForkBlock); err != nil {
   121  		return sdkerrors.Wrap(err, "daoForkBlock")
   122  	}
   123  	if err := validateBlock(cc.EIP150Block); err != nil {
   124  		return sdkerrors.Wrap(err, "eip150Block")
   125  	}
   126  	if err := validateHash(cc.EIP150Hash); err != nil {
   127  		return err
   128  	}
   129  	if err := validateBlock(cc.EIP155Block); err != nil {
   130  		return sdkerrors.Wrap(err, "eip155Block")
   131  	}
   132  	if err := validateBlock(cc.EIP158Block); err != nil {
   133  		return sdkerrors.Wrap(err, "eip158Block")
   134  	}
   135  	if err := validateBlock(cc.ByzantiumBlock); err != nil {
   136  		return sdkerrors.Wrap(err, "byzantiumBlock")
   137  	}
   138  	if err := validateBlock(cc.ConstantinopleBlock); err != nil {
   139  		return sdkerrors.Wrap(err, "constantinopleBlock")
   140  	}
   141  	if err := validateBlock(cc.PetersburgBlock); err != nil {
   142  		return sdkerrors.Wrap(err, "petersburgBlock")
   143  	}
   144  	if err := validateBlock(cc.IstanbulBlock); err != nil {
   145  		return sdkerrors.Wrap(err, "istanbulBlock")
   146  	}
   147  	if err := validateBlock(cc.MuirGlacierBlock); err != nil {
   148  		return sdkerrors.Wrap(err, "muirGlacierBlock")
   149  	}
   150  	if err := validateBlock(cc.YoloV2Block); err != nil {
   151  		return sdkerrors.Wrap(err, "yoloV2Block")
   152  	}
   153  	if err := validateBlock(cc.EWASMBlock); err != nil {
   154  		return sdkerrors.Wrap(err, "eWASMBlock")
   155  	}
   156  
   157  	return nil
   158  }
   159  
   160  func (config *ChainConfig) UnmarshalFromAmino(cdc *amino.Codec, data []byte) error {
   161  	var dataLen uint64 = 0
   162  	var subData []byte
   163  
   164  	for {
   165  		data = data[dataLen:]
   166  
   167  		if len(data) == 0 {
   168  			break
   169  		}
   170  
   171  		pos, aminoType, err := amino.ParseProtoPosAndTypeMustOneByte(data[0])
   172  		if err != nil {
   173  			return err
   174  		}
   175  		data = data[1:]
   176  
   177  		if aminoType == amino.Typ3_ByteLength {
   178  			var n int
   179  			dataLen, n, err = amino.DecodeUvarint(data)
   180  			if err != nil {
   181  				return err
   182  			}
   183  			data = data[n:]
   184  			subData = data[:dataLen]
   185  		}
   186  
   187  		switch pos {
   188  		case 1:
   189  			err = config.HomesteadBlock.UnmarshalFromAmino(cdc, subData)
   190  			if err != nil {
   191  				return err
   192  			}
   193  		case 2:
   194  			err = config.DAOForkBlock.UnmarshalFromAmino(cdc, subData)
   195  			if err != nil {
   196  				return err
   197  			}
   198  		case 3:
   199  			if data[0] != 0 && data[0] != 1 {
   200  				return fmt.Errorf("invalid DAO fork switch")
   201  			}
   202  			config.DAOForkSupport = data[0] == 1
   203  			dataLen = 1
   204  		case 4:
   205  			err = config.EIP150Block.UnmarshalFromAmino(cdc, subData)
   206  			if err != nil {
   207  				return err
   208  			}
   209  		case 5:
   210  			config.EIP150Hash = string(subData)
   211  		case 6:
   212  			err = config.EIP155Block.UnmarshalFromAmino(cdc, subData)
   213  			if err != nil {
   214  				return err
   215  			}
   216  		case 7:
   217  			err = config.EIP158Block.UnmarshalFromAmino(cdc, subData)
   218  			if err != nil {
   219  				return err
   220  			}
   221  		case 8:
   222  			err = config.ByzantiumBlock.UnmarshalFromAmino(cdc, subData)
   223  			if err != nil {
   224  				return err
   225  			}
   226  		case 9:
   227  			err = config.ConstantinopleBlock.UnmarshalFromAmino(cdc, subData)
   228  			if err != nil {
   229  				return err
   230  			}
   231  		case 10:
   232  			err = config.PetersburgBlock.UnmarshalFromAmino(cdc, subData)
   233  			if err != nil {
   234  				return err
   235  			}
   236  		case 11:
   237  			err = config.IstanbulBlock.UnmarshalFromAmino(cdc, subData)
   238  			if err != nil {
   239  				return err
   240  			}
   241  		case 12:
   242  			err = config.MuirGlacierBlock.UnmarshalFromAmino(cdc, subData)
   243  			if err != nil {
   244  				return err
   245  			}
   246  		case 13:
   247  			err = config.YoloV2Block.UnmarshalFromAmino(cdc, subData)
   248  			if err != nil {
   249  				return err
   250  			}
   251  		case 14:
   252  			err = config.EWASMBlock.UnmarshalFromAmino(cdc, subData)
   253  			if err != nil {
   254  				return err
   255  			}
   256  		default:
   257  			return fmt.Errorf("unexpect feild num %d", pos)
   258  		}
   259  	}
   260  	return nil
   261  }
   262  
   263  func validateHash(hex string) error {
   264  	if hex != "" && strings.TrimSpace(hex) == "" {
   265  		return sdkerrors.Wrapf(ErrInvalidChainConfig, "hash cannot be blank")
   266  	}
   267  
   268  	bz := common.FromHex(hex)
   269  	lenHex := len(bz)
   270  	if lenHex > 0 && lenHex != common.HashLength {
   271  		return sdkerrors.Wrapf(ErrInvalidChainConfig, "invalid hash length, expected %d, got %d", common.HashLength, lenHex)
   272  	}
   273  
   274  	return nil
   275  }
   276  
   277  func validateBlock(block sdk.Int) error {
   278  	if block == (sdk.Int{}) || block.BigInt() == nil {
   279  		return sdkerrors.Wrapf(
   280  			ErrInvalidChainConfig,
   281  			"cannot use uninitialized or nil values for Int, set a negative Int value if you want to define a nil Ethereum block",
   282  		)
   283  	}
   284  
   285  	return nil
   286  }