Exemple #1
0
 def verify(self):
     txn = self.config.BU.get_transaction_by_id(self.id, instance=True)
     result = verify_signature(base64.b64decode(self.signature),
                               self.id.encode('utf-8'),
                               bytes.fromhex(txn.public_key))
     if not result:
         raise Exception('Invalid external input')
def verify_ecdsa(message, signature, pub):
    """Checks if the signature from signEcdsa is correct."""

    if not isinstance(message, (bytes, bytearray)):
        raise TypeError(f"Invalid message")
    if len(message) != 32:
        raise ValueError(f"Invalid length message: {len(message)} != 32")
    if not isinstance(signature, (bytes, bytearray)):
        raise TypeError(f"Invalid signature key")
    if len(signature) != 65:
        raise ValueError(f"Invalid length signature key: {len(signature)} != 65")
    if not isinstance(pub, (bytes, bytearray)):
        raise TypeError(f"Invalid signature key")
    if len(pub) != 64:
        raise ValueError(f"Invalid length signature key: {len(pub)} != 64")

    pubkey = PublicKey(b"\x04" + pub)

    r = _big_endian_to_int(signature[0:32])
    s = _big_endian_to_int(signature[32:64])

    low_s = _coerce_low_s(s)
    der_encoded_signature = bytes(_two_int_sequence_encoder(r, low_s))

    return verify_signature(
        der_encoded_signature, message, pubkey.format(compressed=False), hasher=None
    )
Exemple #3
0
 async def recover_missing_transaction(self, txn_id, exclude_ids=[]):
     return False
     if await self.config.mongo.async_db.failed_recoveries.find_one({'txn_id': txn_id}):
         return False
     self.app_log.warning("recovering missing transaction input: {}".format(txn_id))
     address = str(P2PKHBitcoinAddress.from_pubkey(bytes.fromhex(self.public_key)))
     missing_txns = self.config.mongo.async_db.blocks.aggregate([
         {
             '$unwind': '$transactions'
         },
         {
             '$project': {
                 'transaction': '$transactions',
                 'index': '$index'
             }
         }
     ], allowDiskUse=True)
     async for missing_txn in missing_txns:
         self.app_log.warning('recovery searching block index: {}'.format(missing_txn['index']))
         try:
             result = verify_signature(base64.b64decode(txn_id), missing_txn['transaction']['hash'].encode(),
                                     bytes.fromhex(self.public_key))
             if result:
                 block_index = await self.find_unspent_missing_index(missing_txn['transaction']['hash'], exclude_ids)
                 if block_index:
                     await self.replace_missing_transaction_input(
                         block_index,
                         missing_txn['transaction']['hash'],
                         txn_id
                     )
                     return True
             else:
                 if len(base64.b64decode(txn_id)) != 65:
                     continue
                 result = VerifyMessage(
                     address,
                     BitcoinMessage(missing_txn['transaction']['hash'], magic=''),
                     txn_id
                 )
                 if result:
                     block_index = await self.find_unspent_missing_index(missing_txn['transaction']['hash'], exclude_ids)
                     if block_index:
                         await self.replace_missing_transaction_input(
                             block_index,
                             missing_txn['transaction']['hash'],
                             txn_id
                         )
                         return True
         except:
             continue
     await self.config.mongo.async_db.failed_recoveries.update_one({
         'txn_id': txn_id
     },
     {
         '$set': {
             'txn_id': txn_id
         }
     }, upsert=True)
     return False
