/**
  * Return the root hash of a binary tree with leaves at the given depths and with the given hash
  * val in each leaf.
  */
 byte[] hashed(byte[] val, Integer... depths) {
   ArrayDeque<Integer> dstack = new ArrayDeque<Integer>();
   ArrayDeque<byte[]> hstack = new ArrayDeque<byte[]>();
   Iterator<Integer> depthiter = Arrays.asList(depths).iterator();
   if (depthiter.hasNext()) {
     dstack.push(depthiter.next());
     hstack.push(val);
   }
   while (depthiter.hasNext()) {
     Integer depth = depthiter.next();
     byte[] hash = val;
     while (depth.equals(dstack.peek())) {
       // consume the stack
       hash = Hashable.binaryHash(hstack.pop(), hash);
       depth = dstack.pop() - 1;
     }
     dstack.push(depth);
     hstack.push(hash);
   }
   assert hstack.size() == 1;
   return hstack.pop();
 }