Skip to content

Latest commit

 

History

History
707 lines (553 loc) · 28.4 KB

File metadata and controls

707 lines (553 loc) · 28.4 KB

libp2p Integration for IPFS Kit

Overview

The libp2p integration provides direct peer-to-peer communication capabilities for IPFS Kit without requiring a full IPFS daemon. This enables lightweight nodes to participate in the network, establish direct connections with peers, and exchange content efficiently. The integration includes a sophisticated bitswap implementation, enhanced DHT discovery, and seamless integration with the tiered storage system.

This implementation is part of Phase 3A: Direct P2P Communication in the IPFS Kit development roadmap, focusing on direct peer-to-peer content exchange for improved performance and reduced dependency on central infrastructure.

Key Features

  • Direct Peer Connections: Establish direct connections with other peers using libp2p
  • Protocol Negotiation: Dynamically negotiate protocols for communication
  • Enhanced Bitswap Protocol: Advanced content exchange with priority handling and wantlists
  • Secure Messaging: Encrypted and authenticated communication between peers
  • NAT Traversal: Reliable connectivity across network boundaries through relays and hole punching
  • Enhanced DHT Discovery: Improved peer discovery with k-bucket optimization for efficient routing
  • Multi-Layer Peer Discovery: Find peers using DHT, mDNS, bootstrap nodes, PubSub, and random walks
  • Intelligent Content Routing: Uses network metrics and peer statistics to find optimal content providers
  • Provider Reputation Tracking: Tracks reliability and performance of content providers
  • Role-Based Behavior: Specialized behavior based on node role (master/worker/leecher)
  • Tiered Storage Integration: Seamless access to content across different storage tiers
  • Heat-Based Promotion: Automatic content promotion based on access patterns
  • Cache Miss Handling: Automatically retrieves content via P2P when not found in cache

Architecture

The libp2p integration implements a layered architecture with several key components:

Component Overview

  1. IPFSLibp2pPeer (libp2p_peer.py): Main class for direct P2P communication

    • Handles peer connections, discovery, and content exchange
    • Implements role-specific behaviors (master/worker/leecher)
    • Integrates with tiered storage system
    • Manages protocol negotiation and message handling
  2. Enhanced DHT Discovery (enhanced_dht_discovery.py): Advanced peer discovery

    • Implements k-bucket optimization for more efficient routing
    • Tracks provider reputation and reliability
    • Implements content-based peer affinity
    • Provides role-specific optimizations
    • Manages backoff strategies for unreliable peers
  3. Content Routing Manager (enhanced_dht_discovery.py): Intelligent content discovery

    • Finds optimal providers based on multiple metrics
    • Manages content retrieval from best available sources
    • Tracks content availability across the network
    • Announces local content to the network
    • Collects performance metrics for optimization
  4. LibP2P Integration (p2p_integration.py): Connection between libp2p and storage

    • Handles cache misses by retrieving content via libp2p
    • Integrates with TieredCacheManager for content storage
    • Announces cached content to the network
    • Tracks statistics and performance metrics
    • Manages recovery strategies for network failures
  5. IPFS Kit Integration (ipfs_kit_integration.py): High-level integration

    • Extends IPFSKit class with libp2p functionality
    • Modifies get_filesystem method to include libp2p support
    • Provides automatic creation of libp2p peer when needed
    • Enables seamless fallback to libp2p for content not in cache

Layered Design

The integration follows a layered design:

┌───────────────────────────────────────────────────────────┐
│                 Extension Layer (ipfs_kit_integration.py)  │
│   Extends IPFSKit with libp2p functionality and modifies   │
│       get_filesystem to include libp2p support             │
└────────────────────────────┬──────────────────────────────┘
                             │
┌────────────────────────────▼──────────────────────────────┐
│              Integration Layer (p2p_integration.py)        │
│   Connects libp2p functionality with IPFSKit and tiered    │
│                        storage                             │
└────────────────────────────┬──────────────────────────────┘
                             │
┌────────────────────────────▼──────────────────────────────┐
│                 Core Layer (libp2p_peer.py)                │
│  Implements direct peer-to-peer communication using libp2p │
└────────────────────────────┬──────────────────────────────┘
                             │