Exemple #4
0
 async def connect(self, peer):
     try:
         id_attr = getattr(peer, peer.id_attribute)
         if id_attr in self.outbound_ignore[peer.__class__.__name__]:
             return
         if id_attr in self.outbound_pending[peer.__class__.__name__]:
             return
         if id_attr in self.outbound_streams[peer.__class__.__name__]:
             return
         if id_attr in self.config.nodeServer.inbound_pending[
                 peer.__class__.__name__]:
             return
         if id_attr in self.config.nodeServer.inbound_streams[
                 peer.__class__.__name__]:
             return
         if self.config.peer.identity.username_signature == peer.identity.username_signature:
             return
         if (self.config.peer.host, self.config.peer.host) == (peer.host,
                                                               peer.port):
             return
         self.outbound_pending[peer.__class__.__name__][id_attr] = peer
         stream = await super(RPCSocketClient, self).connect(peer.host,
                                                             peer.port,
                                                             timeout=1)
         stream.synced = False
         stream.message_queue = {}
         stream.peer = peer
         try:
             result = verify_signature(
                 base64.b64decode(stream.peer.identity.username_signature),
                 stream.peer.identity.username.encode(),
                 bytes.fromhex(stream.peer.identity.public_key))
             if not result:
                 self.config.app_log.warning(
                     'new {} peer signature is invalid'.format(
                         peer.__class__.__name__))
                 stream.close()
                 return
             self.config.app_log.info('new {} peer is valid'.format(
                 peer.__class__.__name__))
         except:
             self.config.app_log.warning('invalid peer identity signature')
             stream.close()
             return
         if id_attr in self.outbound_pending[peer.__class__.__name__]:
             del self.outbound_pending[peer.__class__.__name__][id_attr]
         self.outbound_streams[peer.__class__.__name__][id_attr] = stream
         self.config.app_log.info('Connected to {}: {}'.format(
             peer.__class__.__name__, peer.to_json()))
         return stream
     except StreamClosedError:
         await self.remove_peer(peer)
         self.config.app_log.warning('Streamed closed for {}: {}'.format(
             peer.__class__.__name__, peer.to_json()))
     except TimeoutError:
         await self.remove_peer(peer)
         self.config.app_log.warning('Timeout connecting to {}: {}'.format(
             peer.__class__.__name__, peer.to_json()))
Exemple #5
0
 def verify(self):
     txn = BU.get_transaction_by_id(self.config,
                                    self.mongo,
                                    self.id,
                                    instance=True)
     result = verify_signature(base64.b64decode(self.signature), self.id,
                               txn.public_key.decode('hex'))
     if not result:
         raise Exception('Invalid external input')
Exemple #6
0
 def authenticate(self, session_id, post_data, hash_session_id=True):
     user = self.get_user(post_data)
     if hash_session_id:
         session_id = hashlib.sha256(session_id.encode()).hexdigest()
     result = verify_signature(
         base64.b64decode(post_data['session_id_signature']),
         session_id.encode(),
         bytes.fromhex(user.public_key)
     )
     return user if result is True else None
Exemple #7
0
 async def authenticate(self, body, stream):
     signed_challenge = body.get('result', {}).get('signed_challenge')
     result = verify_signature(
         base64.b64decode(signed_challenge), stream.peer.token.encode(),
         bytes.fromhex(stream.peer.identity.public_key))
     if result:
         stream.peer.authenticated = True
         self.config.app_log.info('Authenticated {}: {}'.format(
             stream.peer.__class__.__name__, stream.peer.to_json()))
         await self.send_block(self.config.LatestBlock.block)
         await self.get_next_block(self.config.LatestBlock.block)
     else:
         stream.close()
Exemple #8
0
 def verify_bis_signature(cls,
                          signature: str,
                          public_key: str,
                          buffer: bytes,
                          address: str = '') -> None:
     """Verify signature from bismuth tx network format (ecdsa sig and pubkey are b64 encoded)
     Returns None, but raises ValueError if needed."""
     public_key = b64decode(public_key)
     valid = verify_signature(b64decode(signature), buffer, public_key)
     if not valid:
         raise ValueError(f"Invalid signature from {address}")
     # Reconstruct address from pubkey to make sure it matches
     if address != cls.public_key_to_address(public_key):
         raise ValueError("Attempt to spend from a wrong address")
Exemple #9
0
 def verify_bis_signature_raw(cls,
                              signature: bytes,
                              public_key: bytes,
                              buffer: bytes,
                              address: str = '') -> None:
     """Verify signature from bin format
     Returns None, but raises ValueError if needed."""
     # print("ecdsa verify_bis_signature_raw pubkey", public_key, "sig", signature)
     valid = verify_signature(signature, buffer, public_key)
     if not valid:
         raise ValueError(f"Invalid signature from {address}")
     # Reconstruct address from pubkey to make sure it matches
     if address != cls.public_key_to_address(public_key):
         raise ValueError("Attempt to spend from a wrong address")
