core/types: make blocks immutable
This commit is contained in:
committed by
Jeffrey Wilcke
parent
654564e164
commit
1d42888d30
@ -38,23 +38,24 @@ const (
|
||||
maxTimeFutureBlocks = 30
|
||||
)
|
||||
|
||||
func CalcDifficulty(block, parent *types.Header) *big.Int {
|
||||
// CalcDifficulty is the difficulty adjustment algorithm. It returns
|
||||
// the difficulty that a new block b should have when created at time
|
||||
// given the parent block's time and difficulty.
|
||||
func CalcDifficulty(time int64, parentTime int64, parentDiff *big.Int) *big.Int {
|
||||
diff := new(big.Int)
|
||||
|
||||
adjust := new(big.Int).Div(parent.Difficulty, params.DifficultyBoundDivisor)
|
||||
if big.NewInt(int64(block.Time)-int64(parent.Time)).Cmp(params.DurationLimit) < 0 {
|
||||
diff.Add(parent.Difficulty, adjust)
|
||||
adjust := new(big.Int).Div(parentDiff, params.DifficultyBoundDivisor)
|
||||
if big.NewInt(time-parentTime).Cmp(params.DurationLimit) < 0 {
|
||||
diff.Add(parentDiff, adjust)
|
||||
} else {
|
||||
diff.Sub(parent.Difficulty, adjust)
|
||||
diff.Sub(parentDiff, adjust)
|
||||
}
|
||||
|
||||
if diff.Cmp(params.MinimumDifficulty) < 0 {
|
||||
return params.MinimumDifficulty
|
||||
}
|
||||
|
||||
return diff
|
||||
}
|
||||
|
||||
// CalcTD computes the total difficulty of block.
|
||||
func CalcTD(block, parent *types.Block) *big.Int {
|
||||
if parent == nil {
|
||||
return block.Difficulty()
|
||||
@ -62,6 +63,8 @@ func CalcTD(block, parent *types.Block) *big.Int {
|
||||
return new(big.Int).Add(parent.Td, block.Header().Difficulty)
|
||||
}
|
||||
|
||||
// CalcGasLimit computes the gas limit of the next block after parent.
|
||||
// The result may be modified by the caller.
|
||||
func CalcGasLimit(parent *types.Block) *big.Int {
|
||||
decay := new(big.Int).Div(parent.GasLimit(), params.GasLimitBoundDivisor)
|
||||
contrib := new(big.Int).Mul(parent.GasUsed(), big.NewInt(3))
|
||||
@ -71,11 +74,11 @@ func CalcGasLimit(parent *types.Block) *big.Int {
|
||||
gl := new(big.Int).Sub(parent.GasLimit(), decay)
|
||||
gl = gl.Add(gl, contrib)
|
||||
gl = gl.Add(gl, big.NewInt(1))
|
||||
gl = common.BigMax(gl, params.MinGasLimit)
|
||||
gl.Set(common.BigMax(gl, params.MinGasLimit))
|
||||
|
||||
if gl.Cmp(params.GenesisGasLimit) < 0 {
|
||||
gl2 := new(big.Int).Add(parent.GasLimit(), decay)
|
||||
return common.BigMin(params.GenesisGasLimit, gl2)
|
||||
gl.Add(parent.GasLimit(), decay)
|
||||
gl.Set(common.BigMin(gl, params.GenesisGasLimit))
|
||||
}
|
||||
return gl
|
||||
}
|
||||
@ -255,50 +258,11 @@ func (bc *ChainManager) makeCache() {
|
||||
bc.cache = NewBlockCache(blockCacheLimit)
|
||||
}
|
||||
// load in last `blockCacheLimit` - 1 blocks. Last block is the current.
|
||||
ancestors := bc.GetAncestors(bc.currentBlock, blockCacheLimit-1)
|
||||
ancestors = append(ancestors, bc.currentBlock)
|
||||
for _, block := range ancestors {
|
||||
for _, block := range bc.GetBlocksFromHash(bc.currentBlock.Hash(), blockCacheLimit) {
|
||||
bc.cache.Push(block)
|
||||
}
|
||||
}
|
||||
|
||||
// Block creation & chain handling
|
||||
func (bc *ChainManager) NewBlock(coinbase common.Address) *types.Block {
|
||||
bc.mu.RLock()
|
||||
defer bc.mu.RUnlock()
|
||||
|
||||
var (
|
||||
root common.Hash
|
||||
parentHash common.Hash
|
||||
)
|
||||
|
||||
if bc.currentBlock != nil {
|
||||
root = bc.currentBlock.Header().Root
|
||||
parentHash = bc.lastBlockHash
|
||||
}
|
||||
|
||||
block := types.NewBlock(
|
||||
parentHash,
|
||||
coinbase,
|
||||
root,
|
||||
common.BigPow(2, 32),
|
||||
0,
|
||||
nil)
|
||||
block.SetUncles(nil)
|
||||
block.SetTransactions(nil)
|
||||
block.SetReceipts(nil)
|
||||
|
||||
parent := bc.currentBlock
|
||||
if parent != nil {
|
||||
header := block.Header()
|
||||
header.Difficulty = CalcDifficulty(block.Header(), parent.Header())
|
||||
header.Number = new(big.Int).Add(parent.Header().Number, common.Big1)
|
||||
header.GasLimit = CalcGasLimit(parent)
|
||||
}
|
||||
|
||||
return block
|
||||
}
|
||||
|
||||
func (bc *ChainManager) Reset() {
|
||||
bc.mu.Lock()
|
||||
defer bc.mu.Unlock()
|
||||
@ -463,6 +427,19 @@ func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block {
|
||||
|
||||
}
|
||||
|
||||
// GetBlocksFromHash returns the block corresponding to hash and up to n-1 ancestors.
|
||||
func (self *ChainManager) GetBlocksFromHash(hash common.Hash, n int) (blocks []*types.Block) {
|
||||
for i := 0; i < n; i++ {
|
||||
block := self.GetBlock(hash)
|
||||
if block == nil {
|
||||
break
|
||||
}
|
||||
blocks = append(blocks, block)
|
||||
hash = block.ParentHash()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// non blocking version
|
||||
func (self *ChainManager) getBlockByNumber(num uint64) *types.Block {
|
||||
key, _ := self.blockDb.Get(append(blockNumPre, big.NewInt(int64(num)).Bytes()...))
|
||||
@ -482,19 +459,6 @@ func (self *ChainManager) GetUnclesInChain(block *types.Block, length int) (uncl
|
||||
return
|
||||
}
|
||||
|
||||
func (self *ChainManager) GetAncestors(block *types.Block, length int) (blocks []*types.Block) {
|
||||
for i := 0; i < length; i++ {
|
||||
block = self.GetBlock(block.ParentHash())
|
||||
if block == nil {
|
||||
break
|
||||
}
|
||||
|
||||
blocks = append(blocks, block)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// setTotalDifficulty updates the TD of the chain manager. Note, this function
|
||||
// assumes that the `mu` mutex is held!
|
||||
func (bc *ChainManager) setTotalDifficulty(td *big.Int) {
|
||||
@ -621,14 +585,12 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
|
||||
return i, fmt.Errorf("%v: BlockFutureErr, %v > %v", BlockFutureErr, block.Time(), max)
|
||||
}
|
||||
|
||||
block.SetQueued(true)
|
||||
self.futureBlocks.Push(block)
|
||||
stats.queued++
|
||||
continue
|
||||
}
|
||||
|
||||
if IsParentErr(err) && self.futureBlocks.Has(block.ParentHash()) {
|
||||
block.SetQueued(true)
|
||||
self.futureBlocks.Push(block)
|
||||
stats.queued++
|
||||
continue
|
||||
|
Reference in New Issue
Block a user