github.com/jeffallen/go-ethereum@v1.1.4-0.20150910155051-571d3236c49c/core/chain_util.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package core
    18  
    19  import (
    20  	"bytes"
    21  	"math/big"
    22  	"time"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/core/types"
    26  	"github.com/ethereum/go-ethereum/logger"
    27  	"github.com/ethereum/go-ethereum/logger/glog"
    28  	"github.com/ethereum/go-ethereum/params"
    29  	"github.com/ethereum/go-ethereum/rlp"
    30  )
    31  
    32  var (
    33  	blockHashPre  = []byte("block-hash-")
    34  	blockNumPre   = []byte("block-num-")
    35  	ExpDiffPeriod = big.NewInt(100000)
    36  )
    37  
    38  // CalcDifficulty is the difficulty adjustment algorithm. It returns
    39  // the difficulty that a new block b should have when created at time
    40  // given the parent block's time and difficulty.
    41  func CalcDifficulty(time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
    42  	diff := new(big.Int)
    43  	adjust := new(big.Int).Div(parentDiff, params.DifficultyBoundDivisor)
    44  	bigTime := new(big.Int)
    45  	bigParentTime := new(big.Int)
    46  
    47  	bigTime.SetUint64(time)
    48  	bigParentTime.SetUint64(parentTime)
    49  
    50  	if bigTime.Sub(bigTime, bigParentTime).Cmp(params.DurationLimit) < 0 {
    51  		diff.Add(parentDiff, adjust)
    52  	} else {
    53  		diff.Sub(parentDiff, adjust)
    54  	}
    55  	if diff.Cmp(params.MinimumDifficulty) < 0 {
    56  		diff = params.MinimumDifficulty
    57  	}
    58  
    59  	periodCount := new(big.Int).Add(parentNumber, common.Big1)
    60  	periodCount.Div(periodCount, ExpDiffPeriod)
    61  	if periodCount.Cmp(common.Big1) > 0 {
    62  		// diff = diff + 2^(periodCount - 2)
    63  		expDiff := periodCount.Sub(periodCount, common.Big2)
    64  		expDiff.Exp(common.Big2, expDiff, nil)
    65  		diff.Add(diff, expDiff)
    66  		diff = common.BigMax(diff, params.MinimumDifficulty)
    67  	}
    68  
    69  	return diff
    70  }
    71  
    72  // CalcTD computes the total difficulty of block.
    73  func CalcTD(block, parent *types.Block) *big.Int {
    74  	if parent == nil {
    75  		return block.Difficulty()
    76  	}
    77  	d := block.Difficulty()
    78  	d.Add(d, parent.Td)
    79  	return d
    80  }
    81  
    82  // CalcGasLimit computes the gas limit of the next block after parent.
    83  // The result may be modified by the caller.
    84  // This is miner strategy, not consensus protocol.
    85  func CalcGasLimit(parent *types.Block) *big.Int {
    86  	// contrib = (parentGasUsed * 3 / 2) / 1024
    87  	contrib := new(big.Int).Mul(parent.GasUsed(), big.NewInt(3))
    88  	contrib = contrib.Div(contrib, big.NewInt(2))
    89  	contrib = contrib.Div(contrib, params.GasLimitBoundDivisor)
    90  
    91  	// decay = parentGasLimit / 1024 -1
    92  	decay := new(big.Int).Div(parent.GasLimit(), params.GasLimitBoundDivisor)
    93  	decay.Sub(decay, big.NewInt(1))
    94  
    95  	/*
    96  		strategy: gasLimit of block-to-mine is set based on parent's
    97  		gasUsed value.  if parentGasUsed > parentGasLimit * (2/3) then we
    98  		increase it, otherwise lower it (or leave it unchanged if it's right
    99  		at that usage) the amount increased/decreased depends on how far away
   100  		from parentGasLimit * (2/3) parentGasUsed is.
   101  	*/
   102  	gl := new(big.Int).Sub(parent.GasLimit(), decay)
   103  	gl = gl.Add(gl, contrib)
   104  	gl.Set(common.BigMax(gl, params.MinGasLimit))
   105  
   106  	// however, if we're now below the target (GenesisGasLimit) we increase the
   107  	// limit as much as we can (parentGasLimit / 1024 -1)
   108  	if gl.Cmp(params.GenesisGasLimit) < 0 {
   109  		gl.Add(parent.GasLimit(), decay)
   110  		gl.Set(common.BigMin(gl, params.GenesisGasLimit))
   111  	}
   112  	return gl
   113  }
   114  
   115  // GetBlockByHash returns the block corresponding to the hash or nil if not found
   116  func GetBlockByHash(db common.Database, hash common.Hash) *types.Block {
   117  	data, _ := db.Get(append(blockHashPre, hash[:]...))
   118  	if len(data) == 0 {
   119  		return nil
   120  	}
   121  	var block types.StorageBlock
   122  	if err := rlp.Decode(bytes.NewReader(data), &block); err != nil {
   123  		glog.V(logger.Error).Infof("invalid block RLP for hash %x: %v", hash, err)
   124  		return nil
   125  	}
   126  	return (*types.Block)(&block)
   127  }
   128  
   129  // GetBlockByHash returns the canonical block by number or nil if not found
   130  func GetBlockByNumber(db common.Database, number uint64) *types.Block {
   131  	key, _ := db.Get(append(blockNumPre, big.NewInt(int64(number)).Bytes()...))
   132  	if len(key) == 0 {
   133  		return nil
   134  	}
   135  
   136  	return GetBlockByHash(db, common.BytesToHash(key))
   137  }
   138  
   139  // WriteCanonNumber writes the canonical hash for the given block
   140  func WriteCanonNumber(db common.Database, block *types.Block) error {
   141  	key := append(blockNumPre, block.Number().Bytes()...)
   142  	err := db.Put(key, block.Hash().Bytes())
   143  	if err != nil {
   144  		return err
   145  	}
   146  	return nil
   147  }
   148  
   149  // WriteHead force writes the current head
   150  func WriteHead(db common.Database, block *types.Block) error {
   151  	err := WriteCanonNumber(db, block)
   152  	if err != nil {
   153  		return err
   154  	}
   155  	err = db.Put([]byte("LastBlock"), block.Hash().Bytes())
   156  	if err != nil {
   157  		return err
   158  	}
   159  	return nil
   160  }
   161  
   162  // WriteBlock writes a block to the database
   163  func WriteBlock(db common.Database, block *types.Block) error {
   164  	tstart := time.Now()
   165  
   166  	enc, _ := rlp.EncodeToBytes((*types.StorageBlock)(block))
   167  	key := append(blockHashPre, block.Hash().Bytes()...)
   168  	err := db.Put(key, enc)
   169  	if err != nil {
   170  		glog.Fatal("db write fail:", err)
   171  		return err
   172  	}
   173  
   174  	if glog.V(logger.Debug) {
   175  		glog.Infof("wrote block #%v %s. Took %v\n", block.Number(), common.PP(block.Hash().Bytes()), time.Since(tstart))
   176  	}
   177  
   178  	return nil
   179  }