github.com/turingchain2020/turingchain@v1.1.21/blockchain/query_block.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 "github.com/turingchain2020/turingchain/common" 9 "github.com/turingchain2020/turingchain/types" 10 ) 11 12 //GetBlockByHashes 通过blockhash 获取对应的block信息 13 //从数据库获取区块不能太多,防止内存异常。一次最多获取100M区块数据从数据库 14 func (chain *BlockChain) GetBlockByHashes(hashes [][]byte) (respblocks *types.BlockDetails, err error) { 15 if int64(len(hashes)) > types.MaxBlockCountPerTime { 16 return nil, types.ErrMaxCountPerTime 17 } 18 var blocks types.BlockDetails 19 size := 0 20 for _, hash := range hashes { 21 block, err := chain.LoadBlockByHash(hash) 22 if err == nil && block != nil { 23 size += block.Size() 24 if size > types.MaxBlockSizePerTime { 25 chainlog.Error("GetBlockByHashes:overflow", "MaxBlockSizePerTime", types.MaxBlockSizePerTime) 26 return &blocks, nil 27 } 28 blocks.Items = append(blocks.Items, block) 29 } else { 30 blocks.Items = append(blocks.Items, new(types.BlockDetail)) 31 } 32 } 33 return &blocks, nil 34 } 35 36 //ProcGetBlockHash 通过blockheight 获取blockhash 37 func (chain *BlockChain) ProcGetBlockHash(height *types.ReqInt) (*types.ReplyHash, error) { 38 if height == nil || 0 > height.GetHeight() { 39 chainlog.Error("ProcGetBlockHash input err!") 40 return nil, types.ErrInvalidParam 41 } 42 CurHeight := chain.GetBlockHeight() 43 if height.GetHeight() > CurHeight { 44 chainlog.Error("ProcGetBlockHash input height err!") 45 return nil, types.ErrInvalidParam 46 } 47 var ReplyHash types.ReplyHash 48 var err error 49 ReplyHash.Hash, err = chain.blockStore.GetBlockHashByHeight(height.GetHeight()) 50 if err != nil { 51 return nil, err 52 } 53 return &ReplyHash, nil 54 } 55 56 //ProcGetBlockOverview 返回值 57 // type BlockOverview { 58 // Header head = 1; 59 // int64 txCount = 2; 60 // repeated bytes txHashes = 3;} 61 //获取BlockOverview 62 func (chain *BlockChain) ProcGetBlockOverview(ReqHash *types.ReqHash) (*types.BlockOverview, error) { 63 if ReqHash == nil { 64 chainlog.Error("ProcGetBlockOverview input err!") 65 return nil, types.ErrInvalidParam 66 } 67 var blockOverview types.BlockOverview 68 //通过height获取block 69 block, err := chain.LoadBlockByHash(ReqHash.Hash) 70 if err != nil || block == nil { 71 chainlog.Error("ProcGetBlockOverview", "GetBlock err ", err) 72 return nil, err 73 } 74 75 //获取header的信息从block中 76 var header types.Header 77 header.Version = block.Block.Version 78 header.ParentHash = block.Block.ParentHash 79 header.TxHash = block.Block.TxHash 80 header.StateHash = block.Block.StateHash 81 header.BlockTime = block.Block.BlockTime 82 header.Height = block.Block.Height 83 header.Hash = block.Block.Hash(chain.client.GetConfig()) 84 header.TxCount = int64(len(block.Block.GetTxs())) 85 header.Difficulty = block.Block.Difficulty 86 header.Signature = block.Block.Signature 87 88 blockOverview.Head = &header 89 90 blockOverview.TxCount = int64(len(block.Block.GetTxs())) 91 92 txhashs := make([][]byte, blockOverview.TxCount) 93 for index, tx := range block.Block.Txs { 94 txhashs[index] = tx.Hash() 95 } 96 blockOverview.TxHashes = txhashs 97 chainlog.Debug("ProcGetBlockOverview", "blockOverview:", blockOverview.String()) 98 return &blockOverview, nil 99 } 100 101 //ProcGetLastBlockMsg 获取最新区块信息 102 func (chain *BlockChain) ProcGetLastBlockMsg() (respblock *types.Block, err error) { 103 block := chain.blockStore.LastBlock() 104 return block, nil 105 } 106 107 //ProcGetBlockByHashMsg 获取最新区块hash 108 func (chain *BlockChain) ProcGetBlockByHashMsg(hash []byte) (respblock *types.BlockDetail, err error) { 109 blockdetail, err := chain.LoadBlockByHash(hash) 110 if err != nil { 111 return nil, err 112 } 113 return blockdetail, nil 114 } 115 116 //ProcGetHeadersMsg 返回值 117 //type Header struct { 118 // Version int64 119 // ParentHash []byte 120 // TxHash []byte 121 // Height int64 122 // BlockTime int64 123 //} 124 func (chain *BlockChain) ProcGetHeadersMsg(requestblock *types.ReqBlocks) (respheaders *types.Headers, err error) { 125 blockhight := chain.GetBlockHeight() 126 127 if requestblock.GetStart() > requestblock.GetEnd() { 128 chainlog.Error("ProcGetHeadersMsg input must Start <= End:", "Startheight", requestblock.Start, "Endheight", requestblock.End) 129 return nil, types.ErrEndLessThanStartHeight 130 } 131 if requestblock.End-requestblock.Start >= types.MaxHeaderCountPerTime { 132 return nil, types.ErrMaxCountPerTime 133 } 134 if requestblock.Start > blockhight { 135 chainlog.Error("ProcGetHeadersMsg Startheight err", "startheight", requestblock.Start, "curheight", blockhight) 136 return nil, types.ErrStartHeight 137 } 138 end := requestblock.End 139 if requestblock.End > blockhight { 140 end = blockhight 141 } 142 start := requestblock.Start 143 count := end - start + 1 144 chainlog.Debug("ProcGetHeadersMsg", "headerscount", count) 145 if count < 1 { 146 chainlog.Error("ProcGetHeadersMsg count err", "startheight", requestblock.Start, "endheight", requestblock.End, "curheight", blockhight) 147 return nil, types.ErrEndLessThanStartHeight 148 } 149 150 var headers types.Headers 151 headers.Items = make([]*types.Header, count) 152 j := 0 153 for i := start; i <= end; i++ { 154 head, err := chain.blockStore.GetBlockHeaderByHeight(i) 155 if err == nil && head != nil { 156 headers.Items[j] = head 157 } else { 158 return nil, err 159 } 160 j++ 161 } 162 chainlog.Debug("getHeaders", "len", len(headers.Items), "start", start, "end", end) 163 return &headers, nil 164 } 165 166 //ProcGetLastHeaderMsg 获取最新区块头信息 167 func (chain *BlockChain) ProcGetLastHeaderMsg() (*types.Header, error) { 168 //首先从缓存中获取最新的blockheader 169 head := chain.blockStore.LastHeader() 170 if head == nil { 171 blockhight := chain.GetBlockHeight() 172 tmpHead, err := chain.blockStore.GetBlockHeaderByHeight(blockhight) 173 if err == nil && tmpHead != nil { 174 chainlog.Error("ProcGetLastHeaderMsg from cache is nil.", "blockhight", blockhight, "hash", common.ToHex(tmpHead.Hash)) 175 return tmpHead, nil 176 } 177 return nil, err 178 179 } 180 return head, nil 181 } 182 183 /* 184 ProcGetBlockDetailsMsg EventGetBlocks(types.RequestGetBlock): rpc 模块 会向 blockchain 模块发送 EventGetBlocks(types.RequestGetBlock) 消息, 185 功能是查询 区块的信息, 回复消息是 EventBlocks(types.Blocks) 186 type ReqBlocks struct { 187 Start int64 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` 188 End int64 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"`} 189 type Blocks struct {Items []*Block `protobuf:"bytes,1,rep,name=items" json:"items,omitempty"`} 190 */ 191 func (chain *BlockChain) ProcGetBlockDetailsMsg(requestblock *types.ReqBlocks) (respblocks *types.BlockDetails, err error) { 192 blockhight := chain.GetBlockHeight() 193 if requestblock.Start > blockhight { 194 chainlog.Error("ProcGetBlockDetailsMsg Startheight err", "startheight", requestblock.Start, "curheight", blockhight) 195 return nil, types.ErrStartHeight 196 } 197 if requestblock.GetStart() > requestblock.GetEnd() { 198 chainlog.Error("ProcGetBlockDetailsMsg input must Start <= End:", "Startheight", requestblock.Start, "Endheight", requestblock.End) 199 return nil, types.ErrEndLessThanStartHeight 200 } 201 if requestblock.End-requestblock.Start >= types.MaxBlockCountPerTime { 202 return nil, types.ErrMaxCountPerTime 203 } 204 chainlog.Debug("ProcGetBlockDetailsMsg", "Start", requestblock.Start, "End", requestblock.End, "Isdetail", requestblock.IsDetail) 205 206 end := requestblock.End 207 if requestblock.End > blockhight { 208 end = blockhight 209 } 210 start := requestblock.Start 211 count := end - start + 1 212 chainlog.Debug("ProcGetBlockDetailsMsg", "blockscount", count) 213 214 var blocks types.BlockDetails 215 blocks.Items = make([]*types.BlockDetail, count) 216 j := 0 217 for i := start; i <= end; i++ { 218 block, err := chain.GetBlock(i) 219 if err == nil && block != nil { 220 if requestblock.IsDetail { 221 blocks.Items[j] = block 222 } else { 223 var blockdetail types.BlockDetail 224 blockdetail.Block = block.Block 225 blockdetail.Receipts = nil 226 blocks.Items[j] = &blockdetail 227 } 228 } else { 229 return nil, err 230 } 231 j++ 232 } 233 //print 234 if requestblock.IsDetail { 235 for _, blockinfo := range blocks.Items { 236 chainlog.Debug("ProcGetBlocksMsg", "blockinfo", blockinfo.String()) 237 } 238 } 239 return &blocks, nil 240 } 241 242 //ProcAddBlockMsg 处理从peer对端同步过来的block消息 243 func (chain *BlockChain) ProcAddBlockMsg(broadcast bool, blockdetail *types.BlockDetail, pid string) (*types.BlockDetail, error) { 244 beg := types.Now() 245 defer func() { 246 chainlog.Debug("ProcAddBlockMsg", "height", blockdetail.GetBlock().GetHeight(), 247 "txCount", len(blockdetail.GetBlock().GetTxs()), "recvFrom", pid, "cost", types.Since(beg)) 248 }() 249 250 block := blockdetail.Block 251 if block == nil { 252 chainlog.Error("ProcAddBlockMsg input block is null") 253 return nil, types.ErrInvalidParam 254 } 255 b, ismain, isorphan, err := chain.ProcessBlock(broadcast, blockdetail, pid, true, -1) 256 if b != nil { 257 blockdetail = b 258 } 259 260 height := blockdetail.Block.GetHeight() 261 hash := blockdetail.Block.Hash(chain.client.GetConfig()) 262 263 //更新广播block的高度,设置请求过来的区块已经处理完成 264 if broadcast { 265 chain.UpdateRcvCastBlkHeight(height) 266 } else { 267 //syncTask 运行时设置对应的blockdone 268 if chain.syncTask.InProgress() { 269 chain.syncTask.Done(height) 270 } 271 //downLoadTask 运行时设置对应的blockdone 272 if chain.downLoadTask.InProgress() { 273 chain.downLoadTask.Done(height) 274 } 275 } 276 if pid == "self" { 277 if err != nil { 278 return nil, err 279 } 280 if b == nil { 281 return nil, types.ErrExecBlockNil 282 } 283 } 284 chainlog.Debug("ProcAddBlockMsg result:", "height", height, "ismain", ismain, "isorphan", isorphan, "hash", common.ToHex(hash), "err", err) 285 return blockdetail, err 286 } 287 288 //getBlockHashes 获取指定height区间对应的blockhashes 289 func (chain *BlockChain) getBlockHashes(startheight, endheight int64) types.ReqHashes { 290 var reqHashes types.ReqHashes 291 for i := startheight; i <= endheight; i++ { 292 hash, err := chain.blockStore.GetBlockHashByHeight(i) 293 if hash == nil || err != nil { 294 storeLog.Error("getBlockHashesByHeight", "height", i, "error", err) 295 reqHashes.Hashes = append(reqHashes.Hashes, nil) 296 } else { 297 reqHashes.Hashes = append(reqHashes.Hashes, hash) 298 } 299 } 300 return reqHashes 301 }