code: func SendProposal(reqCtx reqContext.Context, proposal *fab.TransactionProposal, targets []fab.ProposalProcessor) ([]*fab.TransactionProposalResponse, error) {
  
  	if proposal == nil {
  		return nil, errors.New("proposal is required")
  	}
  
  	if len(targets) < 1 {
  		return nil, errors.New("targets is required")
  	}
  
  	for _, p := range targets {
  		if p == nil {
  			return nil, errors.New("target is nil")
  		}
  	}
  
  	targets = getTargetsWithoutDuplicates(targets)
  
  	ctx, ok := context.RequestClientContext(reqCtx)
  	if !ok {
  		return nil, errors.New("failed get client context from reqContext for signProposal")
  	}
  	signedProposal, err := signProposal(ctx, proposal.Proposal)
  	if err != nil {
  		return nil, errors.WithMessage(err, "sign proposal failed")
  	}
  
  	request := fab.ProcessProposalRequest{SignedProposal: signedProposal}
  
  	var responseMtx sync.Mutex
  	var transactionProposalResponses []*fab.TransactionProposalResponse
  	var wg sync.WaitGroup
  	errs := multi.Errors{}
  
  	for _, p := range targets {
  		wg.Add(1)
  		go func(processor fab.ProposalProcessor) {
  			defer wg.Done()
  
  			// TODO: The RPC should be timed-out.
  			//resp, err := processor.ProcessTransactionProposal(context.NewRequestOLD(ctx), request)
  			resp, err := processor.ProcessTransactionProposal(reqCtx, request)
  			if err != nil {
  				logger.Debugf("Received error response from txn proposal processing: %s", err)
  				responseMtx.Lock()
  				errs = append(errs, err)
  				responseMtx.Unlock()
  				return
  			}
  
  			responseMtx.Lock()
  			transactionProposalResponses = append(transactionProposalResponses, resp)
  			responseMtx.Unlock()
  		}(p)
  	}
  	wg.Wait()
  
  	return transactionProposalResponses, errs.ToError()
  }
docs: // SendProposal sends a TransactionProposal to ProposalProcessor.