//call specified chaincode (system or user) func (e *Endorser) callChaincode(ctxt context.Context, chainID string, txid string, prop *pb.Proposal, cis *pb.ChaincodeInvocationSpec, cid *pb.ChaincodeID, txsim ledger.TxSimulator) ([]byte, *pb.ChaincodeEvent, error) { var err error var b []byte var ccevent *pb.ChaincodeEvent if txsim != nil { ctxt = context.WithValue(ctxt, chaincode.TXSimulatorKey, txsim) } //is this a system chaincode syscc := chaincode.IsSysCC(cid.Name) cccid := chaincode.NewCCContext(chainID, cid.Name, "", txid, syscc, prop) b, ccevent, err = chaincode.ExecuteChaincode(ctxt, cccid, cis.ChaincodeSpec.CtorMsg.Args) if err != nil { return nil, nil, err } //----- BEGIN - SECTION THAT MAY NEED TO BE DONE IN LCCC ------ //if this a call to deploy a chaincode, We need a mechanism //to pass TxSimulator into LCCC. Till that is worked out this //special code does the actual deploy, upgrade here so as to collect //all state under one TxSimulator // //NOTE that if there's an error all simulation, including the chaincode //table changes in lccc will be thrown away if cid.Name == "lccc" && len(cis.ChaincodeSpec.CtorMsg.Args) == 3 && (string(cis.ChaincodeSpec.CtorMsg.Args[0]) == "deploy" || string(cis.ChaincodeSpec.CtorMsg.Args[0]) == "upgrade") { var cds *pb.ChaincodeDeploymentSpec cds, err = putils.GetChaincodeDeploymentSpec(cis.ChaincodeSpec.CtorMsg.Args[2]) if err != nil { return nil, nil, err } //this should not be a system chaincode if chaincode.IsSysCC(cds.ChaincodeSpec.ChaincodeID.Name) { return nil, nil, fmt.Errorf("attempting to deploy a system chaincode %s/%s", cds.ChaincodeSpec.ChaincodeID.Name, chainID) } cccid = chaincode.NewCCContext(chainID, cds.ChaincodeSpec.ChaincodeID.Name, "", txid, false, prop) err = e.deploy(ctxt, cccid, cds) if err != nil { return nil, nil, err } } //----- END ------- return b, ccevent, err }
//endorse the proposal by calling the ESCC func (e *Endorser) endorseProposal(ctx context.Context, chainID string, txid string, proposal *pb.Proposal, simRes []byte, event *pb.ChaincodeEvent, visibility []byte, ccid *pb.ChaincodeID, txsim ledger.TxSimulator) (*pb.ProposalResponse, error) { endorserLogger.Infof("endorseProposal starts for chainID %s, ccid %s", chainID, ccid) // 1) extract the chaincodeDeploymentSpec for the chaincode we are invoking; we need it to get the escc var escc string if !chaincode.IsSysCC(ccid.Name) { depPayload, err := e.getCDSFromLCCC(ctx, chainID, txid, proposal, ccid.Name, txsim) if err != nil { return nil, fmt.Errorf("failed to obtain cds for %s - %s", ccid, err) } _, err = putils.GetChaincodeDeploymentSpec(depPayload) if err != nil { return nil, fmt.Errorf("failed to unmarshal cds for %s - %s", ccid, err) } // FIXME: pick the right escc from cds - currently cds doesn't have this info escc = "escc" } else { // FIXME: getCDSFromLCCC seems to fail for lccc - not sure this is expected? escc = "escc" } endorserLogger.Infof("endorseProposal info: escc for cid %s is %s", ccid, escc) // marshalling event bytes var err error var eventBytes []byte if event != nil { eventBytes, err = putils.GetBytesChaincodeEvent(event) if err != nil { return nil, fmt.Errorf("failed to marshal event bytes - %s", err) } } // 3) call the ESCC we've identified // arguments: // args[0] - function name (not used now) // args[1] - serialized Header object // args[2] - serialized ChaincodeProposalPayload object // args[3] - binary blob of simulation results // args[4] - serialized events // args[5] - payloadVisibility args := [][]byte{[]byte(""), proposal.Header, proposal.Payload, simRes, eventBytes, visibility} ecccis := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_GOLANG, ChaincodeID: &pb.ChaincodeID{Name: escc}, CtorMsg: &pb.ChaincodeInput{Args: args}}} prBytes, _, err := e.callChaincode(ctx, chainID, txid, proposal, ecccis, &pb.ChaincodeID{Name: escc}, txsim) if err != nil { return nil, err } // Note that we do not extract any simulation results from // the call to ESCC. This is intentional becuse ESCC is meant // to endorse (i.e. sign) the simulation results of a chaincode, // but it can't obviously sign its own. Furthermore, ESCC runs // on private input (its own signing key) and so if it were to // produce simulationr results, they are likely to be different // from other ESCCs, which would stand in the way of the // endorsement process. //3 -- respond pResp, err := putils.GetProposalResponse(prBytes) if err != nil { return nil, err } return pResp, nil }