Exemple #10
0
    async def connect(self, body):
        params = body.get('params')
        if not params.get('identity'):
            self.close()
            return {}

        peer = User.from_dict({
            'host': None,
            'port': None,
            'identity': params.get('identity')
        })
        self.peer = peer
        self.peer.groups = {}
        RCPWebSocketServer.inbound_streams[User.__name__][peer.rid] = self

        try:
            result = verify_signature(
                base64.b64decode(peer.identity.username_signature),
                peer.identity.username.encode(),
                bytes.fromhex(peer.identity.public_key))
            if not result:
                self.close()
        except:
            self.config.app_log.error('invalid peer identity signature')
            self.close()
            return {}

        try:
            self.config.app_log.info('new {} is valid'.format(
                peer.__class__.__name__))
            await self.write_result('connect_confirm', {
                'identity':
                self.config.peer.identity.to_dict,
                'shares_required':
                self.config.shares_required,
                'credit_balance':
                await self.get_credit_balance(),
                'server_pool_address':
                f'{self.config.peer_host}:{self.config.stratum_pool_port}'
            },
                                    body=body)
        except:
            self.config.app_log.error('invalid peer identity signature')
            self.close()
            return {}
    def verify(self):
        verify_hash = self.generate_hash()
        address = P2PKHBitcoinAddress.from_pubkey(
            self.public_key.decode('hex'))

        if verify_hash != self.hash:
            raise InvalidTransactionException("transaction is invalid")

        try:
            result = verify_signature(
                base64.b64decode(self.transaction_signature), self.hash,
                self.public_key.decode('hex'))
            if not result:
                raise
        except:
            try:
                result = VerifyMessage(address,
                                       BitcoinMessage(self.hash, magic=''),
                                       self.transaction_signature)
                if not result:
                    raise
            except:
                raise InvalidTransactionSignatureException(
                    "transaction signature did not verify")

        # verify spend
        total_input = 0
        for txn in self.inputs:
            txn_input = Transaction.from_dict(BU.get_transaction_by_id(txn.id))
            for output in txn_input.outputs:
                if str(output.to) == str(address):
                    total_input += float(output.value)

        if self.coinbase:
            return

        total_output = 0
        for txn in self.outputs:
            total_output += float(txn.value)
        total = float(total_output) + float(self.fee)
        if str(total_input) != str(total):
            raise BaseException(
                "inputs and outputs sum must match %s, %s, %s, %s" %
                (total_input, float(total_output), float(self.fee), total))
Exemple #12
0
 def __eq__(self, other: Any) -> bool:
     # For convenience of using stashed objects, we allow comparison with str
     if isinstance(other, str):
         othersig = Sig(other)
     else:
         othersig = cast(Sig, other)
     if self.sigval and othersig.sigval:
         return self.sigval == othersig.sigval
     elif not self.sigval and not othersig.sigval:
         return self.privkey == othersig.privkey and self.hashval == othersig.hashval
     elif not self.sigval:
         a = self
         b = othersig
     else:
         a = othersig
         b = self
     # A has a privkey/hash, B has a sigval.
     pubkey = coincurve.PublicKey.from_secret(a.privkey.secret)
     assert b.sigval is not None
     if coincurve.verify_signature(self.to_der(b.sigval), a.hashval, pubkey.format(), hasher=None):
         return True
     return False
Exemple #13
0
    async def connect(self, body, stream):
        params = body.get('params')
        if not params.get('peer'):
            stream.close()
            return {}
        generic_peer = Peer.from_dict(params.get('peer'))
        if isinstance(self.config.peer, Seed):

            if generic_peer.identity.username_signature in self.config.seeds:
                peerCls = Seed
            elif generic_peer.identity.username_signature in self.config.seed_gateways:
                peerCls = SeedGateway

        elif isinstance(self.config.peer, SeedGateway):

            if generic_peer.identity.username_signature in self.config.seeds:
                peerCls = Seed
            else:
                peerCls = ServiceProvider

        elif isinstance(self.config.peer, ServiceProvider):

            if generic_peer.identity.username_signature in self.config.seed_gateways:
                peerCls = SeedGateway
            else:
                peerCls = User

        elif isinstance(self.config.peer, User):

            peerCls = User
        else:
            self.config.app_log.error(
                'inbound peer is not defined, disconnecting')
            stream.close()
            return {}

        limit = self.config.peer.__class__.type_limit(peerCls)
        if (len(NodeSocketServer.inbound_pending[peerCls.__name__]) + len(
                NodeSocketServer.inbound_streams[peerCls.__name__])) >= limit:
            await self.write_result(stream, 'capacity', {}, body['id'])
            stream.close()
            return {}

        try:
            stream.peer = peerCls.from_dict(params.get('peer'))
        except:
            self.config.app_log.error('invalid peer identity')
            stream.close()
            return {}

        if generic_peer.rid in NodeSocketServer.inbound_pending[
                stream.peer.__class__.__name__]:
            stream.close()
            return {}

        if generic_peer.rid in NodeSocketServer.inbound_streams[
                stream.peer.__class__.__name__]:
            stream.close()
            return {}

        if generic_peer.rid in self.config.nodeClient.outbound_ignore[
                stream.peer.__class__.__name__]:
            stream.close()
            return

        if generic_peer.rid in self.config.nodeClient.outbound_pending[
                stream.peer.__class__.__name__]:
            stream.close()
            return

        if generic_peer.rid in self.config.nodeClient.outbound_streams[
                stream.peer.__class__.__name__]:
            stream.close()
            return

        try:
            result = verify_signature(
                base64.b64decode(stream.peer.identity.username_signature),
                stream.peer.identity.username.encode(),
                bytes.fromhex(stream.peer.identity.public_key))
            if result:
                self.config.app_log.info('new {} peer is valid'.format(
                    stream.peer.__class__.__name__))
        except:
            self.config.app_log.error('invalid peer identity signature')
            stream.close()
            return {}

        NodeSocketServer.inbound_streams[peerCls.__name__][
            stream.peer.rid] = stream
        self.config.app_log.info('Connected to {}: {}'.format(
            stream.peer.__class__.__name__, stream.peer.to_json()))
        return {}
