hollow/src/main/java/com/netflix/hollow/api/producer/AbstractHollowProducer.java
private ReadStateHelper checkIntegrity(
            ListenerSupport.Listeners listeners, ReadStateHelper readStates, Artifacts artifacts) throws Exception {
        Status.StageWithStateBuilder status = listeners.fireIntegrityCheckStart(readStates.pending());
        try {
            ReadStateHelper result = readStates;
            HollowReadStateEngine pending = readStates.pending().getStateEngine();
            readSnapshot(artifacts.snapshot, pending);

            if (readStates.hasCurrent()) {
                HollowReadStateEngine current = readStates.current().getStateEngine();

                log.info("CHECKSUMS");
                HollowChecksum currentChecksum = HollowChecksum.forStateEngineWithCommonSchemas(current, pending);
                log.info("  CUR        " + currentChecksum);

                HollowChecksum pendingChecksum = HollowChecksum.forStateEngineWithCommonSchemas(pending, current);
                log.info("         PND " + pendingChecksum);

                if (artifacts.hasDelta()) {
                    if (!artifacts.hasReverseDelta()) {
                        throw new IllegalStateException("Both a delta and reverse delta are required");
                    }

                    // FIXME: timt: future cycles will fail unless both deltas validate
                    applyDelta(artifacts.delta, current);
                    HollowChecksum forwardChecksum = HollowChecksum.forStateEngineWithCommonSchemas(current, pending);
                    //out.format("  CUR => PND %s\n", forwardChecksum);
                    if (!forwardChecksum.equals(pendingChecksum)) {
                        throw new HollowProducer.ChecksumValidationException(HollowProducer.Blob.Type.DELTA);
                    }

                    applyDelta(artifacts.reverseDelta, pending);
                    HollowChecksum reverseChecksum = HollowChecksum.forStateEngineWithCommonSchemas(pending, current);
                    //out.format("  CUR <= PND %s\n", reverseChecksum);
                    if (!reverseChecksum.equals(currentChecksum)) {
                        throw new HollowProducer.ChecksumValidationException(HollowProducer.Blob.Type.REVERSE_DELTA);
                    }
                    result = readStates.swap();
                }
            }
            status.success();
            return result;
        } catch (Throwable th) {
            status.fail(th);
            throw th;
        } finally {
            listeners.fireIntegrityCheckComplete(status);
        }
    }
private ReadStateHelper checkIntegrity(
            ListenerSupport.Listeners listeners, ReadStateHelper readStates, Artifacts artifacts) throws Exception {
        Status.StageWithStateBuilder status = listeners.fireIntegrityCheckStart(readStates.pending());
        try {
            ReadStateHelper result = readStates;
            HollowReadStateEngine pending = readStates.pending().getStateEngine();
            readSnapshot(artifacts.snapshot, pending);

            if (readStates.hasCurrent()) {
                HollowReadStateEngine current = readStates.current().getStateEngine();

                log.info("CHECKSUMS");
                HollowChecksum currentChecksum = HollowChecksum.forStateEngineWithCommonSchemas(current, pending);
                log.info("  CUR        " + currentChecksum);

                HollowChecksum pendingChecksum = HollowChecksum.forStateEngineWithCommonSchemas(pending, current);
                log.info("         PND " + pendingChecksum);

                if (artifacts.hasDelta()) {
                    if (!artifacts.hasReverseDelta()) {
                        throw new IllegalStateException("Both a delta and reverse delta are required");
                    }

                    // FIXME: timt: future cycles will fail unless both deltas validate
                    applyDelta(artifacts.delta, current);
                    HollowChecksum forwardChecksum = HollowChecksum.forStateEngineWithCommonSchemas(current, pending);
                    //out.format("  CUR => PND %s\n", forwardChecksum);
                    if (!forwardChecksum.equals(pendingChecksum)) {
                        throw new HollowProducer.ChecksumValidationException(HollowProducer.Blob.Type.DELTA);
                    }

                    applyDelta(artifacts.reverseDelta, pending);
                    HollowChecksum reverseChecksum = HollowChecksum.forStateEngineWithCommonSchemas(pending, current);
                    //out.format("  CUR <= PND %s\n", reverseChecksum);
                    if (!reverseChecksum.equals(currentChecksum)) {
                        throw new HollowProducer.ChecksumValidationException(HollowProducer.Blob.Type.REVERSE_DELTA);
                    }
                    result = readStates.swap();
                }
            }
            status.success();
            return result;
        } catch (Throwable th) {
            status.fail(th);
            throw th;
        } finally {
            listeners.fireIntegrityCheckComplete(status);
        }
    }
Given these read states
<p>
* S(cur) at the currently announced version
* S(pnd) at the pending version
<p>
Ensure that:
<p>
S(cur).apply(forwardDelta).checksum == S(pnd).checksum
S(pnd).apply(reverseDelta).checksum == S(cur).checksum

@return updated read states