sample_chain/peer/shim/validate.go

308 lines
7.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package shim
import (
"bytes"
"fmt"
"log"
"schain/common/signer"
pb "schain/proto"
"schain/proto/util"
"sync"
"sync/atomic"
"time"
"github.com/pkg/errors"
)
var SuccessNum int32
var EndChannel = make(chan bool, 1)
type blockValidationRequest struct {
blockNum uint64
envelope *pb.Envelope
gIdx int
tIdx int
}
func validateSignatureHeader(sHdr *pb.SignatureHeader) error {
if sHdr == nil {
return errors.New("nil SignatureHeader provided")
}
// ensure that there is a nonce
if sHdr.Nonce == nil || len(sHdr.Nonce) == 0 {
return errors.New("invalid nonce specified in the header")
}
// ensure that there is a creator
if sHdr.Creator == nil || len(sHdr.Creator) == 0 {
return errors.New("invalid creator specified in the header")
}
return nil
}
func validateEndorserTransaction(payload *pb.Payload, hdr *pb.SignatureHeader) (*pb.KVRWSet, error) {
tx, err := util.UnmarshalTransaction(payload.Data)
if err != nil {
return nil, errors.New("transaction Unmarshal fail")
}
if tx == nil {
return nil, errors.New("nil transaction")
}
prp, err := util.UnmarshalProposalResponsePayload(tx.Payload.ProposalResponsePayload)
if err != nil {
return nil, err
}
ca, err := util.UnmarshalChaincodeAction(prp.Extension)
if err != nil {
return nil, errors.WithMessage(err, "error getting chaincodeAction from envelop")
}
csBytes, err := util.GetBytesChaincodeSpec(tx.Payload.Input)
if err != nil {
return nil, err
}
pHash, err := util.GetProposalHash(hdr, csBytes)
if err != nil {
return nil, err
}
// ensure that the proposal hash matches
if !bytes.Equal(pHash, prp.ProposalHash) {
return nil, errors.New("proposal hash does not match")
}
prpBytes, err := util.GetBytesProposalResponsePayload(pHash, ca.Response, ca.Results)
if err != nil {
return nil, err
}
for _, endorsement := range tx.Payload.Endorsements {
if err = signer.Verify(endorsement.Endorser, endorsement.Signature, append(prpBytes, endorsement.Endorser...)); err != nil {
fmt.Printf("验证失败!!!!!!!!!!!!!!!!!!!!")
return nil, err
}
//fmt.Println("验证提案签名成功 20210501")
}
kVRWSet, err := util.UnmarshalKVRWSet(ca.Results)
if err != nil {
return nil, errors.WithMessage(err, "error getting txID kVRWSet ChaincodeAction")
}
return kVRWSet, nil
}
func validateRWSet(blockNum uint64, gIdx, seq int, txRWSet *pb.KVRWSet) error {
for _, write := range txRWSet.Writes {
detection.Remove(write.Key)
}
// 验证读写集,如果发现脏读,则把这个事务中止
for _, read := range txRWSet.Reads {
stateRead, _ := State.Get(read.Key)
if stateRead == nil {
return errors.New("Failed to read a transaction from the state database")
}
if read.Version.TxNum != stateRead.Version.TxNum || read.Version.GroupNum != stateRead.Version.GroupNum ||
read.Version.BlockNum != stateRead.Version.BlockNum {
return errors.New("transaction rwSet validate failure")
}
}
for _, write := range txRWSet.Writes {
if write.IsDelete {
State.Remove(write.Key)
} else {
value := &StateDB{Value: write.Value, Version: &pb.Version{BlockNum: blockNum, GroupNum: uint64(gIdx), TxNum: uint64(seq)}}
State.Set(write.Key, value)
}
}
atomic.AddInt32(&SuccessNum, 1)
tl, ok := TxLatency.Get(txRWSet.TxID)
if ok {
tl.endTime = uint64(time.Now().UnixMilli())
TxLatency.Set(txRWSet.TxID, tl)
}
return nil
}
func validateTx(req *blockValidationRequest, vCodes *pb.ValidationCodes) {
// 验证事务,获取事务验证结果
validateCode := validateTransaction(req)
vCodes.Transaction_State = append(vCodes.Transaction_State, validateCode)
}
func validateTransaction(req *blockValidationRequest) pb.TxValidationCode {
env := req.envelope
if env == nil {
return pb.TxValidationCode_NIL_ENVELOPE
}
// 验证交易负载
payload, err := util.UnmarshalPayload(env.Payload)
if err != nil {
return pb.TxValidationCode_BAD_PAYLOAD
}
sHdr := payload.SignatureHeader
// 验证签名头
err = validateSignatureHeader(sHdr)
if err != nil {
return pb.TxValidationCode_BAD_SIGNATURE_HEADER
}
// 验证交易签名
err = signer.Verify(sHdr.Creator, env.Signature, env.Payload)
if err != nil {
fmt.Println("yanzhengshibai11")
return pb.TxValidationCode_BAD_CREATOR_SIGNATURE
}
//获取交易ID
txId, err := util.GetOrComputeTxIDFromEnvelope(env)
if err != nil {
return pb.TxValidationCode_BAD_TXID
}
// 验证交易ID
err = util.CheckTxID(
txId,
sHdr.Nonce,
sHdr.Creator)
if err != nil {
return pb.TxValidationCode_BAD_TXID
}
if payload.Data == nil {
return pb.TxValidationCode_BAD_PAYLOAD
}
//验证交易背书
rwSet, err := validateEndorserTransaction(payload, sHdr)
if err != nil {
return pb.TxValidationCode_INVALID_ENDORSER_TRANSACTION
}
//验证交易读写集
err = validateRWSet(req.blockNum, req.gIdx, req.tIdx, rwSet)
if err != nil {
return pb.TxValidationCode_BAD_RWSET
}
return pb.TxValidationCode_VALID
}
// validateBlockMataData 验证order签名是否正确
func validateBlockMataData(block *pb.Block) error {
blockHeaderBytes := util.BlockHeaderBytes(block.Header)
creator := block.Metadata.SignatureHeader.Creator
signature := block.Metadata.Signature
if err := signer.Verify(creator, signature, blockHeaderBytes); err != nil {
fmt.Println("验证bad bad bad bad bad bad")
return err
}
//fmt.Println("验证成功!!!!!!!!!!!!!!!!!!!")
return nil
}
// validateDataHash 验证区块的交易hash是否被修改
func validateDataHash(block *pb.Block) error {
dataHash := util.BlockDataHash(block.Data)
if !bytes.Equal(block.Header.DataHash, dataHash) {
return errors.New("DataHash is error")
}
return nil
}
// Validate 验证区块
func Validate(block *pb.Block) error {
var err error
var wg sync.WaitGroup
// 验证DataHash查看交易是否被修改
err = validateDataHash(block)
if err != nil {
return err
}
// 验证MateDate查看order节点签名是否正确
err = validateBlockMataData(block)
if err != nil {
return err
}
// 并发的对每个组的事务进行验证
for gIdx, data := range block.Data.Data {
wg.Add(1)
var vCodes = &pb.ValidationCodes{Transaction_State: []pb.TxValidationCode{}}
go func(gIndex int, data []byte) {
defer wg.Done()
envs, err := util.UnmarshalEnvelopes(data)
if err != nil {
log.Fatal(err)
}
// 验证每个组中的事务
for txIndex, env := range envs.Envelope {
validateTx(&blockValidationRequest{
envelope: env,
blockNum: block.Header.Number,
gIdx: gIndex,
tIdx: txIndex,
}, vCodes)
}
}(gIdx, data)
block.Metadata.Transaction_State = append(block.Metadata.Transaction_State, vCodes)
}
wg.Wait()
return nil
}
// ValidateBlock 验证区块中的交易
func ValidateBlock(msg *pb.ValidateMessage) error {
if msg.Payload != nil {
block, err := util.UnmarshalBlock(msg.Payload)
if err != nil {
return err
}
// 对区块进行验证
err = Validate(block)
if err != nil {
return err
}
// 如果区块验证成功,则把该区块写进账本
err = Blockchain.AddBlock(block)
if err != nil {
return err
}
}
if msg.Type == pb.ValidateMessage_Type_VALIDATE_COMPLETED {
EndChannel <- true
}
return nil
}