code: func CreateProposalResponse(hdrbytes []byte, payl []byte, response *peer.Response, results []byte, events []byte, ccid *peer.ChaincodeID, visibility []byte, signingEndorser msp.SigningIdentity) (*peer.ProposalResponse, error) {
  	hdr, err := GetHeader(hdrbytes)
  	if err != nil {
  		return nil, err
  	}
  
  	// obtain the proposal hash given proposal header, payload and the
  	// requested visibility
  	pHashBytes, err := GetProposalHash1(hdr, payl, visibility)
  	if err != nil {
  		return nil, errors.WithMessage(err, "error computing proposal hash")
  	}
  
  	// get the bytes of the proposal response payload - we need to sign them
  	prpBytes, err := GetBytesProposalResponsePayload(pHashBytes, response, results, events, ccid)
  	if err != nil {
  		return nil, err
  	}
  
  	// serialize the signing identity
  	endorser, err := signingEndorser.Serialize()
  	if err != nil {
  		return nil, errors.WithMessage(err, fmt.Sprintf("error serializing signing identity for %s", signingEndorser.GetIdentifier()))
  	}
  
  	// sign the concatenation of the proposal response and the serialized
  	// endorser identity with this endorser's key
  	signature, err := signingEndorser.Sign(append(prpBytes, endorser...))
  	if err != nil {
  		return nil, errors.WithMessage(err, "could not sign the proposal response payload")
  	}
  
  	resp := &peer.ProposalResponse{
  		// Timestamp: TODO!
  		Version: 1, // TODO: pick right version number
  		Endorsement: &peer.Endorsement{
  			Signature: signature,
  			Endorser:  endorser,
  		},
  		Payload: prpBytes,
  		Response: &peer.Response{
  			Status:  200,
  			Message: "OK",
  		},
  	}
  
  	return resp, nil
  }
docs: // CreateProposalResponse creates a proposal response.