From 6d8c916494bfe026b8906261a92fa5f43626ea86 Mon Sep 17 00:00:00 2001 From: Baohua Yang Date: Thu, 24 Aug 2017 16:39:30 +0800 Subject: [PATCH] [FAB-5902] Refine Endorser ProcessProposal code Separate those check, validation related code into another func of preProcess(). Other minor fix in comments. Change-Id: I4cd6a372a6c9a03f126f310629765945dcbc530c Signed-off-by: Baohua Yang --- core/endorser/endorser.go | 59 ++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/core/endorser/endorser.go b/core/endorser/endorser.go index ffeb5fc6fa5..190d28e3503 100644 --- a/core/endorser/endorser.go +++ b/core/endorser/endorser.go @@ -96,6 +96,15 @@ type Endorser struct { s Support } +// validateResult provides the result of endorseProposal verification +type validateResult struct { + prop *pb.Proposal + hdrExt *pb.ChaincodeHeaderExtension + chainID string + txid string + resp *pb.ProposalResponse +} + // NewEndorserServer creates and returns a new Endorser server instance. func NewEndorserServer(privDist privateDataDistributor, s Support) pb.EndorserServer { e := &Endorser{ @@ -288,7 +297,7 @@ func (e *Endorser) endorseProposal(ctx context.Context, chainID string, txid str isSysCC := cd == nil // 1) extract the name of the escc that is requested to endorse this chaincode var escc string - //ie, not "lscc" or system chaincodes + //ie, "lscc" or system chaincodes if isSysCC { escc = "escc" } else { @@ -367,25 +376,27 @@ func (e *Endorser) endorseProposal(ctx context.Context, chainID string, txid str return pResp, nil } -// ProcessProposal process the Proposal -func (e *Endorser) ProcessProposal(ctx context.Context, signedProp *pb.SignedProposal) (*pb.ProposalResponse, error) { - addr := util.ExtractRemoteAddress(ctx) - endorserLogger.Debug("Entering: Got request from", addr) - defer endorserLogger.Debug("Exit: request from", addr) +//preProcess checks the tx proposal headers, uniqueness and ACL +func (e *Endorser) preProcess(signedProp *pb.SignedProposal) (*validateResult, error) { + vr := &validateResult{} // at first, we check whether the message is valid prop, hdr, hdrExt, err := validation.ValidateProposalMessage(signedProp) + if err != nil { - return &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}}, err + vr.resp = &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}} + return vr, err } chdr, err := putils.UnmarshalChannelHeader(hdr.ChannelHeader) if err != nil { - return &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}}, err + vr.resp = &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}} + return vr, err } shdr, err := putils.GetSignatureHeader(hdr.SignatureHeader) if err != nil { - return &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}}, err + vr.resp = &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}} + return vr, err } // block invocations to security-sensitive system chaincodes @@ -393,7 +404,8 @@ func (e *Endorser) ProcessProposal(ctx context.Context, signedProp *pb.SignedPro endorserLogger.Errorf("Error: an attempt was made by %#v to invoke system chaincode %s", shdr.Creator, hdrExt.ChaincodeId.Name) err = errors.Errorf("chaincode %s cannot be invoked through a proposal", hdrExt.ChaincodeId.Name) - return &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}}, err + vr.resp = &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}} + return vr, err } chainID := chdr.ChannelId @@ -404,13 +416,14 @@ func (e *Endorser) ProcessProposal(ctx context.Context, signedProp *pb.SignedPro txid := chdr.TxId if txid == "" { err = errors.New("invalid txID. It must be different from the empty string") - return &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}}, err + vr.resp = &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}} + return vr, err } endorserLogger.Debugf("[%s][%s] processing txid: %s", chainID, shorttxid(txid), txid) if chainID != "" { // here we handle uniqueness check and ACLs for proposals targeting a chain if _, err = e.s.GetTransactionByID(chainID, txid); err == nil { - return nil, errors.Errorf("duplicate transaction found [%s]. Creator [%x]", txid, shdr.Creator) + return vr, errors.Errorf("duplicate transaction found [%s]. Creator [%x]", txid, shdr.Creator) } // check ACL only for application chaincodes; ACLs @@ -418,7 +431,8 @@ func (e *Endorser) ProcessProposal(ctx context.Context, signedProp *pb.SignedPro if !e.s.IsSysCC(hdrExt.ChaincodeId.Name) { // check that the proposal complies with the channel's writers if err = e.s.CheckACL(signedProp, chdr, shdr, hdrExt); err != nil { - return &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}}, err + vr.resp = &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}} + return vr, err } } } else { @@ -428,6 +442,25 @@ func (e *Endorser) ProcessProposal(ctx context.Context, signedProp *pb.SignedPro // MSP of the peer instead by the call to ValidateProposalMessage above } + vr.prop, vr.hdrExt, vr.chainID, vr.txid = prop, hdrExt, chainID, txid + return vr, nil +} + +// ProcessProposal process the Proposal +func (e *Endorser) ProcessProposal(ctx context.Context, signedProp *pb.SignedProposal) (*pb.ProposalResponse, error) { + addr := util.ExtractRemoteAddress(ctx) + endorserLogger.Debug("Entering: Got request from", addr) + defer endorserLogger.Debugf("Exit: request from", addr) + + //0 -- check and validate + vr, err := e.preProcess(signedProp) + if err != nil { + resp := vr.resp + return resp, err + } + + prop, hdrExt, chainID, txid := vr.prop, vr.hdrExt, vr.chainID, vr.txid + // obtaining once the tx simulator for this proposal. This will be nil // for chainless proposals // Also obtain a history query executor for history queries, since tx simulator does not cover history