github.com/Blockdaemon/celo-blockchain@v0.0.0-20200129231733-e667f6b08419/contract_comm/blockchain_parameters/blockchain_parameters.go (about) 1 // Copyright 2017 The Celo Authors 2 // This file is part of the celo library. 3 // 4 // The celo library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The celo library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the celo library. If not, see <http://www.gnu.org/licenses/>. 16 17 package blockchain_parameters 18 19 import ( 20 "math/big" 21 "strings" 22 "time" 23 24 "github.com/ethereum/go-ethereum/accounts/abi" 25 "github.com/ethereum/go-ethereum/common/hexutil" 26 "github.com/ethereum/go-ethereum/contract_comm" 27 "github.com/ethereum/go-ethereum/contract_comm/errors" 28 "github.com/ethereum/go-ethereum/core/types" 29 "github.com/ethereum/go-ethereum/core/vm" 30 "github.com/ethereum/go-ethereum/log" 31 "github.com/ethereum/go-ethereum/params" 32 ) 33 34 const ( 35 blockchainParametersABIString = `[{ 36 "constant": true, 37 "inputs": [], 38 "name": "getMinimumClientVersion", 39 "outputs": [ 40 { 41 "name": "major", 42 "type": "uint256" 43 }, 44 { 45 "name": "minor", 46 "type": "uint256" 47 }, 48 { 49 "name": "patch", 50 "type": "uint256" 51 } 52 ], 53 "payable": false, 54 "stateMutability": "view", 55 "type": "function" 56 }, 57 { 58 "constant": true, 59 "inputs": [], 60 "name": "blockGasLimit", 61 "outputs": [ 62 { 63 "name": "", 64 "type": "uint256" 65 } 66 ], 67 "payable": false, 68 "stateMutability": "view", 69 "type": "function" 70 }, 71 { 72 "constant": true, 73 "inputs": [], 74 "name": "intrinsicGasForAlternativeFeeCurrency", 75 "outputs": [ 76 { 77 "name": "", 78 "type": "uint256" 79 } 80 ], 81 "payable": false, 82 "stateMutability": "view", 83 "type": "function" 84 } 85 ]` 86 ) 87 88 var blockchainParametersABI abi.ABI 89 90 func init() { 91 var err error 92 blockchainParametersABI, err = abi.JSON(strings.NewReader(blockchainParametersABIString)) 93 if err != nil { 94 log.Crit("Error reading ABI for BlockchainParameters", "err", err) 95 } 96 } 97 98 func GetMinimumVersion(header *types.Header, state vm.StateDB) (*params.VersionInfo, error) { 99 version := [3]*big.Int{big.NewInt(0), big.NewInt(0), big.NewInt(0)} 100 var err error 101 _, err = contract_comm.MakeStaticCall( 102 params.BlockchainParametersRegistryId, 103 blockchainParametersABI, 104 "getMinimumClientVersion", 105 []interface{}{}, 106 &version, 107 params.MaxGasForReadBlockchainParameter, 108 header, 109 state, 110 ) 111 if err != nil { 112 return nil, err 113 } 114 return ¶ms.VersionInfo{version[0].Uint64(), version[1].Uint64(), version[2].Uint64()}, nil 115 } 116 117 func GetGasCost(header *types.Header, state vm.StateDB, defaultGas uint64, method string) uint64 { 118 var gas *big.Int 119 var err error 120 _, err = contract_comm.MakeStaticCall( 121 params.BlockchainParametersRegistryId, 122 blockchainParametersABI, 123 method, 124 []interface{}{}, 125 &gas, 126 params.MaxGasForReadBlockchainParameter, 127 header, 128 state, 129 ) 130 if err != nil { 131 log.Trace("Default gas", "gas", defaultGas, "method", method) 132 return defaultGas 133 } 134 log.Trace("Reading gas", "gas", gas) 135 return gas.Uint64() 136 } 137 138 func GetIntrinsicGasForAlternativeFeeCurrency(header *types.Header, state vm.StateDB) uint64 { 139 return GetGasCost(header, state, params.IntrinsicGasForAlternativeFeeCurrency, "intrinsicGasForAlternativeFeeCurrency") 140 } 141 142 func CheckMinimumVersion(header *types.Header, state vm.StateDB) { 143 version, err := GetMinimumVersion(header, state) 144 145 if err != nil { 146 if err == errors.ErrRegistryContractNotDeployed { 147 log.Debug("Error checking client version", "err", err, "contract", hexutil.Encode(params.BlockchainParametersRegistryId[:])) 148 } else { 149 log.Warn("Error checking client version", "err", err, "contract", hexutil.Encode(params.BlockchainParametersRegistryId[:])) 150 } 151 return 152 } 153 154 if params.CurrentVersionInfo.Cmp(version) == -1 { 155 time.Sleep(10 * time.Second) 156 log.Crit("Client version older than required", "current", params.Version, "required", version) 157 } 158 159 } 160 161 func SpawnCheck() { 162 go func() { 163 for { 164 time.Sleep(60 * time.Second) 165 CheckMinimumVersion(nil, nil) 166 } 167 }() 168 } 169 170 func GetBlockGasLimit(header *types.Header, state vm.StateDB) (uint64, error) { 171 var gasLimit *big.Int 172 _, err := contract_comm.MakeStaticCall( 173 params.BlockchainParametersRegistryId, 174 blockchainParametersABI, 175 "blockGasLimit", 176 []interface{}{}, 177 &gasLimit, 178 params.MaxGasForReadBlockchainParameter, 179 header, 180 state, 181 ) 182 if err != nil { 183 if err == errors.ErrRegistryContractNotDeployed { 184 log.Debug("Error obtaining block gas limit", "err", err, "contract", hexutil.Encode(params.BlockchainParametersRegistryId[:])) 185 } else { 186 log.Warn("Error obtaining block gas limit", "err", err, "contract", hexutil.Encode(params.BlockchainParametersRegistryId[:])) 187 } 188 return params.DefaultGasLimit, err 189 } 190 return gasLimit.Uint64(), nil 191 }