github.com/turingchain2020/turingchain@v1.1.21/blockchain/orphanpool.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 "bytes" 9 "sync" 10 "time" 11 12 "github.com/turingchain2020/turingchain/common" 13 "github.com/turingchain2020/turingchain/types" 14 ) 15 16 var ( 17 maxOrphanBlocks = 10240 //最大孤儿block数量,考虑到同步阶段孤儿block会很多 18 ) 19 20 const orphanExpirationTime = time.Second * 600 // 孤儿过期时间设置为10分钟 21 22 //孤儿节点,就是本节点的父节点未知的block 23 type orphanBlock struct { 24 block *types.Block 25 expiration time.Time 26 broadcast bool 27 pid string 28 sequence int64 29 } 30 31 //OrphanPool 孤儿节点的存储以blockhash作为map的索引。hash转换成string 32 type OrphanPool struct { 33 orphanLock sync.RWMutex 34 orphans map[string]*orphanBlock 35 prevOrphans map[string][]*orphanBlock 36 oldestOrphan *orphanBlock 37 param *types.TuringchainConfig 38 } 39 40 //NewOrphanPool new 41 func NewOrphanPool(param *types.TuringchainConfig) *OrphanPool { 42 op := &OrphanPool{ 43 orphans: make(map[string]*orphanBlock), 44 prevOrphans: make(map[string][]*orphanBlock), 45 param: param, 46 } 47 return op 48 } 49 50 //IsKnownOrphan 判断本节点是不是已知的孤儿节点 51 func (op *OrphanPool) IsKnownOrphan(hash []byte) bool { 52 op.orphanLock.RLock() 53 _, exists := op.orphans[string(hash)] 54 op.orphanLock.RUnlock() 55 56 return exists 57 } 58 59 //GetOrphanRoot 获取本孤儿节点的祖先节点hash在孤儿链中,没有的话就返回孤儿节点本身hash 60 func (op *OrphanPool) GetOrphanRoot(hash []byte) []byte { 61 op.orphanLock.RLock() 62 defer op.orphanLock.RUnlock() 63 64 // Keep looping while the parent of each orphaned block is known and is an orphan itself. 65 orphanRoot := hash 66 prevHash := hash 67 for { 68 orphan, exists := op.orphans[string(prevHash)] 69 if !exists { 70 break 71 } 72 orphanRoot = prevHash 73 prevHash = orphan.block.GetParentHash() 74 } 75 76 return orphanRoot 77 } 78 79 //RemoveOrphanBlockByHash 通过指定的区块hash 80 //删除孤儿区块从OrphanPool中,以及prevOrphans中的index. 81 func (op *OrphanPool) RemoveOrphanBlockByHash(hash []byte) { 82 op.orphanLock.Lock() 83 defer op.orphanLock.Unlock() 84 85 orphan, exists := op.orphans[string(hash)] 86 if exists && orphan != nil { 87 chainlog.Debug("RemoveOrphanBlockByHash:", "height", orphan.block.Height, "hash", common.ToHex(hash)) 88 op.removeOrphanBlock(orphan) 89 } 90 } 91 92 //RemoveOrphanBlock 删除孤儿节点从OrphanPool中,以及prevOrphans中的index 93 func (op *OrphanPool) RemoveOrphanBlock(orphan *orphanBlock) { 94 op.orphanLock.Lock() 95 defer op.orphanLock.Unlock() 96 97 chainlog.Debug("RemoveOrphanBlock:", "height", orphan.block.Height, "hash", common.ToHex(orphan.block.Hash(op.param))) 98 99 op.removeOrphanBlock(orphan) 100 } 101 102 //RemoveOrphanBlock2 删除孤儿节点从OrphanPool中,以及prevOrphans中的index 103 func (op *OrphanPool) RemoveOrphanBlock2(block *types.Block, expiration time.Time, broadcast bool, pid string, sequence int64) { 104 b := &orphanBlock{ 105 block: block, 106 expiration: expiration, 107 broadcast: broadcast, 108 pid: pid, 109 sequence: sequence, 110 } 111 op.RemoveOrphanBlock(b) 112 } 113 114 // 删除孤儿节点从OrphanPool中,以及prevOrphans中的index 115 func (op *OrphanPool) removeOrphanBlock(orphan *orphanBlock) { 116 chainlog.Debug("removeOrphanBlock:", "orphan.block.height", orphan.block.Height, "orphan.block.hash", common.ToHex(orphan.block.Hash(op.param))) 117 118 // 从orphan pool中删除孤儿节点 119 orphanHash := orphan.block.Hash(op.param) 120 delete(op.orphans, string(orphanHash)) 121 122 // 删除parent hash中本孤儿节点的index 123 prevHash := orphan.block.GetParentHash() 124 orphans := op.prevOrphans[string(prevHash)] 125 for i := 0; i < len(orphans); i++ { 126 hash := orphans[i].block.Hash(op.param) 127 if bytes.Equal(hash, orphanHash) { 128 copy(orphans[i:], orphans[i+1:]) 129 orphans[len(orphans)-1] = nil 130 orphans = orphans[:len(orphans)-1] 131 i-- 132 } 133 } 134 op.prevOrphans[string(prevHash)] = orphans 135 136 // parent hash对应的子孤儿节点都已经删除,也需要删除本parent hash 137 if len(op.prevOrphans[string(prevHash)]) == 0 { 138 delete(op.prevOrphans, string(prevHash)) 139 } 140 } 141 142 // AddOrphanBlock adds the passed block (which is already determined to be 143 // an orphan prior calling this function) to the orphan pool. It lazily cleans 144 // up any expired blocks so a separate cleanup poller doesn't need to be run. 145 // It also imposes a maximum limit on the number of outstanding orphan 146 // blocks and will remove the oldest received orphan block if the limit is 147 // exceeded. 148 func (op *OrphanPool) AddOrphanBlock(broadcast bool, block *types.Block, pid string, sequence int64) { 149 150 chainlog.Debug("addOrphanBlock:", "block.height", block.Height, "block.hash", common.ToHex(block.Hash(op.param))) 151 152 op.orphanLock.Lock() 153 defer op.orphanLock.Unlock() 154 155 // 删除过期的孤儿节点从孤儿池中 156 for _, oBlock := range op.orphans { 157 if types.Now().After(oBlock.expiration) { 158 chainlog.Debug("addOrphanBlock:removeOrphanBlock expiration", "block.height", oBlock.block.Height, "block.hash", common.ToHex(oBlock.block.Hash(op.param))) 159 160 op.removeOrphanBlock(oBlock) 161 continue 162 } 163 // 更新最早的孤儿block 164 if op.oldestOrphan == nil || oBlock.expiration.Before(op.oldestOrphan.expiration) { 165 op.oldestOrphan = oBlock 166 } 167 } 168 169 // 孤儿池超过最大限制时,删除最早的一个孤儿block 170 if (len(op.orphans) + 1) > maxOrphanBlocks { 171 op.removeOrphanBlock(op.oldestOrphan) 172 chainlog.Debug("addOrphanBlock:removeOrphanBlock maxOrphanBlocks ", "block.height", op.oldestOrphan.block.Height, "block.hash", common.ToHex(op.oldestOrphan.block.Hash(op.param))) 173 174 op.oldestOrphan = nil 175 } 176 177 // 将本孤儿节点插入孤儿池中,并启动过期定时器 178 expiration := types.Now().Add(orphanExpirationTime) 179 oBlock := &orphanBlock{ 180 block: block, 181 expiration: expiration, 182 broadcast: broadcast, 183 pid: pid, 184 sequence: sequence, 185 } 186 op.orphans[string(block.Hash(op.param))] = oBlock 187 188 // 将本孤儿节点添加到其父hash对应的map列表中,方便快速查找 189 prevHash := block.GetParentHash() 190 op.prevOrphans[string(prevHash)] = append(op.prevOrphans[string(prevHash)], oBlock) 191 } 192 193 //getChildOrphanCount 获取父hash对应的子孤儿节点的个数,内部函数 194 func (op *OrphanPool) getChildOrphanCount(hash string) int { 195 return len(op.prevOrphans[hash]) 196 } 197 198 //getChildOrphan 获取子孤儿连,内部函数 199 func (op *OrphanPool) getChildOrphan(hash string, index int) *orphanBlock { 200 if index >= len(op.prevOrphans[hash]) { 201 return nil 202 } 203 return op.prevOrphans[hash][index] 204 } 205 206 //ProcessOrphans 孤儿链的处理,将本hash对应的子block插入chain中 207 func (op *OrphanPool) ProcessOrphans(hash []byte, b *BlockChain) error { 208 chainlog.Debug("ProcessOrphans:parent", "hash", common.ToHex(hash)) 209 op.orphanLock.Lock() 210 defer op.orphanLock.Unlock() 211 212 processHashes := make([]string, 0, 100) 213 processHashes = append(processHashes, string(hash)) 214 for len(processHashes) > 0 { 215 processHash := processHashes[0] 216 processHashes[0] = "" // Prevent GC leak. 217 processHashes = processHashes[1:] 218 219 // 处理以processHash为父hash的所有子block 220 count := b.orphanPool.getChildOrphanCount(processHash) 221 for i := 0; i < count; i++ { 222 orphan := b.orphanPool.getChildOrphan(processHash, i) 223 if orphan == nil { 224 chainlog.Debug("ProcessOrphans", "Found a nil entry at index", i, "orphan dependency list for block", common.ToHex([]byte(processHash))) 225 continue 226 } 227 228 // 从孤儿池中删除此孤儿节点 229 orphanHash := orphan.block.Hash(op.param) 230 b.orphanPool.removeOrphanBlock(orphan) 231 i-- 232 233 chainlog.Debug("processOrphans:maybeAcceptBlock", "height", orphan.block.GetHeight(), "hash", common.ToHex(orphan.block.Hash(op.param))) 234 // 尝试将此孤儿节点添加到主链 235 _, _, err := b.maybeAcceptBlock(orphan.broadcast, &types.BlockDetail{Block: orphan.block}, orphan.pid, orphan.sequence) 236 if err != nil { 237 return err 238 } 239 processHashes = append(processHashes, string(orphanHash)) 240 } 241 } 242 return nil 243 }