Exemple #14
0
    async def verify(self):
        verify_hash = await self.generate_hash()
        address = P2PKHBitcoinAddress.from_pubkey(
            bytes.fromhex(self.public_key))

        if verify_hash != self.hash:
            raise InvalidTransactionException("transaction is invalid")

        try:
            result = verify_signature(
                base64.b64decode(self.transaction_signature),
                self.hash.encode('utf-8'), bytes.fromhex(self.public_key))
            if not result:
                print("t verify1")
                raise Exception()
        except:
            try:
                result = VerifyMessage(address,
                                       BitcoinMessage(self.hash, magic=''),
                                       self.transaction_signature)
                if not result:
                    print("t verify2")
                    raise
            except:
                print("t verify3")
                raise InvalidTransactionSignatureException(
                    "transaction signature did not verify")

        if len(self.relationship) > 20480:
            raise MaxRelationshipSizeExceeded(
                'Relationship field cannot be greater than 2048 bytes')

        # verify spend
        total_input = 0
        exclude_recovered_ids = []
        async for txn in self.get_inputs(self.inputs):
            input_txn = self.config.BU.get_transaction_by_id(txn.id)
            if input_txn:
                txn_input = Transaction.from_dict(input_txn)
            if not input_txn:
                if self.extra_blocks:
                    txn_input = await self.find_in_extra_blocks(txn)
                if not txn_input:
                    result = await self.recover_missing_transaction(
                        txn.id, exclude_recovered_ids)
                    exclude_recovered_ids.append(exclude_recovered_ids)
                    raise MissingInputTransactionException(
                        "Input not found on blockchain: {}".format(txn.id))

            found = False
            for output in txn_input.outputs:
                if isinstance(txn, ExternalInput):
                    ext_address = P2PKHBitcoinAddress.from_pubkey(
                        bytes.fromhex(txn_input.public_key))
                    int_address = P2PKHBitcoinAddress.from_pubkey(
                        bytes.fromhex(txn.public_key))
                    if str(output.to) == str(ext_address) and str(
                            int_address) == str(txn.address):
                        try:
                            result = verify_signature(
                                base64.b64decode(txn.signature),
                                txn.id.encode('utf-8'),
                                bytes.fromhex(txn_input.public_key))
                            if not result:
                                print("t verify4")
                                raise Exception()
                        except:
                            try:
                                result = VerifyMessage(
                                    ext_address,
                                    BitcoinMessage(txn.id, magic=''),
                                    txn.signature)
                                if not result:
                                    print("t verify5")
                                    raise
                            except:
                                raise InvalidTransactionSignatureException(
                                    "external input transaction signature did not verify"
                                )

                        found = True
                        total_input += float(output.value)
                elif str(output.to) == str(address):
                    found = True
                    total_input += float(output.value)

            if not found:
                if isinstance(txn, ExternalInput):
                    raise InvalidTransactionException(
                        "external input signing information did not match any recipients of the input transaction"
                    )
                else:
                    raise InvalidTransactionException(
                        "using inputs from a transaction where you were not one of the recipients."
                    )

        if self.coinbase:
            return

        total_output = 0
        for txn in self.outputs:
            total_output += float(txn.value)
        total = float(total_output) + float(self.fee)
        if fix_float1(total_input) != fix_float1(total) and fix_float2(
                total_input) != fix_float2(total):
            raise TotalValueMismatchException(
                "inputs and outputs sum must match %s, %s, %s, %s" %
                (total_input, float(total_output), float(self.fee), total))
