def _find_address_values_in_chain(self, base_contexts, addresses_to_find):
        """Breadth first search through the chain of contexts searching for
        the bytes values at the addresses in addresses_to_find.

        Args:
            base_contexts (list of str): The context ids to start with.
            addresses_to_find (list of str): Addresses to find values in the
                chain of contexts.

        Returns:
            tuple of found address_values and still not found addresses
        """

        contexts_in_chain = deque()
        contexts_in_chain.extend(base_contexts)
        reads = list(addresses_to_find)
        address_values = []
        context_ids_already_searched = []
        context_ids_already_searched.extend(base_contexts)

        # There are two loop exit conditions, either all the addresses that
        # are being searched for have been found, or we run out of contexts
        # in the chain of contexts.

        while reads:
            try:
                current_c_id = contexts_in_chain.popleft()
            except IndexError:
                # There aren't any more contexts known about.
                break
            current_context = self._contexts[current_c_id]

            # First, check for addresses that have been deleted.
            deleted_addresses = current_context.get_if_deleted(reads)
            for address in deleted_addresses:
                if address is not None:
                    address_values.append((address, None))

            reads = list(set(reads) - set(deleted_addresses))

            # Second, check for addresses that have been set in the context,
            # and remove those addresses from being asked about again. Here
            # any value of None means the address hasn't been set.

            values = current_context.get_if_set(reads)
            addresses_not_found = []
            for address, value in zip(reads, values):
                if value is not None:
                    address_values.append((address, value))
                else:
                    addresses_not_found.append(address)
            reads = addresses_not_found

            # Next check for addresses that might be in a context
            # because they were inputs.

            addresses_in_inputs = [address for address in reads
                                   if address in current_context]

            values = current_context.get_if_not_set(addresses_in_inputs)

            address_values.extend(list(zip(addresses_in_inputs, values)))

            for add in addresses_in_inputs:
                reads.remove(add)

            for c_id in current_context.base_contexts:
                if c_id not in context_ids_already_searched:
                    contexts_in_chain.append(c_id)
                    context_ids_already_searched.append(c_id)

        return address_values, reads
Breadth first search through the chain of contexts searching for
        the bytes values at the addresses in addresses_to_find.

        Args:
            base_contexts (list of str): The context ids to start with.
            addresses_to_find (list of str): Addresses to find values in the
                chain of contexts.

        Returns:
            tuple of found address_values and still not found addresses