github.com/turingchain2020/turingchain@v1.1.21/types/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 types 6 7 import ( 8 "bytes" 9 "runtime" 10 "sync" 11 12 "github.com/turingchain2020/turingchain/common" 13 "github.com/turingchain2020/turingchain/common/crypto" 14 proto "github.com/golang/protobuf/proto" 15 ) 16 17 // Hash 获取block的hash值 18 func (block *Block) Hash(cfg *TuringchainConfig) []byte { 19 if cfg.IsFork(block.Height, "ForkBlockHash") { 20 return block.HashNew() 21 } 22 return block.HashOld() 23 } 24 25 //HashByForkHeight hash 通过自己设置的fork 高度计算 hash 26 func (block *Block) HashByForkHeight(forkheight int64) []byte { 27 if block.Height >= forkheight { 28 return block.HashNew() 29 } 30 return block.HashOld() 31 } 32 33 //HashNew 新版本的Hash 34 func (block *Block) HashNew() []byte { 35 data, err := proto.Marshal(block.getHeaderHashNew()) 36 if err != nil { 37 panic(err) 38 } 39 return common.Sha256(data) 40 } 41 42 //HashOld 老版本的hash 43 func (block *Block) HashOld() []byte { 44 data, err := proto.Marshal(block.getHeaderHashOld()) 45 if err != nil { 46 panic(err) 47 } 48 return common.Sha256(data) 49 } 50 51 // Size 获取block的Size 52 func (block *Block) Size() int { 53 return Size(block) 54 } 55 56 // GetHeader 获取block的Header信息 57 func (block *Block) GetHeader(cfg *TuringchainConfig) *Header { 58 head := &Header{} 59 head.Version = block.Version 60 head.ParentHash = block.ParentHash 61 head.TxHash = block.TxHash 62 head.BlockTime = block.BlockTime 63 head.Height = block.Height 64 head.Difficulty = block.Difficulty 65 head.StateHash = block.StateHash 66 head.TxCount = int64(len(block.Txs)) 67 head.Hash = block.Hash(cfg) 68 return head 69 } 70 71 func (block *Block) getHeaderHashOld() *Header { 72 head := &Header{} 73 head.Version = block.Version 74 head.ParentHash = block.ParentHash 75 head.TxHash = block.TxHash 76 head.BlockTime = block.BlockTime 77 head.Height = block.Height 78 return head 79 } 80 81 func (block *Block) getHeaderHashNew() *Header { 82 head := &Header{} 83 head.Version = block.Version 84 head.ParentHash = block.ParentHash 85 head.TxHash = block.TxHash 86 head.BlockTime = block.BlockTime 87 head.Height = block.Height 88 head.Difficulty = block.Difficulty 89 head.StateHash = block.StateHash 90 head.TxCount = int64(len(block.Txs)) 91 return head 92 } 93 94 // VerifySignature 验证区块和交易的签名,支持指定需要验证的交易 95 func VerifySignature(cfg *TuringchainConfig, block *Block, txs []*Transaction) bool { 96 //检查区块的签名 97 if !block.verifySignature(cfg) { 98 return false 99 } 100 //检查交易的签名 101 return verifyTxsSignature(txs) 102 } 103 104 // CheckSign 检测block的签名,以及交易的签名 105 func (block *Block) CheckSign(cfg *TuringchainConfig) bool { 106 return VerifySignature(cfg, block, block.Txs) 107 } 108 109 func (block *Block) verifySignature(cfg *TuringchainConfig) bool { 110 if block.GetSignature() == nil { 111 return true 112 } 113 hash := block.Hash(cfg) 114 return CheckSign(hash, "", block.GetSignature()) 115 } 116 117 func verifyTxsSignature(txs []*Transaction) bool { 118 119 //没有需要要验签的交易,直接返回 120 if len(txs) == 0 { 121 return true 122 } 123 done := make(chan struct{}) 124 defer close(done) 125 taskes := gen(done, txs) 126 cpuNum := runtime.NumCPU() 127 // Start a fixed number of goroutines to read and digest files. 128 c := make(chan result) // HLc 129 var wg sync.WaitGroup 130 wg.Add(cpuNum) 131 for i := 0; i < cpuNum; i++ { 132 go func() { 133 checksign(done, taskes, c) // HLc 134 wg.Done() 135 }() 136 } 137 go func() { 138 wg.Wait() 139 close(c) // HLc 140 }() 141 // End of pipeline. OMIT 142 for r := range c { 143 if !r.isok { 144 return false 145 } 146 } 147 return true 148 } 149 150 func gen(done <-chan struct{}, task []*Transaction) <-chan *Transaction { 151 ch := make(chan *Transaction) 152 go func() { 153 defer func() { 154 close(ch) 155 }() 156 for i := 0; i < len(task); i++ { 157 select { 158 case ch <- task[i]: 159 case <-done: 160 return 161 } 162 } 163 }() 164 return ch 165 } 166 167 type result struct { 168 isok bool 169 } 170 171 func check(data *Transaction) bool { 172 return data.CheckSign() 173 } 174 175 func checksign(done <-chan struct{}, taskes <-chan *Transaction, c chan<- result) { 176 for task := range taskes { 177 select { 178 case c <- result{check(task)}: 179 case <-done: 180 return 181 } 182 } 183 } 184 185 // CheckSign 检测签名 186 func CheckSign(data []byte, execer string, sign *Signature) bool { 187 //GetDefaultSign: 系统内置钱包,非插件中的签名 188 c, err := crypto.New(GetSignName(execer, int(sign.Ty))) 189 if err != nil { 190 return false 191 } 192 return c.Validate(data, sign.Pubkey, sign.Signature) == nil 193 } 194 195 //FilterParaTxsByTitle 过滤指定title的平行链交易 196 //1,单笔平行连交易 197 //2,交易组中的平行连交易,需要将整个交易组都过滤出来 198 //目前暂时不返回单个交易的proof证明路径, 199 //后面会将平行链的交易组装到一起,构成一个子roothash。会返回子roothash的proof证明路径 200 func (blockDetail *BlockDetail) FilterParaTxsByTitle(cfg *TuringchainConfig, title string) *ParaTxDetail { 201 var paraTx ParaTxDetail 202 paraTx.Header = blockDetail.Block.GetHeader(cfg) 203 204 for i := 0; i < len(blockDetail.Block.Txs); i++ { 205 tx := blockDetail.Block.Txs[i] 206 if IsSpecificParaExecName(title, string(tx.Execer)) { 207 208 //过滤交易组中的para交易,需要将整个交易组都过滤出来 209 if tx.GroupCount >= 2 { 210 txDetails, endIdx := blockDetail.filterParaTxGroup(tx, i) 211 paraTx.TxDetails = append(paraTx.TxDetails, txDetails...) 212 i = endIdx - 1 213 continue 214 } 215 216 //单笔para交易 217 var txDetail TxDetail 218 txDetail.Tx = tx 219 txDetail.Receipt = blockDetail.Receipts[i] 220 txDetail.Index = uint32(i) 221 paraTx.TxDetails = append(paraTx.TxDetails, &txDetail) 222 223 } 224 } 225 return ¶Tx 226 } 227 228 //filterParaTxGroup 获取para交易所在交易组信息 229 func (blockDetail *BlockDetail) filterParaTxGroup(tx *Transaction, index int) ([]*TxDetail, int) { 230 var headIdx int 231 var txDetails []*TxDetail 232 233 for i := index; i >= 0; i-- { 234 if bytes.Equal(tx.Header, blockDetail.Block.Txs[i].Hash()) { 235 headIdx = i 236 break 237 } 238 } 239 240 endIdx := headIdx + int(tx.GroupCount) 241 for i := headIdx; i < endIdx; i++ { 242 var txDetail TxDetail 243 txDetail.Tx = blockDetail.Block.Txs[i] 244 txDetail.Receipt = blockDetail.Receipts[i] 245 txDetail.Index = uint32(i) 246 txDetails = append(txDetails, &txDetail) 247 } 248 return txDetails, endIdx 249 } 250 251 // Size 获取blockDetail的Size 252 func (blockDetail *BlockDetail) Size() int { 253 return Size(blockDetail) 254 } 255 256 // Size 获取header的Size 257 func (header *Header) Size() int { 258 return Size(header) 259 } 260 261 // Size 获取paraTxDetail的Size 262 func (paraTxDetail *ParaTxDetail) Size() int { 263 return Size(paraTxDetail) 264 }