public boolean isValidRangeProof(
      final Bytes32 startKeyHash,
      final Bytes32 endKeyHash,
      final Bytes32 rootHash,
      final List<Bytes> proofs,
      final SortedMap<Bytes32, Bytes> keys) {

    // check if it's monotonic increasing
    if (keys.size() > 1 && !Ordering.natural().isOrdered(keys.keySet())) {
      return false;
    }

    // when proof is empty and we requested the full range, we should
    // have all the keys to reconstruct the trie
    if (proofs.isEmpty()) {
      if (startKeyHash.equals(Bytes32.ZERO)) {
        final MerkleTrie<Bytes, Bytes> trie = new SimpleMerklePatriciaTrie<>(Function.identity());
        // add the received keys in the trie
        for (Map.Entry<Bytes32, Bytes> key : keys.entrySet()) {
          trie.put(key.getKey(), key.getValue());
        }
        return rootHash.equals(trie.getRootHash());
      } else {
        // TODO: possibly accept a node loader so we can verify this with already
        //  completed partial storage requests
        LOG.info("failing proof due to incomplete range without proofs");
        return false;
      }
    }

    // reconstruct a part of the trie with the proof
    final Map<Bytes32, Bytes> proofsEntries = new HashMap<>();
    for (Bytes proof : proofs) {
      proofsEntries.put(Hash.hash(proof), proof);
    }

    if (keys.isEmpty()) {
      final MerkleTrie<Bytes, Bytes> trie =
          new StoredMerklePatriciaTrie<>(
              new InnerNodeDiscoveryManager<>(
                  (location, hash) -> Optional.ofNullable(proofsEntries.get(hash)),
                  Function.identity(),
                  Function.identity(),
                  startKeyHash,
                  endKeyHash,
                  false),
              rootHash);
      try {
        // check if there is not missing element
        // a missing node will throw an exception while it is loading
        // @see org.hyperledger.besu.ethereum.trie.StoredNode#load()
        trie.entriesFrom(startKeyHash, Integer.MAX_VALUE);
      } catch (MerkleTrieException e) {
        return false;
      }
      return true;
    }

    // search inner nodes in the range created by the proofs and remove
    final InnerNodeDiscoveryManager<Bytes> snapStoredNodeFactory =
        new InnerNodeDiscoveryManager<>(
            (location, hash) -> Optional.ofNullable(proofsEntries.get(hash)),
            Function.identity(),
            Function.identity(),
            startKeyHash,
            keys.lastKey(),
            true);
    final MerkleTrie<Bytes, Bytes> trie =
        new StoredMerklePatriciaTrie<>(snapStoredNodeFactory, rootHash);
    // filling out innerNodes of the InnerNodeDiscoveryManager by walking through the trie
    trie.visitAll(node -> {});
    final List<InnerNode> innerNodes = snapStoredNodeFactory.getInnerNodes();
    for (InnerNode innerNode : innerNodes) {
      trie.removePath(
          Bytes.concatenate(innerNode.location(), innerNode.path()), new RemoveVisitor<>(false));
    }

    // add the received keys in the trie to reconstruct the trie
    for (Map.Entry<Bytes32, Bytes> account : keys.entrySet()) {
      trie.put(account.getKey(), account.getValue());
    }

    // check if the generated root hash is valid
    return rootHash.equals(trie.getRootHash());
  }
Checks if a range proof is valid for a given range of keys.

@param startKeyHash The hash of the starting key in the range.
@param endKeyHash The hash of the ending key in the range.
@param rootHash The root hash of the Merkle Trie.
@param proofs The list of proofs for the keys in the range.
@param keys The TreeMap of key-value pairs representing the range.
@return {@code true} if the range proof is valid, {@code false} otherwise.
ethereum/core/src/main/java/org/hyperledger/besu/ethereum/proof/WorldStateProofProvider.java