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 &paraTx
   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  }