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 &params.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  }