┌────────────────────────────▼──────────────────────────────┐
│           Base Layer (enhanced_dht_discovery.py)           │
│    Enhanced DHT discovery and content routing components   │
└───────────────────────────────────────────────────────────┘

Integration with Tiered Storage

The libp2p integration extends the tiered storage system with P2P content retrieval:

┌─────────────────┐     ┌────────────────────┐
│  Memory Cache   │─────►  When content not  │
└────────┬────────┘     │   found in cache,  │
         │              │   retrieve via     │
┌────────▼────────┐     │       libp2p       │
│   Disk Cache    │────►│                    │
└────────┬────────┘     └─────────┬──────────┘
         │                        │
┌────────▼────────┐              │
│  Local IPFS or  │              │
│  Gateway Access │              │
└────────┬────────┘              │
         │                       │
┌────────▼────────┐     ┌────────▼────────┐
│  IPFS Cluster   │     │   P2P Network   │
└────────┬────────┘     │    Discovery    │
         │              └────────┬────────┘
┌────────▼────────┐              │
│    Storacha     │     ┌────────▼────────┐
└────────┬────────┘     │  Content Routing │
         │              └────────┬────────┘
┌────────▼────────┐              │
│    Filecoin     │     ┌────────▼────────┐
└─────────────────┘     │  Direct Content  │
                        │    Retrieval     │
                        └─────────────────┘

Implementation Details

Enhanced DHT Discovery

The EnhancedDHTDiscovery class provides advanced peer discovery beyond the basic DHT functionality:

class EnhancedDHTDiscovery:
    """Enhanced DHT-based discovery implementation for libp2p peers.
    
    This class improves upon the basic DHT discovery with:
    - Advanced routing algorithm with k-bucket optimizations
    - Provider tracking with reputation scoring
    - Content-based peer affinity for better routing
    - Role-specific optimizations
    - Backoff strategies for unreliable peers
    """

Key methods include:

  • find_providers(cid, count=5): Find providers for specific content
  • add_provider(cid, peer_id): Register a provider for content
  • get_optimal_providers(cid, count=3): Find best providers based on metrics
  • update_provider_stats(peer_id, success, latency): Track provider performance

Content Routing Manager

The ContentRoutingManager class handles intelligent content discovery and retrieval:

class ContentRoutingManager:
    """Manages content discovery and routing for the libp2p peer.
    
    This class provides:
    - Intelligent content provider selection
    - Content retrieval from best available sources
    - Content availability announcements
    - Performance metrics collection
    """

Key methods include:

  • find_content(cid, options=None): Find content in the network
  • retrieve_content(cid, options=None): Get content from best provider
  • announce_content(cid, size=None, metadata=None): Announce content availability
  • get_metrics(): Get performance metrics for content routing

LibP2P Integration

The LibP2PIntegration class connects libp2p functionality with the IPFSKit and cache system:

class LibP2PIntegration:
    """Integration layer between libp2p peer discovery and the filesystem cache.
    
    This class:
    - Handles cache misses by retrieving content via libp2p
    - Announces cached content to the network
    - Tracks statistics and performance metrics
    """

Key methods include:

  • handle_cache_miss(cid): Retrieve content when not found in cache
  • announce_content(cid, data=None, size=None, metadata=None): Announce content
  • get_stats(): Get integration statistics

IPFSKit Integration

The ipfs_kit_integration.py module extends the IPFSKit class with libp2p functionality:

def extend_ipfs_kit_class(ipfs_kit_cls):
    """Extend the IPFSKit class with libp2p miss handler functionality.
    
    This function:
    - Adds _handle_content_miss_with_libp2p method to IPFSKit
    - Modifies get_filesystem to include libp2p integration
    - Enables automatic libp2p peer creation when needed
    """

Usage

Basic Usage with IPFSKit Integration

The simplest way to use the libp2p integration is through the IPFSKit class:

from ipfs_kit_py.ipfs_kit import ipfs_kit
from ipfs_kit_py.libp2p.ipfs_kit_integration import apply_ipfs_kit_integration

