docs: public ListenableFuture startAsync() {
          // This is run in a background thread by the Service implementation.
          if (chain == null) {
              // Just try to help catch what might be a programming error.
              log.warn("Starting up with no attached block chain. Did you forget to pass one to the constructor?");
          }
          checkState(!vUsedUp, "Cannot start a peer group twice");
          vRunning = true;
          vUsedUp = true;
          executorStartupLatch.countDown();
          // We do blocking waits during startup, so run on the executor thread.
          return executor.submit(new Runnable() {
              @Override
              public void run() {
                  try {
                      log.info("Starting ...");
                      channels.startAsync();
                      channels.awaitRunning();
                      triggerConnections();
                      setupPinging();
                  } catch (Throwable e) {
                      log.error("Exception when starting up", e);  // The executor swallows exceptions :(
                  }
              }
          });
      }