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 }