github.com/turingchain2020/turingchain@v1.1.21/blockchain/blockindex.go (about)

     1  // Copyright Turing Corp. 2018 All Rights Reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package blockchain
     6  
     7  import (
     8  	"container/list"
     9  	"math/big"
    10  	"sync"
    11  
    12  	"github.com/turingchain2020/turingchain/common/difficulty"
    13  	"github.com/turingchain2020/turingchain/types"
    14  )
    15  
    16  type blockNode struct {
    17  	parent     *blockNode
    18  	hash       []byte
    19  	Difficulty *big.Int
    20  	height     int64
    21  	statehash  []byte
    22  	broadcast  bool
    23  	pid        string
    24  	sequence   int64
    25  	BlockTime  int64
    26  }
    27  
    28  type blockIndex struct {
    29  	sync.RWMutex
    30  	index      map[string]*list.Element
    31  	cacheQueue *list.List
    32  }
    33  
    34  const (
    35  	indexCacheLimit = 102400 //目前 暂定index链缓存blocknode的个数
    36  )
    37  
    38  func initBlockNode(cfg *types.TuringchainConfig, node *blockNode, block *types.Block, broadcast bool, pid string, sequence int64) {
    39  	*node = blockNode{
    40  		hash:       block.Hash(cfg),
    41  		Difficulty: difficulty.CalcWork(block.Difficulty),
    42  		height:     block.Height,
    43  		statehash:  block.GetStateHash(),
    44  		broadcast:  broadcast,
    45  		pid:        pid,
    46  		sequence:   sequence,
    47  		BlockTime:  block.BlockTime,
    48  	}
    49  }
    50  
    51  func newBlockNode(cfg *types.TuringchainConfig, broadcast bool, block *types.Block, pid string, sequence int64) *blockNode {
    52  	var node blockNode
    53  	initBlockNode(cfg, &node, block, broadcast, pid, sequence)
    54  	return &node
    55  }
    56  
    57  //通过区块头构造blocknode节点
    58  func newBlockNodeByHeader(broadcast bool, header *types.Header, pid string, sequence int64) *blockNode {
    59  	node := &blockNode{
    60  		hash:       header.Hash,
    61  		Difficulty: difficulty.CalcWork(header.Difficulty),
    62  		height:     header.Height,
    63  		statehash:  header.GetStateHash(),
    64  		broadcast:  broadcast,
    65  		pid:        pid,
    66  		sequence:   sequence,
    67  		BlockTime:  header.BlockTime,
    68  	}
    69  	return node
    70  }
    71  
    72  var sha256Len = 32
    73  
    74  func newPreGenBlockNode() *blockNode {
    75  	node := &blockNode{
    76  		hash:       make([]byte, sha256Len),
    77  		Difficulty: big.NewInt(-1),
    78  		height:     -1,
    79  		statehash:  make([]byte, sha256Len),
    80  		broadcast:  false,
    81  		pid:        "self",
    82  	}
    83  	return node
    84  }
    85  
    86  func (node *blockNode) Ancestor(height int64) *blockNode {
    87  	if height < 0 || height > node.height {
    88  		return nil
    89  	}
    90  
    91  	n := node
    92  	for ; n != nil && n.height != height; n = n.parent {
    93  		// Intentionally left blank
    94  	}
    95  
    96  	return n
    97  }
    98  func (node *blockNode) RelativeAncestor(distance int64) *blockNode {
    99  	return node.Ancestor(node.height - distance)
   100  }
   101  
   102  func newBlockIndex() *blockIndex {
   103  	return &blockIndex{
   104  		index:      make(map[string]*list.Element),
   105  		cacheQueue: list.New(),
   106  	}
   107  }
   108  
   109  func (bi *blockIndex) HaveBlock(hash []byte) bool {
   110  	bi.RLock()
   111  	defer bi.RUnlock()
   112  	_, hasBlock := bi.index[string(hash)]
   113  
   114  	return hasBlock
   115  }
   116  
   117  func (bi *blockIndex) LookupNode(hash []byte) *blockNode {
   118  	bi.Lock()
   119  	defer bi.Unlock()
   120  
   121  	elem, ok := bi.index[string(hash)]
   122  	if ok {
   123  		return elem.Value.(*blockNode)
   124  	}
   125  
   126  	return nil
   127  }
   128  
   129  func (bi *blockIndex) AddNode(node *blockNode) {
   130  	bi.Lock()
   131  	defer bi.Unlock()
   132  
   133  	// Create entry in cache and append to cacheQueue.
   134  	elem := bi.cacheQueue.PushBack(node)
   135  	bi.index[string(node.hash)] = elem
   136  
   137  	// Maybe expire an item.
   138  	if int64(bi.cacheQueue.Len()) > indexCacheLimit {
   139  		delnode := bi.cacheQueue.Remove(bi.cacheQueue.Front()).(*blockNode)
   140  		//将删除节点的parent指针设置成空,用于释放parent节点
   141  		delnode.parent = nil
   142  		delete(bi.index, string(delnode.hash))
   143  	}
   144  }
   145  
   146  func (bi *blockIndex) UpdateNode(hash []byte, node *blockNode) bool {
   147  	bi.Lock()
   148  	defer bi.Unlock()
   149  	elem, ok := bi.index[string(hash)]
   150  	if !ok {
   151  		return false
   152  	}
   153  	elem.Value = node
   154  	delete(bi.index, string(hash))
   155  	bi.index[string(node.hash)] = elem
   156  	return true
   157  }
   158  
   159  //删除index节点
   160  func (bi *blockIndex) DelNode(hash []byte) {
   161  	bi.Lock()
   162  	defer bi.Unlock()
   163  
   164  	elem, ok := bi.index[string(hash)]
   165  	if ok {
   166  		delnode := bi.cacheQueue.Remove(elem).(*blockNode)
   167  		delnode.parent = nil
   168  		delete(bi.index, string(hash))
   169  	}
   170  }