# Apply the integration to the IPFSKit class
apply_ipfs_kit_integration()

# Create an IPFSKit instance
kit = ipfs_kit()

# Get a filesystem interface with libp2p integration
fs = kit.get_filesystem(use_libp2p=True)

# Add content to IPFS
result = kit.ipfs_add_string("Hello, IPFS Kit with LibP2P integration!")
cid = result["Hash"]

# Retrieve content using the filesystem interface
# This will automatically use libp2p if the content isn't in the cache
content = fs.cat(cid)

Direct Peer-to-Peer Usage

For more direct control over peer-to-peer communication:

from ipfs_kit_py.libp2p_peer import IPFSLibp2pPeer

# Initialize a libp2p peer with default settings
peer = IPFSLibp2pPeer(
    role="worker",
    listen_addrs=["/ip4/0.0.0.0/tcp/0", "/ip4/0.0.0.0/udp/0/quic"]
)

# Connect to a remote peer
peer.connect_peer("/ip4/192.168.1.10/tcp/4001/p2p/QmRemotePeerId")

# Request content directly from connected peers
content = peer.request_content("QmContentHash")

# Announce available content to the network
peer.announce_content("QmContentHash", metadata={"size": 1024})

# Start discovery to find more peers
peer.start_discovery()

Tiered Storage Integration

from ipfs_kit_py.libp2p_peer import IPFSLibp2pPeer
from ipfs_kit_py.tiered_cache import TieredCacheManager

# Initialize tiered storage manager
storage_manager = TieredCacheManager({
    'memory_cache_size': 100 * 1024 * 1024,  # 100MB
    'local_cache_size': 1 * 1024 * 1024 * 1024,  # 1GB
    'local_cache_path': '/tmp/ipfs_cache'
})

# Create a peer with tiered storage integration
peer = IPFSLibp2pPeer(
    role="worker",
    listen_addrs=["/ip4/0.0.0.0/tcp/4001"],
    tiered_storage_manager=storage_manager
)

# Store content in local store and announce to network
content = b"Hello, IPFS!"
cid = "QmExampleContentID"
peer.store_bytes(cid, content)
peer.announce_content(cid, metadata={"size": len(content)})

# When content is requested, it will automatically:
# 1. Check memory store first
# 2. Check tiered storage if not in memory
# 3. Track access heat for promotion to faster tiers

Advanced Configuration

from ipfs_kit_py.libp2p_peer import IPFSLibp2pPeer
import anyio

# Create a peer with advanced configuration
peer = IPFSLibp2pPeer(
    role="master",
    identity_path="~/.ipfs/libp2p_identity",
    listen_addrs=[
        "/ip4/0.0.0.0/tcp/4001",
        "/ip4/0.0.0.0/udp/4001/quic"
    ],
    bootstrap_peers=[
        "/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
        "/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa"
    ],
    enable_mdns=True,
    enable_hole_punching=True,
    enable_relay=True,
    tiered_storage_manager=storage_manager
)

# Register a custom protocol handler
async def handle_custom_protocol(stream):
    data = await stream.read()
    # Process the request
    await stream.write(b"Response data")
    await stream.close()

peer.register_protocol_handler("/my/custom/protocol/1.0.0", handle_custom_protocol)

Using Advanced DHT and Content Routing

For more control over the discovery and routing process:

from ipfs_kit_py.libp2p_peer import IPFSLibp2pPeer
from ipfs_kit_py.libp2p.enhanced_dht_discovery import EnhancedDHTDiscovery, ContentRoutingManager

# Create libp2p peer
peer = IPFSLibp2pPeer(role="worker")

# Create enhanced discovery
discovery = EnhancedDHTDiscovery(
    peer,
    role="worker",
    bootstrap_peers=[
        "/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN"
    ]
)
discovery.start()

# Create content routing manager
router = ContentRoutingManager(discovery, peer)

# Find providers for content
providers = discovery.find_providers("QmContentHash", count=5)
print(f"Found {len(providers)} providers for the content")

