'Takes a list of PDUs and checks the signatures and hashs of each
one. If a PDU fails its signature check then we check if we have it in
the database and if not then request if from the originating server of
that PDU.
If a PDU fails its content hash check then it is redacted.
The given list of PDUs are not modified, instead the function returns
a new list.
Args:
pdu (list)
outlier (bool)
Returns:
Deferred : A list of PDUs that have valid signatures and hashes.'

@defer.inlineCallbacks
def _check_sigs_and_hash_and_fetch(self, origin, pdus, outlier=False, include_none=False):

    deferreds = self._check_sigs_and_hashes(pdus)
    def callback(pdu):
        return pdu
    def errback(failure, pdu):
        failure.trap(SynapseError)
        return None
    def try_local_db(res, pdu):
        if (not res):
            return self.store.get_event(pdu.event_id, allow_rejected=True, allow_none=True)
        return res
    def try_remote(res, pdu):
        if ((not res) and (pdu.origin != origin)):
            return self.get_pdu(destinations=[pdu.origin], event_id=pdu.event_id, outlier=outlier, timeout=10000).addErrback((lambda e: None))
        return res
    def warn(res, pdu):
        if (not res):
            logger.warn('Failed    to    find    copy    of    %s    with    valid    signature', pdu.event_id)
        return res
    for (pdu, deferred) in zip(pdus, deferreds):
        deferred.addCallbacks(callback, errback, errbackArgs=[pdu]).addCallback(try_local_db, pdu).addCallback(try_remote, pdu).addCallback(warn, pdu)
    valid_pdus = (yield preserve_context_over_deferred(defer.gatherResults(deferreds, consumeErrors=True)).addErrback(unwrapFirstError))
    if include_none:
        defer.returnValue(valid_pdus)
    else:
        defer.returnValue([p for p in valid_pdus if p])
