async def connect(self, remote: NodeAPI) -> BasePeer: """ Connect to the given remote and return a Peer instance when successful. Returns None if the remote is unreachable, times out or is useless. """ if self._handshake_locks.is_locked(remote): self.logger.debug2("Skipping %s; already shaking hands", remote) raise IneligiblePeer(f"Already shaking hands with {remote}") async with self._handshake_locks.lock(remote): if remote in self.connected_nodes: self.logger.debug2("Skipping %s; already connected to it", remote) raise IneligiblePeer(f"Already connected to {remote}") try: should_connect = await self.wait( self.connection_tracker.should_connect_to(remote), timeout=1, ) except TimeoutError: self.logger.warning("ConnectionTracker.should_connect_to request timed out.") raise if not should_connect: raise IneligiblePeer(f"Peer database rejected peer candidate: {remote}") try: self.logger.debug2("Connecting to %s...", remote) peer = await self.wait(handshake(remote, self.get_peer_factory())) return peer except OperationCancelled: # Pass it on to instruct our main loop to stop. raise except BadAckMessage: # This is kept separate from the # `COMMON_PEER_CONNECTION_EXCEPTIONS` to be sure that we aren't # silencing an error in our authentication code. self.logger.error('Got bad auth ack from %r', remote) # dump the full stacktrace in the debug logs self.logger.debug('Got bad auth ack from %r', remote, exc_info=True) raise except MalformedMessage: # This is kept separate from the # `COMMON_PEER_CONNECTION_EXCEPTIONS` to be sure that we aren't # silencing an error in how we decode messages during handshake. self.logger.error('Got malformed response from %r during handshake', remote) # dump the full stacktrace in the debug logs self.logger.debug('Got malformed response from %r', remote, exc_info=True) raise except HandshakeFailure as e: self.logger.debug("Could not complete handshake with %r: %s", remote, repr(e)) self.connection_tracker.record_failure(remote, e) raise except COMMON_PEER_CONNECTION_EXCEPTIONS as e: self.logger.debug("Could not complete handshake with %r: %s", remote, repr(e)) raise except Exception: self.logger.exception("Unexpected error during auth/p2p handshake with %r", remote) raise
async def connect(self, remote: Node) -> BasePeer: """ Connect to the given remote and return a Peer instance when successful. Returns None if the remote is unreachable, times out or is useless. """ if remote in self.connected_nodes: self.logger.debug2("Skipping %s; already connected to it", remote) raise IneligiblePeer(f"Already connected to {remote}") if not self.peer_info.should_connect_to(remote): raise IneligiblePeer( f"Peer database rejected peer candidate: {remote}") try: self.logger.debug2("Connecting to %s...", remote) # We use self.wait() as well as passing our CancelToken to handshake() as a workaround # for https://github.com/ethereum/py-evm/issues/670. peer = await self.wait(handshake(remote, self.get_peer_factory())) return peer except OperationCancelled: # Pass it on to instruct our main loop to stop. raise except BadAckMessage: # This is kept separate from the # `COMMON_PEER_CONNECTION_EXCEPTIONS` to be sure that we aren't # silencing an error in our authentication code. self.logger.error('Got bad auth ack from %r', remote) # dump the full stacktrace in the debug logs self.logger.debug('Got bad auth ack from %r', remote, exc_info=True) raise except MalformedMessage: # This is kept separate from the # `COMMON_PEER_CONNECTION_EXCEPTIONS` to be sure that we aren't # silencing an error in how we decode messages during handshake. self.logger.error( 'Got malformed response from %r during handshake', remote) # dump the full stacktrace in the debug logs self.logger.debug('Got malformed response from %r', remote, exc_info=True) raise except HandshakeFailure as e: self.logger.debug("Could not complete handshake with %r: %s", remote, repr(e)) self.peer_info.record_failure(remote, e) raise except COMMON_PEER_CONNECTION_EXCEPTIONS as e: self.logger.debug("Could not complete handshake with %r: %s", remote, repr(e)) raise except Exception: self.logger.exception( "Unexpected error during auth/p2p handshake with %r", remote) raise
def main(): """ Create a Peer instance connected to a local geth instance and log messages exchanged with it. Use the following command line to run geth: ~/Codes/gohome/bin/geth -vmodule p2p=4,p2p/discv5=0,eth/*=0 \ -nodekeyhex 45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8 \ -testnet -lightserv 90 """ import argparse import signal from evm.chains.ropsten import RopstenChain, ROPSTEN_GENESIS_HEADER from evm.db.backends.memory import MemoryDB from tests.p2p.integration_test_helpers import FakeAsyncChainDB logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s: %(message)s') # The default remoteid can be used if you pass nodekeyhex as above to geth. nodekey = keys.PrivateKey( decode_hex( "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") ) remoteid = nodekey.public_key.to_hex() parser = argparse.ArgumentParser() parser.add_argument('-remoteid', type=str, default=remoteid) parser.add_argument('-light', action='store_true', help="Connect as a light node") args = parser.parse_args() peer_class = ETHPeer # type: ignore if args.light: peer_class = LESPeer # type: ignore remote = Node(keys.PublicKey(decode_hex(args.remoteid)), Address('127.0.0.1', 30303, 30303)) chaindb = FakeAsyncChainDB(MemoryDB()) chaindb.persist_header(ROPSTEN_GENESIS_HEADER) network_id = RopstenChain.network_id loop = asyncio.get_event_loop() peer = loop.run_until_complete( asyncio.wait_for( handshake(remote, ecies.generate_privkey(), peer_class, chaindb, network_id), HANDSHAKE_TIMEOUT)) async def request_stuff(): # Request some stuff from ropsten's block 2440319 # (https://ropsten.etherscan.io/block/2440319), just as a basic test. nonlocal peer block_hash = decode_hex( '0x59af08ab31822c992bb3dad92ddb68d820aa4c69e9560f07081fa53f1009b152' ) if peer_class == ETHPeer: peer = cast(ETHPeer, peer) peer.sub_proto.send_get_block_headers(block_hash, 1) peer.sub_proto.send_get_block_bodies([block_hash]) peer.sub_proto.send_get_receipts([block_hash]) else: peer = cast(LESPeer, peer) request_id = 1 peer.sub_proto.send_get_block_headers(block_hash, 1, request_id) peer.sub_proto.send_get_block_bodies([block_hash], request_id + 1) peer.sub_proto.send_get_receipts(block_hash, request_id + 2) for sig in [signal.SIGINT, signal.SIGTERM]: loop.add_signal_handler(sig, peer.cancel_token.trigger) asyncio.ensure_future(request_stuff()) loop.run_until_complete(peer.run()) loop.close()