code: func (p *Prober) Solve(authorizations []acme.Authorization) error {
  	failures := make(obtainError)
  
  	var authSolvers []*selectedAuthSolver
  	var authSolversSequential []*selectedAuthSolver
  
  	// Loop through the resources, basically through the domains.
  	// First pass just selects a solver for each authz.
  	for _, authz := range authorizations {
  		domain := challenge.GetTargetedDomain(authz)
  		if authz.Status == acme.StatusValid {
  			// Boulder might recycle recent validated authz (see issue #267)
  			log.Infof("[%s] acme: authorization already valid; skipping challenge", domain)
  			continue
  		}
  
  		if solvr := p.solverManager.chooseSolver(authz); solvr != nil {
  			authSolver := &selectedAuthSolver{authz: authz, solver: solvr}
  
  			switch s := solvr.(type) {
  			case sequential:
  				if ok, _ := s.Sequential(); ok {
  					authSolversSequential = append(authSolversSequential, authSolver)
  				} else {
  					authSolvers = append(authSolvers, authSolver)
  				}
  			default:
  				authSolvers = append(authSolvers, authSolver)
  			}
  		} else {
  			failures[domain] = fmt.Errorf("[%s] acme: could not determine solvers", domain)
  		}
  	}
  
  	parallelSolve(authSolvers, failures)
  
  	sequentialSolve(authSolversSequential, failures)
  
  	// Be careful not to return an empty failures map,
  	// for even an empty obtainError is a non-nil error value
  	if len(failures) > 0 {
  		return failures
  	}
  	return nil
  }
docs: // Solve Looks through the challenge combinations to find a solvable match.
  // Then solves the challenges in series and returns.