mirror of
https://github.com/varun-r-mallya/py-libp2p.git
synced 2025-12-31 20:36:24 +00:00
fix: added identify push to setup.py
This commit is contained in:
@ -35,10 +35,10 @@ from libp2p.peer.peerinfo import (
|
||||
)
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.DEBUG,
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
||||
)
|
||||
# logging.basicConfig(
|
||||
# level=logging.DEBUG,
|
||||
# format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
||||
# )
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -119,3 +119,9 @@ async def main() -> None:
|
||||
|
||||
if __name__ == "__main__":
|
||||
trio.run(main)
|
||||
|
||||
|
||||
# Non-async entry point for console script
|
||||
def run_main():
|
||||
"""Non-async entry point for the console script."""
|
||||
trio.run(main)
|
||||
|
||||
@ -23,11 +23,17 @@ import logging
|
||||
import sys
|
||||
|
||||
import multiaddr
|
||||
from multiaddr import (
|
||||
Multiaddr,
|
||||
)
|
||||
import trio
|
||||
|
||||
from libp2p import (
|
||||
new_host,
|
||||
)
|
||||
from libp2p.abc import (
|
||||
INetStream,
|
||||
)
|
||||
from libp2p.crypto.secp256k1 import (
|
||||
create_new_key_pair,
|
||||
)
|
||||
@ -35,6 +41,9 @@ from libp2p.identity.identify import (
|
||||
identify_handler_for,
|
||||
)
|
||||
from libp2p.identity.identify import ID as ID_IDENTIFY
|
||||
from libp2p.identity.identify.pb.identify_pb2 import (
|
||||
Identify,
|
||||
)
|
||||
from libp2p.identity.identify_push import (
|
||||
identify_push_handler_for,
|
||||
push_identify_to_peer,
|
||||
@ -45,16 +54,88 @@ from libp2p.peer.peerinfo import (
|
||||
)
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.DEBUG,
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
||||
)
|
||||
# logging.basicConfig(
|
||||
# level=logging.DEBUG,
|
||||
# format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
||||
# )
|
||||
logger = logging.getLogger("libp2p.identity.identify-push-example")
|
||||
|
||||
# Default port configuration
|
||||
DEFAULT_PORT = 8888
|
||||
|
||||
|
||||
def custom_identify_push_handler_for(host):
|
||||
"""
|
||||
Create a custom handler for the identify/push protocol that logs and prints
|
||||
the identity information received from the dialer.
|
||||
"""
|
||||
|
||||
async def handle_identify_push(stream: INetStream) -> None:
|
||||
peer_id = stream.muxed_conn.peer_id
|
||||
|
||||
try:
|
||||
# Read the identify message from the stream
|
||||
data = await stream.read()
|
||||
identify_msg = Identify()
|
||||
identify_msg.ParseFromString(data)
|
||||
|
||||
# Log and print the identify information
|
||||
logger.info("Received identify/push from peer %s", peer_id)
|
||||
print(f"\n==== Received identify/push from peer {peer_id} ====")
|
||||
|
||||
if identify_msg.HasField("protocol_version"):
|
||||
logger.info(" Protocol Version: %s", identify_msg.protocol_version)
|
||||
print(f" Protocol Version: {identify_msg.protocol_version}")
|
||||
|
||||
if identify_msg.HasField("agent_version"):
|
||||
logger.info(" Agent Version: %s", identify_msg.agent_version)
|
||||
print(f" Agent Version: {identify_msg.agent_version}")
|
||||
|
||||
if identify_msg.HasField("public_key"):
|
||||
logger.info(
|
||||
" Public Key: %s", identify_msg.public_key.hex()[:16] + "..."
|
||||
)
|
||||
print(f" Public Key: {identify_msg.public_key.hex()[:16]}...")
|
||||
|
||||
if identify_msg.listen_addrs:
|
||||
addrs = [Multiaddr(addr) for addr in identify_msg.listen_addrs]
|
||||
logger.info(" Listen Addresses: %s", addrs)
|
||||
print(" Listen Addresses:")
|
||||
for addr in addrs:
|
||||
print(f" - {addr}")
|
||||
|
||||
if identify_msg.HasField("observed_addr") and identify_msg.observed_addr:
|
||||
observed_addr = Multiaddr(identify_msg.observed_addr)
|
||||
logger.info(" Observed Address: %s", observed_addr)
|
||||
print(f" Observed Address: {observed_addr}")
|
||||
|
||||
if identify_msg.protocols:
|
||||
logger.info(" Protocols: %s", identify_msg.protocols)
|
||||
print(" Protocols:")
|
||||
for protocol in identify_msg.protocols:
|
||||
print(f" - {protocol}")
|
||||
|
||||
# Update the peerstore with the new information as usual
|
||||
peerstore = host.get_peerstore()
|
||||
from libp2p.identity.identify_push.identify_push import (
|
||||
_update_peerstore_from_identify,
|
||||
)
|
||||
|
||||
await _update_peerstore_from_identify(peerstore, peer_id, identify_msg)
|
||||
|
||||
logger.info("Successfully processed identify/push from peer %s", peer_id)
|
||||
print(f"\nSuccessfully processed identify/push from peer {peer_id}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Error processing identify/push from %s: %s", peer_id, e)
|
||||
print(f"\nError processing identify/push from {peer_id}: {e}")
|
||||
finally:
|
||||
# Close the stream after processing
|
||||
await stream.close()
|
||||
|
||||
return handle_identify_push
|
||||
|
||||
|
||||
async def run_listener(port: int) -> None:
|
||||
"""Run a host in listener mode."""
|
||||
print(f"\n==== Starting Identify-Push Listener on port {port} ====\n")
|
||||
@ -67,7 +148,7 @@ async def run_listener(port: int) -> None:
|
||||
|
||||
# Set up the identify and identify/push handlers
|
||||
host.set_stream_handler(ID_IDENTIFY, identify_handler_for(host))
|
||||
host.set_stream_handler(ID_IDENTIFY_PUSH, identify_push_handler_for(host))
|
||||
host.set_stream_handler(ID_IDENTIFY_PUSH, custom_identify_push_handler_for(host))
|
||||
|
||||
# Start listening
|
||||
listen_addr = multiaddr.Multiaddr(f"/ip4/0.0.0.0/tcp/{port}")
|
||||
@ -84,7 +165,7 @@ async def run_listener(port: int) -> None:
|
||||
print(f"Peer ID: {host.get_id().pretty()}")
|
||||
|
||||
print("\nRun dialer with command:")
|
||||
print(f"python identify_push_listener_dialer.py -d {addr}")
|
||||
print(f"identify-push-listener-dialer-demo -d {addr}")
|
||||
print("\nWaiting for incoming connections... (Ctrl+C to exit)")
|
||||
|
||||
# Keep running until interrupted
|
||||
|
||||
2
setup.py
2
setup.py
@ -108,6 +108,8 @@ setup(
|
||||
"echo-demo=examples.echo.echo:main",
|
||||
"ping-demo=examples.ping.ping:main",
|
||||
"identify-demo=examples.identify.identify:main",
|
||||
"identify-push-demo=examples.identify_push.identify_push_demo:run_main",
|
||||
"identify-push-listener-dialer-demo=examples.identify_push.identify_push_listener_dialer:main",
|
||||
"pubsub-demo=examples.pubsub.pubsub:main",
|
||||
],
|
||||
},
|
||||
|
||||
@ -14,6 +14,7 @@ from libp2p.identity.identify_push.identify_push import (
|
||||
_update_peerstore_from_identify,
|
||||
identify_push_handler_for,
|
||||
push_identify_to_peer,
|
||||
push_identify_to_peers,
|
||||
)
|
||||
from tests.utils.factories import (
|
||||
host_pair_factory,
|
||||
@ -24,6 +25,16 @@ logger = logging.getLogger("libp2p.identity.identify-push-test")
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_identify_push_protocol(security_protocol):
|
||||
"""
|
||||
Test the basic functionality of the identify/push protocol.
|
||||
|
||||
This test verifies that when host_a pushes identify information to host_b:
|
||||
1. The information is correctly received and processed
|
||||
2. The peerstore of host_b is updated with host_a's peer ID
|
||||
3. The peerstore contains all of host_a's addresses
|
||||
4. The peerstore contains all of host_a's supported protocols
|
||||
5. The public key in the peerstore matches host_a's public key
|
||||
"""
|
||||
async with host_pair_factory(security_protocol=security_protocol) as (
|
||||
host_a,
|
||||
host_b,
|
||||
@ -72,6 +83,17 @@ async def test_identify_push_protocol(security_protocol):
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_identify_push_handler(security_protocol):
|
||||
"""
|
||||
Test the identify_push_handler_for function specifically.
|
||||
|
||||
This test focuses on verifying that the handler function correctly:
|
||||
1. Receives the identify message
|
||||
2. Updates the peerstore with the peer information
|
||||
3. Processes all fields of the identify message (addresses, protocols, public key)
|
||||
|
||||
Note: This test is similar to test_identify_push_protocol but specifically
|
||||
focuses on the handler function's behavior.
|
||||
"""
|
||||
async with host_pair_factory(security_protocol=security_protocol) as (
|
||||
host_a,
|
||||
host_b,
|
||||
@ -120,6 +142,16 @@ async def test_identify_push_handler(security_protocol):
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_identify_push_to_peers(security_protocol):
|
||||
"""
|
||||
Test the push_identify_to_peers function to broadcast identity to multiple peers.
|
||||
|
||||
This test verifies that:
|
||||
1. Host_a can push identify information to multiple peers simultaneously
|
||||
2. The identify information is correctly received by all connected peers
|
||||
3. Both host_b and host_c have their peerstores updated with host_a's information
|
||||
|
||||
This tests the broadcasting capability of the identify/push protocol.
|
||||
"""
|
||||
# Create three hosts
|
||||
async with host_pair_factory(security_protocol=security_protocol) as (
|
||||
host_a,
|
||||
@ -178,8 +210,116 @@ async def test_identify_push_to_peers(security_protocol):
|
||||
assert peer_id_a in peerstore_c.peer_ids()
|
||||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_push_identify_to_peers_with_explicit_params(security_protocol):
|
||||
"""
|
||||
Test the push_identify_to_peers function with explicit parameters.
|
||||
|
||||
This test verifies that:
|
||||
1. The function correctly handles an explicitly provided set of peer IDs
|
||||
2. The function correctly uses the provided observed_multiaddr
|
||||
3. The identify information is only pushed to the specified peers
|
||||
4. The observed address is correctly included in the identify message
|
||||
|
||||
This test ensures all parameters of push_identify_to_peers are properly tested.
|
||||
"""
|
||||
import multiaddr
|
||||
|
||||
from libp2p import (
|
||||
new_host,
|
||||
)
|
||||
from libp2p.crypto.secp256k1 import (
|
||||
create_new_key_pair,
|
||||
)
|
||||
from libp2p.peer.peerinfo import (
|
||||
info_from_p2p_addr,
|
||||
)
|
||||
|
||||
# Create four hosts to thoroughly test selective pushing
|
||||
async with host_pair_factory(security_protocol=security_protocol) as (
|
||||
host_a,
|
||||
host_b,
|
||||
):
|
||||
# Create two additional hosts
|
||||
key_pair_c = create_new_key_pair()
|
||||
host_c = new_host(key_pair=key_pair_c)
|
||||
|
||||
key_pair_d = create_new_key_pair()
|
||||
host_d = new_host(key_pair=key_pair_d)
|
||||
|
||||
# Set up the identify/push handlers for all hosts
|
||||
host_b.set_stream_handler(ID_PUSH, identify_push_handler_for(host_b))
|
||||
host_c.set_stream_handler(ID_PUSH, identify_push_handler_for(host_c))
|
||||
host_d.set_stream_handler(ID_PUSH, identify_push_handler_for(host_d))
|
||||
|
||||
# Start listening on random ports
|
||||
listen_addr_c = multiaddr.Multiaddr("/ip4/127.0.0.1/tcp/0")
|
||||
listen_addr_d = multiaddr.Multiaddr("/ip4/127.0.0.1/tcp/0")
|
||||
|
||||
async with host_c.run([listen_addr_c]), host_d.run([listen_addr_d]):
|
||||
# Connect all hosts to host_a
|
||||
await host_c.connect(info_from_p2p_addr(host_a.get_addrs()[0]))
|
||||
await host_d.connect(info_from_p2p_addr(host_a.get_addrs()[0]))
|
||||
|
||||
# Create a specific observed multiaddr for the test
|
||||
observed_addr = multiaddr.Multiaddr("/ip4/192.0.2.1/tcp/1234")
|
||||
|
||||
# Only push to hosts B and C (not D)
|
||||
selected_peers = {host_b.get_id(), host_c.get_id()}
|
||||
|
||||
# Push identify information from host_a to selected peers with observed addr
|
||||
await push_identify_to_peers(
|
||||
host=host_a, peer_ids=selected_peers, observed_multiaddr=observed_addr
|
||||
)
|
||||
|
||||
# Wait a bit for the push to complete
|
||||
await trio.sleep(0.1)
|
||||
|
||||
# Check that host_b's and host_c's peerstores have been updated
|
||||
peerstore_b = host_b.get_peerstore()
|
||||
peerstore_c = host_c.get_peerstore()
|
||||
peerstore_d = host_d.get_peerstore()
|
||||
peer_id_a = host_a.get_id()
|
||||
|
||||
# Hosts B and C should have peer_id_a in their peerstores
|
||||
assert peer_id_a in peerstore_b.peer_ids()
|
||||
assert peer_id_a in peerstore_c.peer_ids()
|
||||
|
||||
# Host D should NOT have peer_id_a in its peerstore from the push
|
||||
# (it may still have it from the connection)
|
||||
# So we check for the observed address instead, which would only be
|
||||
# present from a push
|
||||
|
||||
# Hosts B and C should have the observed address in their peerstores
|
||||
addrs_b = [str(addr) for addr in peerstore_b.addrs(peer_id_a)]
|
||||
addrs_c = [str(addr) for addr in peerstore_c.addrs(peer_id_a)]
|
||||
|
||||
assert str(observed_addr) in addrs_b
|
||||
assert str(observed_addr) in addrs_c
|
||||
|
||||
# If host D has addresses for peer_id_a, the observed address
|
||||
# should not be there
|
||||
if peer_id_a in peerstore_d.peer_ids():
|
||||
addrs_d = [str(addr) for addr in peerstore_d.addrs(peer_id_a)]
|
||||
assert str(observed_addr) not in addrs_d
|
||||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_update_peerstore_from_identify(security_protocol):
|
||||
"""
|
||||
Test the _update_peerstore_from_identify function directly.
|
||||
|
||||
This test verifies that the internal function responsible for updating
|
||||
the peerstore from an identify message works correctly:
|
||||
1. It properly updates the peerstore with all fields from the identify message
|
||||
2. The peer ID is added to the peerstore
|
||||
3. All addresses are correctly stored
|
||||
4. All protocols are correctly stored
|
||||
5. The public key is correctly stored
|
||||
|
||||
This tests the low-level peerstore update mechanism used by
|
||||
the identify/push protocol.
|
||||
"""
|
||||
async with host_pair_factory(security_protocol=security_protocol) as (
|
||||
host_a,
|
||||
host_b,
|
||||
@ -225,6 +365,19 @@ async def test_update_peerstore_from_identify(security_protocol):
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_partial_update_peerstore_from_identify(security_protocol):
|
||||
"""
|
||||
Test partial updates of the peerstore using the identify/push protocol.
|
||||
|
||||
This test verifies that:
|
||||
1. A partial identify message (containing only some fields) correctly updates
|
||||
the peerstore without affecting other existing information
|
||||
2. New protocols are added to the existing set in the peerstore
|
||||
3. The original protocols, addresses, and public key remain intact
|
||||
4. The update is additive rather than replacing all existing data
|
||||
|
||||
This tests the ability of the identify/push protocol to handle incremental
|
||||
or partial updates to peer information.
|
||||
"""
|
||||
async with host_pair_factory(security_protocol=security_protocol) as (
|
||||
host_a,
|
||||
host_b,
|
||||
|
||||
Reference in New Issue
Block a user