Explore the CFG and look for re-entrancy
            Heuristic: There is a re-entrancy if a state variable is written
                        after an external call

            node.context will contains the external calls executed
            It contains the calls executed in father nodes

            if node.context is not empty, and variables are written, a re-entrancy is possible

def _explore(self, node, visited, skip_father=None):
        """
            Explore the CFG and look for re-entrancy
            Heuristic: There is a re-entrancy if a state variable is written
                        after an external call

            node.context will contains the external calls executed
            It contains the calls executed in father nodes

            if node.context is not empty, and variables are written, a re-entrancy is possible
        """
        if node in visited:
            return

        visited = visited + [node]

        # First we add the external calls executed in previous nodes
        # send_eth returns the list of calls sending value
        # calls returns the list of calls that can callback
        # read returns the variable read
        # read_prior_calls returns the variable read prior a call
        fathers_context = {'send_eth':set(), 'calls':set(), 'read':set(), 'read_prior_calls':{}}

        for father in node.fathers:
            if self.KEY in father.context:
                fathers_context['send_eth'] |= set([s for s in father.context[self.KEY]['send_eth'] if s!=skip_father])
                fathers_context['calls'] |= set([c for c in father.context[self.KEY]['calls'] if c!=skip_father])
                fathers_context['read'] |= set(father.context[self.KEY]['read'])
                fathers_context['read_prior_calls'] = union_dict(fathers_context['read_prior_calls'], father.context[self.KEY]['read_prior_calls'])

        # Exclude path that dont bring further information
        if node in self.visited_all_paths:
            if all(call in self.visited_all_paths[node]['calls'] for call in fathers_context['calls']):
                if all(send in self.visited_all_paths[node]['send_eth'] for send in fathers_context['send_eth']):
                    if all(read in self.visited_all_paths[node]['read'] for read in fathers_context['read']):
                        if dict_are_equal(self.visited_all_paths[node]['read_prior_calls'], fathers_context['read_prior_calls']):
                            return
        else:
            self.visited_all_paths[node] = {'send_eth':set(), 'calls':set(), 'read':set(), 'read_prior_calls':{}}

        self.visited_all_paths[node]['send_eth'] = set(self.visited_all_paths[node]['send_eth'] | fathers_context['send_eth'])
        self.visited_all_paths[node]['calls'] = set(self.visited_all_paths[node]['calls'] | fathers_context['calls'])
        self.visited_all_paths[node]['read'] = set(self.visited_all_paths[node]['read'] | fathers_context['read'])
        self.visited_all_paths[node]['read_prior_calls'] = union_dict(self.visited_all_paths[node]['read_prior_calls'], fathers_context['read_prior_calls'])

        node.context[self.KEY] = fathers_context

        state_vars_read = set(node.state_variables_read)

        # All the state variables written
        state_vars_written = set(node.state_variables_written)
        slithir_operations = []
        # Add the state variables written in internal calls
        for internal_call in node.internal_calls:
            # Filter to Function, as internal_call can be a solidity call
            if isinstance(internal_call, Function):
                state_vars_written |= set(internal_call.all_state_variables_written())
                state_vars_read |= set(internal_call.all_state_variables_read())
                slithir_operations += internal_call.all_slithir_operations()

        contains_call = False
        node.context[self.KEY]['written'] = set(state_vars_written)
        if self._can_callback(node.irs + slithir_operations):
            node.context[self.KEY]['calls'] = set(node.context[self.KEY]['calls'] | {node})
            node.context[self.KEY]['read_prior_calls'][node] = set(node.context[self.KEY]['read_prior_calls'].get(node, set()) | node.context[self.KEY]['read'] |state_vars_read)
            contains_call = True
        if self._can_send_eth(node.irs + slithir_operations):
            node.context[self.KEY]['send_eth'] = set(node.context[self.KEY]['send_eth'] | {node})

        node.context[self.KEY]['read'] = set(node.context[self.KEY]['read'] | state_vars_read)

        sons = node.sons
        if contains_call and node.type in [NodeType.IF, NodeType.IFLOOP]:
            if self._filter_if(node):
                son = sons[0]
                self._explore(son, visited, node)
                sons = sons[1:]
            else:
                son = sons[1]
                self._explore(son, visited, node)
                sons = [sons[0]]


        for son in sons:
            self._explore(son, visited)