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 ¶ms.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 }