static int differenceHelper(MerkleTree ltree, MerkleTree rtree, List<TreeRange> diff, TreeRange active)
    {
        if (active.depth == Byte.MAX_VALUE)
            return CONSISTENT;

        Token midpoint = ltree.partitioner().midpoint(active.left, active.right);
        TreeDifference left = new TreeDifference(active.left, midpoint, inc(active.depth));
        TreeDifference right = new TreeDifference(midpoint, active.right, inc(active.depth));
        byte[] lhash, rhash;
        Hashable lnode, rnode;

        // see if we should recurse left
        lnode = ltree.find(left);
        rnode = rtree.find(left);
        lhash = lnode.hash();
        rhash = rnode.hash();
        left.setSize(lnode.sizeOfRange(), rnode.sizeOfRange());
        left.setRows(lnode.rowsInRange(), rnode.rowsInRange());

        int ldiff = CONSISTENT;
        boolean lreso = lhash != null && rhash != null;
        if (lreso && !Arrays.equals(lhash, rhash))
            ldiff = differenceHelper(ltree, rtree, diff, left);
        else if (!lreso)
            ldiff = FULLY_INCONSISTENT;

        // see if we should recurse right
        lnode = ltree.find(right);
        rnode = rtree.find(right);
        lhash = lnode.hash();
        rhash = rnode.hash();
        right.setSize(lnode.sizeOfRange(), rnode.sizeOfRange());
        right.setRows(lnode.rowsInRange(), rnode.rowsInRange());

        int rdiff = CONSISTENT;
        boolean rreso = lhash != null && rhash != null;
        if (rreso && !Arrays.equals(lhash, rhash))
            rdiff = differenceHelper(ltree, rtree, diff, right);
        else if (!rreso)
            rdiff = FULLY_INCONSISTENT;

        if (ldiff == FULLY_INCONSISTENT && rdiff == FULLY_INCONSISTENT)
        {
            // both children are fully inconsistent
            return FULLY_INCONSISTENT;
        }
        else if (ldiff == FULLY_INCONSISTENT)
        {
            diff.add(left);
            return PARTIALLY_INCONSISTENT;
        }
        else if (rdiff == FULLY_INCONSISTENT)
        {
            diff.add(right);
            return PARTIALLY_INCONSISTENT;
        }
        return PARTIALLY_INCONSISTENT;
    }
static int differenceHelper ( MerkleTree ltree , MerkleTree rtree , List < TreeRange > diff , TreeRange active ) { if ( active . depth == Byte . MAX_VALUE ) return CONSISTENT ; Token midpoint = ltree . partitioner ( ) . midpoint ( active . left , active . right ) ; TreeDifference left = new TreeDifference ( active . left , midpoint , inc ( active . depth ) ) ; TreeDifference right = new TreeDifference ( midpoint , active . right , inc ( active . depth ) ) ; byte [ ] lhash , rhash ; Hashable lnode , rnode ; lnode = ltree . find ( left ) ; rnode = rtree . find ( left ) ; lhash = lnode . hash ( ) ; rhash = rnode . hash ( ) ; left . setSize ( lnode . sizeOfRange ( ) , rnode . sizeOfRange ( ) ) ; left . setRows ( lnode . rowsInRange ( ) , rnode . rowsInRange ( ) ) ; int ldiff = CONSISTENT ; boolean lreso = lhash != null && rhash != null ; if ( lreso && ! Arrays . equals ( lhash , rhash ) ) ldiff = differenceHelper ( ltree , rtree , diff , left ) ; else if ( ! lreso ) ldiff = FULLY_INCONSISTENT ; lnode = ltree . find ( right ) ; rnode = rtree . find ( right ) ; lhash = lnode . hash ( ) ; rhash = rnode . hash ( ) ; right . setSize ( lnode . sizeOfRange ( ) , rnode . sizeOfRange ( ) ) ; right . setRows ( lnode . rowsInRange ( ) , rnode . rowsInRange ( ) ) ; int rdiff = CONSISTENT ; boolean rreso = lhash != null && rhash != null ; if ( rreso && ! Arrays . equals ( lhash , rhash ) ) rdiff = differenceHelper ( ltree , rtree , diff , right ) ; else if ( ! rreso ) rdiff = FULLY_INCONSISTENT ; if ( ldiff == FULLY_INCONSISTENT && rdiff == FULLY_INCONSISTENT ) { return FULLY_INCONSISTENT ; } else if ( ldiff == FULLY_INCONSISTENT ) { diff . add ( left ) ; return PARTIALLY_INCONSISTENT ; } else if ( rdiff == FULLY_INCONSISTENT ) { diff . add ( right ) ; return PARTIALLY_INCONSISTENT ; } return PARTIALLY_INCONSISTENT ; }
TODO: This function could be optimized into a depth first traversal of
the two trees in parallel.

Takes two trees and a range for which they have hashes, but are inconsistent.
@return FULLY_INCONSISTENT if active is inconsistent, PARTIALLY_INCONSISTENT if only a subrange is inconsistent.