'Checks the auth chain is valid (and passes auth checks) for the
state and event. Then persists the auth chain and state atomically.
Persists the event seperately.
Will attempt to fetch missing auth events.
Args:
origin (str): Where the events came from
auth_events (list)
state (list)
event (Event)
Returns:
2-tuple of (event_stream_id, max_stream_id) from the persist_event
call for `event`'

@defer.inlineCallbacks
def _persist_auth_tree(self, origin, auth_events, state, event):

    events_to_context = {}
    for e in itertools.chain(auth_events, state):
        e.internal_metadata.outlier = True
        ctx = (yield self.state_handler.compute_event_context(e))
        events_to_context[e.event_id] = ctx
    event_map = {e.event_id: e for e in itertools.chain(auth_events, state, [event])}
    create_event = None
    for e in auth_events:
        if ((e.type, e.state_key) == (EventTypes.Create, '')):
            create_event = e
            break
    missing_auth_events = set()
    for e in itertools.chain(auth_events, state, [event]):
        for (e_id, _) in e.auth_events:
            if (e_id not in event_map):
                missing_auth_events.add(e_id)
    for e_id in missing_auth_events:
        m_ev = (yield self.replication_layer.get_pdu([origin], e_id, outlier=True, timeout=10000))
        if (m_ev and (m_ev.event_id == e_id)):
            event_map[e_id] = m_ev
        else:
            logger.info('Failed    to    find    auth    event    %r', e_id)
    for e in itertools.chain(auth_events, state, [event]):
        auth_for_e = {(event_map[e_id].type, event_map[e_id].state_key): event_map[e_id] for (e_id, _) in e.auth_events if (e_id in event_map)}
        if create_event:
            auth_for_e[(EventTypes.Create, '')] = create_event
        try:
            self.auth.check(e, auth_events=auth_for_e)
        except SynapseError as err:
            logger.warn('Rejecting    %s    because    %s', e.event_id, err.msg)
            if (e == event):
                raise
            events_to_context[e.event_id].rejected = RejectedReason.AUTH_ERROR
    (yield self.store.persist_events([(e, events_to_context[e.event_id]) for e in itertools.chain(auth_events, state)]))
    new_event_context = (yield self.state_handler.compute_event_context(event, old_state=state))
    (event_stream_id, max_stream_id) = (yield self.store.persist_event(event, new_event_context))
    defer.returnValue((event_stream_id, max_stream_id))