# Get optimal providers based on metrics
optimal_providers = discovery.get_optimal_providers(
    "QmContentHash",
    content_size=1024*1024,  # 1MB
    count=3
)
print(f"Best providers: {optimal_providers}")

# Retrieve content using the router
future = router.retrieve_content("QmContentHash", {
    'timeout': 30,
    'max_size': 10 * 1024 * 1024  # 10MB
})
content = future.result(timeout=30)

Integrating with Existing IPFSKit Instance

from ipfs_kit_py.ipfs_kit import ipfs_kit
from ipfs_kit_py.libp2p_peer import IPFSLibp2pPeer
from ipfs_kit_py.libp2p.p2p_integration import register_libp2p_with_ipfs_kit

# Create an IPFSKit instance
kit = ipfs_kit()

# Create a custom libp2p peer
libp2p_peer = IPFSLibp2pPeer(
    role="worker",
    bootstrap_peers=[
        "/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN"
    ],
    listen_addrs=[
        "/ip4/0.0.0.0/tcp/4001"
    ]
)

# Register the peer with the kit
integration = register_libp2p_with_ipfs_kit(kit, libp2p_peer, extend_cache=True)

# Now kit.get_filesystem() will use libp2p for cache misses
fs = kit.get_filesystem()

# Access integration statistics
stats = integration.get_stats()
print(f"Cache miss success rate: {stats['success_rate']:.2f}")

Role-Based Architecture Integration

The libp2p implementation integrates with our role-based architecture, providing optimized behaviors for each node type:

Master Nodes

  • Operate as full DHT server nodes with comprehensive routing tables
  • Proactively fetch popular content based on cluster-wide heat scores
  • Provide relay services for peers behind NAT
  • Maintain metadata about content providers across the network
  • Handle task distribution and coordination through PubSub
  • Keep backup provider information for redundancy
  • Use higher connection limits for wider network reach
  • Subscribe to network-wide content announcements
  • Implement sophisticated content routing algorithms
  • Store content with higher replication factors
  • Run comprehensive peer discovery processes

Worker Nodes

  • Actively contribute processing capabilities to the network
  • Execute task assignments from master nodes via PubSub
  • Participate in content distribution and replication
  • Provide relay services when appropriate
  • Operate as DHT server nodes but with more selective routing tables
  • Implement specialized caching based on assigned tasks
  • Focus on peer connections relevant to current workloads
  • Prioritize content related to active processing tasks
  • Balance resource allocation between processing and routing
  • Implement efficient content exchange protocols
  • Use moderate connection limits for focused networking

Leecher Nodes

  • Optimize for minimal resource usage
  • Connect to a limited set of peers (primarily master nodes)
  • Use DHT in client mode for resource efficiency
  • Prefer direct content retrieval over relaying
  • Implement efficient local caching with strict size limits
  • Optimize for offline/intermittent connectivity
  • Minimize network and storage overhead
  • Use aggressive connection pruning
  • Implement simplified discovery mechanisms
  • Prioritize local content access over network requests
  • Focus on retaining frequently accessed content locally
  • Implement battery-efficient networking on mobile devices

Performance Optimizations

The implementation includes several key performance optimizations:

Network Optimizations

  • Protocol Negotiation: Automatically select the most efficient protocol for each peer
  • Connection Pooling: Reuse connections for multiple requests to the same peer
  • Concurrent Requests: Request content from multiple providers in parallel
  • Connection Pruning: Close idle connections to free up resources
  • Adaptive Timeouts: Adjust request timeouts based on network conditions
  • Retry Logic: Intelligently retry failed requests with backoff strategies

Resource Management

  • Adaptive Buffer Sizes: Adjust buffer sizes based on content type and size
  • Memory Mapping: Use memory mapping for large content to reduce memory usage
  • Incremental Content Loading: Load content incrementally for large files
  • Connection Limits: Enforce role-specific connection limits to prevent resource exhaustion
  • Thread Pool Management: Optimize thread usage for async operations
  • Event Loop Optimization: Efficient event loop management for async I/O