Exemple #15
0
    def verify(self):
        from yadacoin.fastgraph import FastGraph
        verify_hash = self.generate_hash()
        address = P2PKHBitcoinAddress.from_pubkey(bytes.fromhex(self.public_key))

        if verify_hash != self.hash:
            raise InvalidTransactionException("transaction is invalid")

        try:
            result = verify_signature(base64.b64decode(self.transaction_signature), self.hash.encode('utf-8'),
                                      bytes.fromhex(self.public_key))
            if not result:
                print("t verify1")
                raise Exception()
        except:
            try:
                result = VerifyMessage(address, BitcoinMessage(self.hash.encode('utf-8'), magic=''), self.transaction_signature)
                if not result:
                    print("t verify2")
                    raise
            except:
                print("t verify3")
                raise InvalidTransactionSignatureException("transaction signature did not verify")

        if len(self.relationship) > 2048:
            raise MaxRelationshipSizeExceeded('Relationship field cannot be greater than 2048 bytes')

        # verify spend
        total_input = 0
        for txn in self.inputs:
            # TODO: move to async
            input_txn = self.config.BU.get_transaction_by_id(txn.id, include_fastgraph=isinstance(self, FastGraph))
            if not input_txn:
                raise InvalidTransactionException("Input not found on blockchain.")
            txn_input = Transaction.from_dict(self.block_height, input_txn)

            found = False
            for output in txn_input.outputs:
                if isinstance(txn, ExternalInput):
                    ext_address = P2PKHBitcoinAddress.from_pubkey(bytes.fromhex(txn_input.public_key))
                    int_address = P2PKHBitcoinAddress.from_pubkey(bytes.fromhex(txn.public_key))
                    if str(output.to) == str(ext_address) and str(int_address) == str(txn.address):
                        try:
                            result = verify_signature(base64.b64decode(txn.signature), txn.id.encode('utf-8'), bytes.fromhex(txn_input.public_key))
                            if not result:
                                print("t verify4")
                                raise Exception()
                        except:
                            try:
                                result = VerifyMessage(ext_address, BitcoinMessage(txn.id, magic=''), txn.signature)
                                if not result:
                                    print("t verify5")
                                    raise
                            except:
                                raise InvalidTransactionSignatureException("external input transaction signature did not verify")
                        
                        found = True
                        total_input += float(output.value)
                elif str(output.to) == str(address):
                    found = True
                    total_input += float(output.value)
                
            if not found:
                if isinstance(txn, ExternalInput):
                    raise InvalidTransactionException("external input signing information did not match any recipients of the input transaction")
                else:
                    raise InvalidTransactionException("using inputs from a transaction where you were not one of the recipients.")

        if self.coinbase:
            return

        total_output = 0
        for txn in self.outputs:
            total_output += float(txn.value)
        total = float(total_output) + float(self.fee)
        if "{0:.8f}".format(total_input) != "{0:.8f}".format(total):
            raise Exception("inputs and outputs sum must match %s, %s, %s, %s" % (total_input, float(total_output), float(self.fee), total))
