/**
  * Return the fingerprint of this key's parent as an int value, or zero if this key is the root
  * node of the key hierarchy. Raise an exception if the arguments are inconsistent. This method
  * exists to avoid code repetition in the constructors.
  */
 private int ascertainParentFingerprint(DeterministicKey parentKey, int parentFingerprint)
     throws IllegalArgumentException {
   if (parentFingerprint != 0) {
     if (parent != null)
       checkArgument(
           parent.getFingerprint() == parentFingerprint,
           "parent fingerprint mismatch",
           Integer.toHexString(parent.getFingerprint()),
           Integer.toHexString(parentFingerprint));
     return parentFingerprint;
   } else return 0;
 }
 /** Constructs a key from its components. This is not normally something you should use. */
 public DeterministicKey(
     ImmutableList<ChildNumber> childNumberPath,
     byte[] chainCode,
     BigInteger priv,
     @Nullable DeterministicKey parent) {
   super(priv, compressPoint(ECKey.publicPointFromPrivate(priv)));
   checkArgument(chainCode.length == 32);
   this.parent = parent;
   this.childNumberPath = checkNotNull(childNumberPath);
   this.chainCode = Arrays.copyOf(chainCode, chainCode.length);
   this.depth = this.childNumberPath.size();
   this.parentFingerprint = (parent != null) ? parent.getFingerprint() : 0;
 }
 /**
  * Deserialize an HD Key.
  *
  * @param parent The parent node in the given key's deterministic hierarchy.
  */
 public static DeterministicKey deserialize(
     NetworkParameters params, byte[] serializedKey, @Nullable DeterministicKey parent) {
   ByteBuffer buffer = ByteBuffer.wrap(serializedKey);
   int header = buffer.getInt();
   if (header != params.getBip32HeaderPriv() && header != params.getBip32HeaderPub())
     throw new IllegalArgumentException(
         "Unknown header bytes: " + toBase58(serializedKey).substring(0, 4));
   boolean pub = header == params.getBip32HeaderPub();
   int depth =
       buffer.get() & 0xFF; // convert signed byte to positive int since depth cannot be negative
   final int parentFingerprint = buffer.getInt();
   final int i = buffer.getInt();
   final ChildNumber childNumber = new ChildNumber(i);
   ImmutableList<ChildNumber> path;
   if (parent != null) {
     if (parentFingerprint == 0)
       throw new IllegalArgumentException("Parent was provided but this key doesn't have one");
     if (parent.getFingerprint() != parentFingerprint)
       throw new IllegalArgumentException("Parent fingerprints don't match");
     path = HDUtils.append(parent.getPath(), childNumber);
     if (path.size() != depth) throw new IllegalArgumentException("Depth does not match");
   } else {
     if (depth >= 1)
       // We have been given a key that is not a root key, yet we lack the object representing the
       // parent.
       // This can happen when deserializing an account key for a watching wallet.  In this case,
       // we assume that
       // the client wants to conceal the key's position in the hierarchy.  The path is truncated
       // at the
       // parent's node.
       path = ImmutableList.of(childNumber);
     else path = ImmutableList.of();
   }
   byte[] chainCode = new byte[32];
   buffer.get(chainCode);
   byte[] data = new byte[33];
   buffer.get(data);
   checkArgument(!buffer.hasRemaining(), "Found unexpected data in key");
   if (pub) {
     return new DeterministicKey(
         path,
         chainCode,
         new LazyECPoint(ECKey.CURVE.getCurve(), data),
         parent,
         depth,
         parentFingerprint);
   } else {
     return new DeterministicKey(
         path, chainCode, new BigInteger(1, data), parent, depth, parentFingerprint);
   }
 }