Skip to content

Commit

Permalink
Evaluate() error response for node chaincode
Browse files Browse the repository at this point in the history
The gateway Evaluate() method is not returning the error response to the client for node chaincodes. The code path for node chaincode errors is different than for Go chaincodes (this is a known separate issue).
It turns out the endorser is handling this difference and populates the Response field of the ProposalResponse accordingly.  The gateway needs to use this field rather than the one in the ChaincodeAction structure.

Signed-off-by: andrew-coleman <andrew_coleman@uk.ibm.com>
  • Loading branch information
andrew-coleman authored and denyeart committed Sep 30, 2021
1 parent 0625b10 commit 6656f72
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 40 deletions.
23 changes: 10 additions & 13 deletions internal/pkg/gateway/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,20 +66,22 @@ func (gs *Server) Evaluate(ctx context.Context, request *gp.EvaluateRequest) (*g

response, err := endorser.client.ProcessProposal(ctx, signedProposal)
if err != nil {
logger.Debugw("Evaluate call to endorser failed", "channel", request.ChannelId, "txid", request.TransactionId, "endorserAddress", endorser.endpointConfig.address, "endorserMspid", endorser.endpointConfig.mspid, "error", err)
logger.Debugw("Evaluate call to endorser failed", "chaincode", chaincodeID, "channel", channel, "txid", request.TransactionId, "endorserAddress", endorser.endpointConfig.address, "endorserMspid", endorser.endpointConfig.mspid, "error", err)
return nil, wrappedRpcError(err, "failed to evaluate transaction", endpointError(endorser.endpointConfig, err))
}

retVal, err := getTransactionResponse(response)
if err != nil {
logger.Debugw("Evaluate call to endorser returned a malformed or error response", "channel", request.ChannelId, "txid", request.TransactionId, "endorserAddress", endorser.endpointConfig.address, "endorserMspid", endorser.endpointConfig.mspid, "error", err)
return nil, rpcError(codes.Unknown, err.Error(), endpointError(endorser.endpointConfig, err))
rr := response.GetResponse()
if rr != nil && (rr.Status < 200 || rr.Status >= 400) {
logger.Debugw("Evaluate call to endorser returned a malformed or error response", "chaincode", chaincodeID, "channel", channel, "txid", request.TransactionId, "endorserAddress", endorser.endpointConfig.address, "endorserMspid", endorser.endpointConfig.mspid, "status", rr.Status, "message", rr.Message)
err = fmt.Errorf("error %d returned from chaincode %s on channel %s: %s", rr.Status, chaincodeID, channel, rr.Message)
return nil, rpcError(codes.Unknown, "error returned from chaincode: "+rr.Message, endpointError(endorser.endpointConfig, err))
}

evaluateResponse := &gp.EvaluateResponse{
Result: retVal,
Result: rr,
}

logger.Debugw("Evaluate call to endorser returned success", "channel", request.ChannelId, "txid", request.TransactionId, "endorserAddress", endorser.endpointConfig.address, "endorserMspid", endorser.endpointConfig.mspid, "status", retVal.GetStatus(), "message", retVal.GetMessage())
logger.Debugw("Evaluate call to endorser returned success", "channel", request.ChannelId, "txid", request.TransactionId, "endorserAddress", endorser.endpointConfig.address, "endorserMspid", endorser.endpointConfig.mspid, "status", rr.GetStatus(), "message", rr.GetMessage())
return evaluateResponse, nil
}

Expand Down Expand Up @@ -247,13 +249,8 @@ func (gs *Server) Endorse(ctx context.Context, request *gp.EndorseRequest) (*gp.
return nil, status.Errorf(codes.Aborted, "failed to assemble transaction: %s", err)
}

retVal, err := getTransactionResponse(responses[0])
if err != nil {
return nil, status.Errorf(codes.Aborted, "failed to extract transaction response: %s", err)
}

endorseResponse := &gp.EndorseResponse{
Result: retVal,
Result: responses[0].GetResponse(),
PreparedTransaction: env,
}
return endorseResponse, nil
Expand Down
4 changes: 2 additions & 2 deletions internal/pkg/gateway/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,11 +309,11 @@ func TestEvaluate(t *testing.T) {
proposalResponseStatus: 400,
proposalResponseMessage: "Mock chaincode error",
},
errString: "rpc error: code = Unknown desc = error 400, Mock chaincode error",
errString: "rpc error: code = Unknown desc = error returned from chaincode: Mock chaincode error",
errDetails: []*pb.EndpointError{{
Address: "peer1:8051",
MspId: "msp1",
Message: "error 400, Mock chaincode error",
Message: "error 400 returned from chaincode test_chaincode on channel test_channel: Mock chaincode error",
}},
},
{
Expand Down
25 changes: 0 additions & 25 deletions internal/pkg/gateway/apiutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,6 @@ import (
"google.golang.org/grpc/status"
)

func getTransactionResponse(response *peer.ProposalResponse) (*peer.Response, error) {
var retVal *peer.Response

if response.GetPayload() != nil {
payload, err := protoutil.UnmarshalProposalResponsePayload(response.Payload)
if err != nil {
return nil, err
}

extension, err := protoutil.UnmarshalChaincodeAction(payload.Extension)
if err != nil {
return nil, err
}

if extension.GetResponse() != nil {
if extension.Response.Status < 200 || extension.Response.Status >= 400 {
return nil, fmt.Errorf("error %d, %s", extension.Response.Status, extension.Response.Message)
}
retVal = extension.Response
}
}

return retVal, nil
}

func getChannelAndChaincodeFromSignedProposal(signedProposal *peer.SignedProposal) (string, string, bool, error) {
if signedProposal == nil {
return "", "", false, fmt.Errorf("a signed proposal is required")
Expand Down

0 comments on commit 6656f72

Please sign in to comment.