/**
   * Pre-generate enough keys to reach the lookahead size, but only if there are more than the
   * lookaheadThreshold to be generated, so that the Bloom filter does not have to be regenerated
   * that often.
   *
   * <p>The returned mutable list of keys must be inserted into the basic key chain.
   */
  private List<DeterministicKey> maybeLookAhead(
      DeterministicKey parent, int issued, int lookaheadSize, int lookaheadThreshold) {
    checkState(lock.isHeldByCurrentThread());
    final int numChildren = hierarchy.getNumChildren(parent.getPath());
    final int needed = issued + lookaheadSize + lookaheadThreshold - numChildren;

    if (needed <= lookaheadThreshold) return new ArrayList<DeterministicKey>();

    log.info(
        "{} keys needed for {} = {} issued + {} lookahead size + {} lookahead threshold - {} num children",
        needed,
        parent.getPathAsString(),
        issued,
        lookaheadSize,
        lookaheadThreshold,
        numChildren);

    List<DeterministicKey> result = new ArrayList<DeterministicKey>(needed);
    long now = System.currentTimeMillis();
    int nextChild = numChildren;
    for (int i = 0; i < needed; i++) {
      DeterministicKey key = HDKeyDerivation.deriveThisOrNextChildKey(parent, nextChild);
      key = key.getPubOnly();
      hierarchy.putKey(key);
      result.add(key);
      nextChild = key.getChildNumber().num() + 1;
    }
    log.info("Took {} msec", System.currentTimeMillis() - now);
    return result;
  }
 public Bip32HDKeyManager() {
   keys.put(
       new int[] {},
       new EncryptedDeterministicKey(
           HDKeyDerivation.createMasterPrivateKey(Random.get_bytes(16))));
   set_has_private_keys(true);
   set_password_protected(false);
 }
 private void checkForBitFlip(DeterministicKey k) {
   DeterministicKey parent = checkNotNull(k.getParent());
   byte[] rederived =
       HDKeyDerivation.deriveChildKeyBytesFromPublic(
               parent, k.getChildNumber(), HDKeyDerivation.PublicDeriveMode.WITH_INVERSION)
           .keyBytes;
   byte[] actual = k.getPubKey();
   if (!Arrays.equals(rederived, actual))
     throw new IllegalStateException(
         String.format(
             "Bit-flip check failed: %s vs %s",
             Arrays.toString(rederived), Arrays.toString(actual)));
 }
 DeterministicKeyChain(DeterministicSeed seed, @Nullable KeyCrypter crypter) {
   this.seed = seed;
   basicKeyChain = new BasicKeyChain(crypter);
   if (!seed.isEncrypted()) {
     rootKey = HDKeyDerivation.createMasterPrivateKey(checkNotNull(seed.getSeedBytes()));
     rootKey.setCreationTimeSeconds(seed.getCreationTimeSeconds());
     initializeHierarchyUnencrypted(rootKey);
   }
   // Else...
   // We can't initialize ourselves with just an encrypted seed, so we expected deserialization
   // code to do the
   // rest of the setup (loading the root key).
 }