Content Discovery

  • Provider Caching: Cache provider information to reduce discovery overhead
  • Priority-Based Discovery: Prioritize discovery for high-demand content
  • Locality-Aware Routing: Prefer providers with lower network latency
  • Multipath Discovery: Try multiple discovery mechanisms in parallel
  • Backoff for Unreliable Peers: Implement exponential backoff for unreliable peers
  • Content Affinity: Track which peers tend to have related content

Caching Strategy

  • Predictive Prefetching: Prefetch content likely to be requested soon
  • Heat-Based Caching: Use sophisticated heat scoring for cache management
  • Content Chunking: Break large content into chunks for more efficient caching
  • Metadata Caching: Cache metadata separately from content for faster lookups
  • Adaptive Replacement Policy: Balance recency and frequency in cache eviction
  • Size-Aware Caching: Consider content size in caching decisions

Example Implementation Patterns

Cache Miss Handling with libp2p

def handle_cache_miss(cid):
    """Handle a cache miss by attempting to retrieve content via libp2p."""
    self.stats['cache_misses'] += 1
    
    try:
        self.logger.debug(f"Handling cache miss for {cid} via libp2p")
        
        # Create a future for content retrieval
        future = self.content_router.retrieve_content(cid, {
            'timeout': 30,  # 30 second timeout
            'max_size': 50 * 1024 * 1024  # 50MB size limit
        })
        
        # Get result from future
        start_time = time.time()
        content = future.result(timeout=30)
        retrieve_time = time.time() - start_time
        
        if content:
            # Successfully retrieved content
            self.stats['cache_misses_handled'] += 1
            self.stats['total_bytes_retrieved'] += len(content)
            self.stats['retrieve_times'].append(retrieve_time)
            
            # Update the cache with the retrieved content
            if self.cache_manager:
                self.cache_manager.put(cid, content)
            
            self.logger.info(
                f"Successfully retrieved {cid} via libp2p "
                f"({len(content)} bytes in {retrieve_time:.2f}s)"
            )
            
            return content
        else:
            # Failed to retrieve
            self.stats['cache_misses_failed'] += 1
            self.logger.warning(f"Failed to retrieve {cid} via libp2p")
            return None
            
    except Exception as e:
        self.stats['cache_misses_failed'] += 1
        self.logger.error(f"Error handling cache miss for {cid}: {e}")
        return None

DHT-Based Provider Discovery

async def find_providers_async(self, cid, count=5):
    """Find providers for content using enhanced DHT discovery."""
    providers = []
    
    # Try to find providers in the DHT
    try:
        # Use our enhanced discovery with reputation tracking
        provider_info = await self.dht.get_providers(cid, count * 2)
        
        # Sort providers by reputation
        sorted_providers = sorted(
            provider_info,
            key=lambda p: p.get('reputation', 0.5),
            reverse=True
        )
        
        # Take the best providers up to count
        providers = sorted_providers[:count]
        
        self.logger.debug(f"Found {len(providers)} providers for {cid}")
        
    except Exception as e:
        self.logger.warning(f"Error finding providers for {cid}: {e}")
    
    return providers

Role-Specific Connection Management

def _setup_connection_manager(self):
    """Configure connection manager based on node role."""
    if self.role == "master":
        # Masters maintain more connections for better network view
        low_water = 100
        high_water = 400
        grace_period = "30s"
    elif self.role == "worker":
        # Workers maintain moderate connections focused on tasks
        low_water = 50
        high_water = 200
        grace_period = "20s"
    else:  # leecher
        # Leechers minimize connections to save resources
        low_water = 20
        high_water = 100
        grace_period = "10s"
    
    # Apply configuration to the connection manager
    self.host.get_network().get_connection_manager().set_connection_limits(
        low_water=low_water,
        high_water=high_water,
        grace_period=grace_period
    )

Testing and Metrics

The libp2p integration includes comprehensive testing and metrics collection:

Testing

The implementation can be tested using the unit tests in /test/test_libp2p_integration.py. These tests verify:

  • Connection establishment and peer discovery
  • Content routing and provider discovery
  • Cache miss handling through libp2p
  • Performance metrics collection
  • Role-specific behavior (master/worker/leecher)
  • Error handling and timeout management