Exemple #16
0
    def verify(self):
        from fastgraph import FastGraph
        verify_hash = self.generate_hash()
        address = P2PKHBitcoinAddress.from_pubkey(
            self.public_key.decode('hex'))

        if verify_hash != self.hash:
            raise InvalidTransactionException("transaction is invalid")

        try:
            result = verify_signature(
                base64.b64decode(self.transaction_signature), self.hash,
                self.public_key.decode('hex'))
            if not result:
                raise Exception()
        except:
            try:
                result = VerifyMessage(address,
                                       BitcoinMessage(self.hash, magic=''),
                                       self.transaction_signature)
                if not result:
                    raise
            except:
                raise InvalidTransactionSignatureException(
                    "transaction signature did not verify")

        # verify spend
        total_input = 0
        for txn in self.inputs:
            input_txn = BU.get_transaction_by_id(self.config,
                                                 self.mongo,
                                                 txn.id,
                                                 include_fastgraph=isinstance(
                                                     self, FastGraph))
            if not input_txn:
                raise InvalidTransactionException(
                    "Input not found on blockchain.")
            txn_input = Transaction.from_dict(self.config, self.mongo,
                                              self.block_height, input_txn)

            found = False
            for output in txn_input.outputs:
                if hasattr(txn, 'public_key') and hasattr(txn, 'signature'):
                    ext_address = P2PKHBitcoinAddress.from_pubkey(
                        txn.public_key.decode('hex'))
                    if str(output.to) == str(ext_address):
                        found = True
                        try:
                            result = verify_signature(
                                base64.b64decode(txn.signature), txn.id,
                                txn.public_key.decode('hex'))
                            if not result:
                                raise Exception()
                        except:
                            try:
                                result = VerifyMessage(
                                    ext_address,
                                    BitcoinMessage(txn.id, magic=''),
                                    txn.signature)
                                if not result:
                                    raise
                            except:
                                raise InvalidTransactionSignatureException(
                                    "external input transaction signature did not verify"
                                )
                elif str(output.to) == str(address):
                    found = True
                    total_input += float(output.value)

            if not found:
                if hasattr(txn, 'public_key') and hasattr(txn, 'signature'):
                    raise InvalidTransactionException(
                        "external input signing information did not match any recipients of the input transaction"
                    )
                else:
                    raise InvalidTransactionException(
                        "using inputs from a transaction where you were not one of the recipients."
                    )

        if self.coinbase:
            return

        total_output = 0
        for txn in self.outputs:
            total_output += float(txn.value)
        total = float(total_output) + float(self.fee)
        if "{0:.8f}".format(total_input) != "{0:.8f}".format(total):
            raise BaseException(
                "inputs and outputs sum must match %s, %s, %s, %s" %
                (total_input, float(total_output), float(self.fee), total))
 def verify(self):
     return coincurve.verify_signature(bytes.fromhex(self.signature),
                                       self._signable(),
                                       bytes.fromhex(self.source))
Exemple #18
0
    async def connect(self, peer):
        try:
            stream = None
            id_attr = getattr(peer, peer.id_attribute)
            if id_attr in self.outbound_ignore[peer.__class__.__name__]:
                return
            if id_attr in self.outbound_pending[peer.__class__.__name__]:
                return
            if id_attr in self.outbound_streams[peer.__class__.__name__]:
                return
            if id_attr in self.config.nodeServer.inbound_pending[peer.__class__.__name__]:
                return
            if id_attr in self.config.nodeServer.inbound_streams[peer.__class__.__name__]:
                return
            if self.config.peer.identity.username_signature == peer.identity.username_signature:
                return
            if (self.config.peer.host, self.config.peer.host) == (peer.host, peer.port):
                return
            stream = DummyStream(peer)
            stream.last_activity = int(time.time())
            self.outbound_pending[peer.__class__.__name__][id_attr] = stream
            stream = await super(RPCSocketClient, self).connect(peer.host, peer.port, timeout=timedelta(seconds=1))
            stream.synced = False
            stream.syncing = False
            stream.message_queue = {}
            stream.peer = peer
            self.config.health.tcp_client.last_activity = time.time()
            stream.last_activity = int(time.time())
            try:
                result = verify_signature(
                    base64.b64decode(stream.peer.identity.username_signature),
                    stream.peer.identity.username.encode(),
                    bytes.fromhex(stream.peer.identity.public_key)
                )
                if not result:
                    self.config.app_log.warning('new {} peer signature is invalid'.format(peer.__class__.__name__))
                    stream.close()
                    return
                self.config.app_log.info('new {} peer is valid'.format(peer.__class__.__name__))
            except:
                self.config.app_log.warning('invalid peer identity signature')
                await self.remove_peer(stream)
                return
            if id_attr in self.outbound_pending[peer.__class__.__name__]:
                del self.outbound_pending[peer.__class__.__name__][id_attr]
            self.outbound_streams[peer.__class__.__name__][id_attr] = stream
            self.config.app_log.info('Connected to {}: {}'.format(peer.__class__.__name__, peer.to_json()))
            return stream
        except StreamClosedError:
            if not stream:
                stream = DummyStream(peer)

            await self.remove_peer(stream)
            self.config.app_log.warning('Streamed closed for {}: {}'.format(peer.__class__.__name__, peer.to_json()))
        except TimeoutError:
            if not stream:
                stream = DummyStream(peer)

            await self.remove_peer(stream)
            self.config.app_log.warning('Timeout connecting to {}: {}'.format(peer.__class__.__name__, peer.to_json()))
        except:
            if hasattr(stream, 'peer'):
                self.config.app_log.warning('Unhandled exception from {}: {}'.format(stream.peer.__class__.__name__, stream.peer.to_json()))

            await self.remove_peer(stream)
            self.config.app_log.debug("{}".format(format_exc()))