Example test run:

python -m unittest test.test_libp2p_integration

Performance Metrics

The integration collects performance metrics accessible through get_stats():

# Get statistics from the integration
stats = integration.get_stats()

print(f"Cache misses: {stats.get('cache_misses', 0)}")
print(f"Cache misses handled: {stats.get('cache_misses_handled', 0)}")
print(f"Success rate: {stats.get('success_rate', 0):.2f}")
print(f"Average retrieval time: {stats.get('average_retrieve_time', 0):.2f}s")
print(f"Total bytes retrieved: {stats.get('total_bytes_retrieved', 0)}")

# Discovery metrics
discovery_metrics = stats.get('discovery_metrics', {})
print(f"Providers found: {discovery_metrics.get('providers_found', 0)}")
print(f"Failed discoveries: {discovery_metrics.get('failed_discoveries', 0)}")

These metrics provide valuable insights into the performance of the libp2p integration and can help identify optimization opportunities.

Error Handling and Recovery

The implementation includes comprehensive error handling and recovery strategies:

  • Connection Failures: Implement automatic retry with exponential backoff
  • Timeout Management: Adaptive timeout handling based on content size and network conditions
  • Provider Failures: Track provider reliability and adjust selection accordingly
  • Partial Content Handling: Deal gracefully with partially retrieved content
  • Background Recovery: Attempt recovery in background threads
  • Fallback Mechanisms: Use alternative retrieval methods when primary methods fail
  • Detailed Logging: Comprehensive logging for troubleshooting

Future Enhancements

Planned enhancements for the libp2p integration include:

High Priority Enhancements

  • WebTransport Integration: Critical for browser connectivity, enabling web applications to connect directly to libp2p nodes without using WebSockets
  • QUIC Transport: Improved performance with multiplexed connections, reduced latency, and better congestion control
  • AutoNAT Protocol: Automatic NAT detection for more reliable connectivity across network boundaries
  • Direct Connection Upgrade (DCUTR): Enhanced NAT traversal through direct connection upgrade techniques
  • Advanced Gossipsub Features: Security improvements including message signing, validation, and peer scoring

Medium Priority Enhancements

  • GraphSync Protocol: Support for efficient graph-based data exchange using IPLD selectors
  • yamux Multiplexing: Better performance for many streams compared to the current mplex implementation
  • Bandwidth Throttling and QoS: Prioritize important content in bandwidth allocation
  • Enhanced Security: Authentication and authorization mechanisms including TLS 1.3 and improved Noise protocol
  • Peer Reputation System: Sophisticated peer quality metrics for better routing
  • Resource Manager: Comprehensive resource limitation functionality to prevent resource exhaustion

Additional Planned Features

  • Rendezvous Protocol: Enhanced peer discovery through rendezvous points
  • Relay v2 Support: Advanced relay capabilities for NAT traversal
  • Bloom Filter Advertisements: More efficient content routing with Bloom filters
  • IPLD-Based Content Verification: Verify content integrity using IPLD mechanisms
  • Cross-Language Shared Memory: Improved interoperability via shared memory interfaces
  • Advanced Relay Selection: Network topology awareness for relay selection
  • Distributed Task Scheduling: Enhanced computation scheduling using P2P communication
  • Content Encryption: End-to-end encryption for sensitive content
  • Mobile Optimizations: Battery and bandwidth efficiency for mobile devices

For a detailed implementation plan and timeline for these enhancements, see the LIBP2P_IMPLEMENTATION_PLAN.md document.

Complete Example

A complete example demonstrating the libp2p integration is available in /examples/libp2p_example.py. This example shows:

  1. Setting up IPFS Kit with libp2p integration
  2. Adding test content to IPFS
  3. Retrieving content via filesystem interface with libp2p fallback
  4. Testing direct content retrieval using libp2p
  5. Displaying integration statistics

To run the example:

python examples/libp2p_example.py

The example provides a practical demonstration of how to use the libp2p integration for direct peer-to-peer content exchange, making it an excellent starting point for developers integrating this functionality into their own applications.

Also, the 'ls' command is not currently supported in enhanced mode.