Replies: 10 comments 11 replies
-
@seetadev interop-py-js-libp2p/
├── js_node/
│ └── ping-server.js # JS ping listener
├── py_node/
│ └── ping_client.py # Python dialer
├── scripts/
│ └── run_test.sh # Launch both nodes and validate
├── README.md # This file how do you suggest to add other test like |
Beta Was this translation helpful? Give feedback.
-
@acul71 , @Nkovaturient and @paschal533 : Great initiative. Appreciate the efforts. I am opening an issue right away. |
Beta Was this translation helpful? Give feedback.
-
Wish to share some key meeting points from JS-libp2p maintainer's meeting. To enable successful
Once these are in place, basic interop tests (e.g., successful echo and RTT) can be conducted reliably. @acul71 , @paschal533 and @Nkovaturient : Looking forward to the PR. Interop tests will be added at https://github.com/libp2p/test-plans |
Beta Was this translation helpful? Give feedback.
-
@Nkovaturient |
Beta Was this translation helpful? Give feedback.
-
Hi @acul71, @Nkovaturient, @seetadev I've been working on the py-libp2p ↔ js-libp2p interop testing and found an interesting issue with the multistream-select negotiation. The initial connection and Yamux muxing works fine, I can see successful stream creation in the logs. The problem occurs during protocol negotiation when js-libp2p tries to read the multistream response. Python side shows streams with IDs 1 and 3 being created, but then hits a The connection establishment is successful (both sides show proper peer IDs). Yamux multiplexing is working (streams are being created). The failure happens specifically in the multistream-select protocol negotiation. The JS side is timing out/aborting when trying to read the protocol response Potential issues I'm investigating:
The fact that we get to the point of creating Yamux streams suggests the core networking stack is compatible, but there's something subtle in the protocol negotiation layer that's causing the abort. I'm going to dig deeper into the multistream-select implementation differences and see if there are any known compatibility issues between the Python and JS versions. Will update with findings. |
Beta Was this translation helpful? Give feedback.
-
@seetadev @paschal533 @Nkovaturient @achingbrain Python-JavaScript Yamux Interoperability Success ReportOverviewThis document summarizes the successful interoperability test between the Python and JavaScript implementations of the yamux stream multiplexer, describes the root cause of the previous failure, how it was fixed, and cites the relevant specifications and code from both sides. Problem Summary
Root Cause
The Fix
Relevant Specification
Relevant JavaScript Code
Relevant Python Code (Before and After)
Test Result
Final Python Logic and ReasoningAfter careful analysis and testing, the correct, spec-compliant Python logic for stream creation is: if (typ == TYPE_DATA or typ == TYPE_WINDOW_UPDATE) and flags & FLAG_SYN:
# Create new stream
Why Not Just
|
Beta Was this translation helpful? Give feedback.
-
Hi @seetadev, @Nkovaturient, @achingbrain. After making the changes @acul71 recommended in Yamux.py, I was able to run the ping interop test successfully with Yamux and Noise. if (typ == TYPE_DATA or typ == TYPE_WINDOW_UPDATE) and flags & FLAG_SYN:
Python ping.pyimport argparse
import logging
from cryptography.hazmat.primitives.asymmetric import (
x25519,
)
import multiaddr
import trio
from libp2p import (
generate_new_rsa_identity,
new_host,
)
from libp2p.custom_types import (
TProtocol,
)
from libp2p.network.stream.net_stream import (
INetStream,
)
from libp2p.peer.peerinfo import (
info_from_p2p_addr,
)
from libp2p.security.noise.transport import Transport as NoiseTransport
from libp2p.stream_muxer.yamux.yamux import (
Yamux,
)
from libp2p.stream_muxer.yamux.yamux import PROTOCOL_ID as YAMUX_PROTOCOL_ID
# Configure detailed logging
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s - %(levelname)s - %(message)s",
handlers=[
logging.StreamHandler(),
logging.FileHandler("ping_debug.log", mode="w", encoding="utf-8"),
],
)
# Standard libp2p ping protocol
PING_PROTOCOL_ID = TProtocol("/ipfs/ping/1.0.0")
PING_LENGTH = 32
RESP_TIMEOUT = 60
async def handle_ping(stream: INetStream) -> None:
"""Handle incoming ping requests from js-libp2p clients"""
peer_id = stream.muxed_conn.peer_id
print(f"[INFO] New ping stream opened by {peer_id}")
logging.info(f"Ping handler called for peer {peer_id}")
ping_count = 0
try:
while True:
try:
print(f"[INFO] Waiting for ping data from {peer_id}...")
logging.debug(f"Stream state: {stream}")
data = await stream.read(PING_LENGTH)
if not data:
print(
f"[INFO] No data received,"
f" connection likely closed by {peer_id}"
)
logging.debug("No data received, stream closed")
break
if len(data) == 0:
print(f"[INFO] Empty data received, connection closed by {peer_id}")
logging.debug("Empty data received")
break
ping_count += 1
print(
f"[PING {ping_count}] Received ping from {peer_id}:"
f" {len(data)} bytes"
)
logging.debug(f"Ping data: {data.hex()}")
# Echo the data back (this is what ping protocol does)
await stream.write(data)
print(f"[PING {ping_count}] Echoed ping back to {peer_id}")
except Exception as e:
print(f"[ERROR] Error in ping loop with {peer_id}: {e}")
logging.exception("Ping loop error")
break
except Exception as e:
print(f"[ERROR] Error handling ping from {peer_id}: {e}")
logging.exception("Ping handler error")
finally:
try:
print(f"[INFO] Closing ping stream with {peer_id}")
await stream.close()
except Exception as e:
logging.debug(f"Error closing stream: {e}")
print(f"[INFO] Ping session completed with {peer_id} ({ping_count} pings)")
async def send_ping_sequence(stream: INetStream, count: int = 5) -> None:
"""Send a sequence of pings compatible with js-libp2p."""
peer_id = stream.muxed_conn.peer_id
print(f"[INFO] Starting ping sequence to {peer_id} ({count} pings)")
import os
import time
rtts = []
for i in range(1, count + 1):
try:
# Generate random 32-byte payload as per ping protocol spec
payload = os.urandom(PING_LENGTH)
print(f"[PING {i}/{count}] Sending ping to {peer_id}")
logging.debug(f"Sending payload: {payload.hex()}")
start_time = time.time()
await stream.write(payload)
with trio.fail_after(RESP_TIMEOUT):
response = await stream.read(PING_LENGTH)
end_time = time.time()
rtt = (end_time - start_time) * 1000
if (
response
and len(response) >= PING_LENGTH
and response[:PING_LENGTH] == payload
):
rtts.append(rtt)
print(f"[PING {i}] Successful! RTT: {rtt:.2f}ms")
else:
print(f"[ERROR] Ping {i} failed: response mismatch or incomplete")
if response:
logging.debug(f"Expected: {payload.hex()}")
logging.debug(f"Received: {response.hex()}")
if i < count:
await trio.sleep(1)
except trio.TooSlowError:
print(f"[ERROR] Ping {i} timed out after {RESP_TIMEOUT}s")
except Exception as e:
print(f"[ERROR] Ping {i} failed: {e}")
logging.exception(f"Ping {i} error")
# Print statistics
if rtts:
avg_rtt = sum(rtts) / len(rtts)
min_rtt = min(rtts)
max_rtt = max(rtts)
success_count = len(rtts)
loss_rate = ((count - success_count) / count) * 100
print("\n[STATS] Ping Statistics:")
print(
f" Packets: Sent={count}, Received={success_count},"
f" Lost={count - success_count}"
)
print(f" Loss rate: {loss_rate:.1f}%")
print(
f" RTT: min={min_rtt:.2f}ms, avg={avg_rtt:.2f}ms," f" max={max_rtt:.2f}ms"
)
else:
print(f"\n[STATS] All pings failed ({count} attempts)")
def create_noise_keypair():
"""Create a Noise protocol keypair for secure communication"""
try:
x25519_private_key = x25519.X25519PrivateKey.generate()
class NoisePrivateKey:
def __init__(self, key):
self._key = key
def to_bytes(self):
return self._key.private_bytes_raw()
def public_key(self):
return NoisePublicKey(self._key.public_key())
def get_public_key(self):
return NoisePublicKey(self._key.public_key())
class NoisePublicKey:
def __init__(self, key):
self._key = key
def to_bytes(self):
return self._key.public_bytes_raw()
return NoisePrivateKey(x25519_private_key)
except Exception as e:
logging.error(f"Failed to create Noise keypair: {e}")
return None
async def run_server(port: int) -> None:
"""Run ping server that accepts connections from js-libp2p clients."""
listen_addr = multiaddr.Multiaddr(f"/ip4/0.0.0.0/tcp/{port}")
key_pair = generate_new_rsa_identity()
logging.debug("Generated RSA keypair")
noise_privkey = create_noise_keypair()
if not noise_privkey:
print("[ERROR] Failed to create Noise keypair")
return
logging.debug("Generated Noise keypair")
noise_transport = NoiseTransport(key_pair, noise_privkey=noise_privkey)
logging.debug(f"Noise transport initialized: {noise_transport}")
sec_opt = {TProtocol("/noise"): noise_transport}
muxer_opt = {TProtocol(YAMUX_PROTOCOL_ID): Yamux}
logging.info(f"Using muxer: {muxer_opt}")
host = new_host(key_pair=key_pair, sec_opt=sec_opt, muxer_opt=muxer_opt)
print("[INFO] Starting py-libp2p ping server...")
async with host.run(listen_addrs=[listen_addr]):
print(f"[INFO] Registering ping handler for protocol: {PING_PROTOCOL_ID}")
host.set_stream_handler(PING_PROTOCOL_ID, handle_ping)
# Also register alternative protocol IDs for better compatibility
alt_protocols = [
TProtocol("/ping/1.0.0"),
TProtocol("/libp2p/ping/1.0.0"),
]
for alt_proto in alt_protocols:
print(f"[INFO] Also registering handler for: {alt_proto}")
host.set_stream_handler(alt_proto, handle_ping)
print("[INFO] Server started successfully!")
print(f"[INFO] Peer ID: {host.get_id()}")
print(f"[INFO] Listening: /ip4/0.0.0.0/tcp/{port}")
print(f"[INFO] Primary Protocol: {PING_PROTOCOL_ID}")
print("[INFO] Security: Noise encryption")
print("[INFO] Muxer: Yamux stream multiplexing")
print("\n[INFO] Registered protocols:")
print(f" - {PING_PROTOCOL_ID}")
for proto in alt_protocols:
print(f" - {proto}")
peer_id = host.get_id()
print("\n[TEST] Test with rust-libp2p:")
print(f" node ping.js client -- /ip4/127.0.0.1/tcp/{port}/p2p/{peer_id}")
print("\n[TEST] Test with py-libp2p:")
print(f" python ping.py client /ip4/127.0.0.1/tcp/{port}/p2p/{peer_id}")
print("\n[INFO] Waiting for connections...")
print("Press Ctrl+C to exit")
await trio.sleep_forever()
async def run_client(destination: str, count: int = 5) -> None:
"""Run ping client to test connectivity with another peer."""
listen_addr = multiaddr.Multiaddr("/ip4/0.0.0.0/tcp/0")
key_pair = generate_new_rsa_identity()
logging.debug("Generated RSA keypair")
noise_privkey = create_noise_keypair()
if not noise_privkey:
print("[ERROR] Failed to create Noise keypair")
return 1
logging.debug("Generated Noise keypair")
noise_transport = NoiseTransport(key_pair, noise_privkey=noise_privkey)
logging.debug(f"Noise transport initialized: {noise_transport}")
sec_opt = {TProtocol("/noise"): noise_transport}
muxer_opt = {TProtocol(YAMUX_PROTOCOL_ID): Yamux}
logging.info(f"Using muxer: {muxer_opt}")
host = new_host(key_pair=key_pair, sec_opt=sec_opt, muxer_opt=muxer_opt)
print("[INFO] Starting py-libp2p ping client...")
async with host.run(listen_addrs=[listen_addr]):
print(f"[INFO] Our Peer ID: {host.get_id()}")
print(f"[INFO] Target: {destination}")
print("[INFO] Security: Noise encryption")
print("[INFO] Muxer: Yamux stream multiplexing")
try:
maddr = multiaddr.Multiaddr(destination)
info = info_from_p2p_addr(maddr)
target_peer_id = info.peer_id
print(f"[INFO] Target Peer ID: {target_peer_id}")
print("[INFO] Connecting to peer...")
await host.connect(info)
print("[INFO] Connection established!")
# Try protocols in order of preference
# Start with the standard libp2p ping protocol
protocols_to_try = [
PING_PROTOCOL_ID, # /ipfs/ping/1.0.0 - standard protocol
TProtocol("/ping/1.0.0"), # Alternative
TProtocol("/libp2p/ping/1.0.0"), # Another alternative
]
stream = None
for proto in protocols_to_try:
try:
print(f"[INFO] Trying to open stream with protocol: {proto}")
stream = await host.new_stream(target_peer_id, [proto])
print(f"[INFO] Stream opened with protocol: {proto}")
break
except Exception as e:
print(f"[ERROR] Failed to open stream with {proto}: {e}")
logging.debug(f"Protocol {proto} failed: {e}")
continue
if not stream:
print("[ERROR] Failed to open stream with any ping protocol")
print("[ERROR] Ensure the target peer supports one of these protocols:")
for proto in protocols_to_try:
print(f"[ERROR] - {proto}")
return 1
await send_ping_sequence(stream, count)
await stream.close()
print("[INFO] Stream closed successfully")
except Exception as e:
print(f"[ERROR] Client error: {e}")
logging.exception("Client error")
import traceback
traceback.print_exc()
return 1
print("\n[INFO] Client stopped")
return 0
def main() -> None:
"""Main function with argument parsing."""
description = """
py-libp2p ping tool for interoperability testing with js-libp2p.
Uses Noise encryption and Yamux multiplexing for compatibility.
Server mode: Listens for ping requests from js-libp2p or py-libp2p clients.
Client mode: Sends ping requests to js-libp2p or py-libp2p servers.
The tool implements the standard libp2p ping protocol (/ipfs/ping/1.0.0)
which exchanges 32-byte random payloads and measures round-trip time.
"""
example_maddr = (
"/ip4/127.0.0.1/tcp/8000/p2p/QmQn4SwGkDZKkUEpBRBvTmheQycxAHJUNmVEnjA2v1qe8Q"
)
parser = argparse.ArgumentParser(
description=description,
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=f"""
Examples:
python ping.py server # Start server on port 8000
python ping.py server --port 9000 # Start server on port 9000
python ping.py client {example_maddr}
python ping.py client {example_maddr} --count 10
Protocols supported:
- /ipfs/ping/1.0.0 (primary, rust-libp2p default)
- /ping/1.0.0 (alternative)
- /libp2p/ping/1.0.0 (alternative)
""",
)
subparsers = parser.add_subparsers(dest="mode", help="Operation mode")
server_parser = subparsers.add_parser("server", help="Run as ping server")
server_parser.add_argument(
"--port", "-p", type=int, default=8000, help="Port to listen on (default: 8000)"
)
client_parser = subparsers.add_parser("client", help="Run as ping client")
client_parser.add_argument("destination", help="Target peer multiaddr")
client_parser.add_argument(
"--count",
"-c",
type=int,
default=5,
help="Number of pings to send (default: 5)",
)
args = parser.parse_args()
if not args.mode:
parser.print_help()
return 1
try:
if args.mode == "server":
trio.run(run_server, args.port)
elif args.mode == "client":
return trio.run(run_client, args.destination, args.count)
except KeyboardInterrupt:
print("\n[INFO] Goodbye!")
return 0
except Exception as e:
print(f"[ERROR] Fatal error: {e}")
logging.exception("Fatal error")
import traceback
traceback.print_exc()
return 1
return 0
if __name__ == "__main__":
exit(main()) Javascript Ping.js #!/usr/bin/env node
process.env.DEBUG = 'libp2p:*,@libp2p:ping,@chainsafe:yamux'
import { createLibp2p } from 'libp2p'
import { tcp } from '@libp2p/tcp'
import { noise } from '@chainsafe/libp2p-noise'
import { yamux } from '@chainsafe/libp2p-yamux'
import { ping } from '@libp2p/ping'
import { identify } from '@libp2p/identify'
import { multiaddr } from '@multiformats/multiaddr'
import { logger } from '@libp2p/logger'
import { pipe } from 'it-pipe'
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
const log = logger('libp2p')
// Use a custom protocol to avoid conflict with built-in ping
const CUSTOM_PING_PROTOCOL = '/custom/ping/1.0.0'
const PING_LENGTH = 32
async function createNode() {
const node = await createLibp2p({
addresses: {
listen: ['/ip4/0.0.0.0/tcp/0']
},
transports: [
tcp()
],
connectionEncrypters: [
noise()
],
streamMuxers: [
yamux()
],
services: {
ping: ping({
protocolPrefix: 'ipfs',
maxInboundStreams: 32,
maxOutboundStreams: 64,
timeout: 800000
}),
//identify: identify()
},
connectionManager: {
minConnections: 0,
maxConnections: 100,
dialTimeout: 30000
}
})
return node
}
// Manual ping implementation for better control
async function sendManualPing(stream, payload) {
const writer = stream.sink
const reader = stream.source
// Send the ping payload
await pipe([payload], writer)
// Read the response
const response = await pipe(reader, async function (source) {
for await (const chunk of source) {
return chunk.subarray(0, PING_LENGTH)
}
})
return response
}
async function runServer() {
console.log('🚀 Starting js-libp2p ping server...')
const node = await createNode()
// Set up custom ping handler (using different protocol to avoid conflict)
await node.handle(CUSTOM_PING_PROTOCOL, ({ stream }) => {
console.log('📥 Received custom ping stream')
pipe(
stream.source,
async function* (source) {
for await (const data of source) {
console.log(`🏓 Received ping data: ${data.length} bytes`)
// Echo back the same data
yield data
}
},
stream.sink
).catch(err => {
console.error('❌ Ping handler error:', err)
})
})
await node.start()
console.log('✅ Server started!')
console.log(`📋 Peer ID: ${node.peerId.toString()}`)
console.log('📍 Listening addresses:')
node.getMultiaddrs().forEach(addr => {
console.log(` ${addr.toString()}`)
})
// Listen for connections
node.addEventListener('peer:connect', (evt) => {
console.log(`🔗 Peer connected: ${evt.detail.toString()}`)
})
node.addEventListener('peer:disconnect', (evt) => {
console.log(`❌ Peer disconnected: ${evt.detail.toString()}`)
})
console.log('\n🎧 Server ready for ping requests...')
console.log(' - Built-in ping available at: /ipfs/ping/1.0.0')
console.log(' - Custom ping available at: /custom/ping/1.0.0')
console.log('Press Ctrl+C to exit')
// Graceful shutdown
process.on('SIGINT', async () => {
console.log('\n🛑 Shutting down...')
await node.stop()
process.exit(0)
})
// Keep alive
while (true) {
await new Promise(resolve => setTimeout(resolve, 1000))
}
}
async function runClient(targetAddr, count = 5) {
console.log('🚀 Starting js-libp2p ping client...')
const node = await createNode()
await node.start()
console.log(`📋 Our Peer ID: ${node.peerId.toString()}`)
console.log(`🎯 Target: ${targetAddr}`)
try {
const ma = multiaddr(targetAddr)
const targetPeerId = ma.getPeerId()
if (!targetPeerId) {
throw new Error('Could not extract peer ID from multiaddr')
}
console.log(`🎯 Target Peer ID: ${targetPeerId}`)
console.log('🔗 Connecting to peer...')
const connection = await node.dial(ma)
console.log('✅ Connection established!')
console.log(`🔗 Connected to: ${connection.remotePeer.toString()}`)
// Wait for connection to stabilize
await new Promise(resolve => setTimeout(resolve, 1000))
const rtts = []
for (let i = 1; i <= count; i++) {
try {
console.log(`\n🏓 Sending ping ${i}/${count}...`)
const start = Date.now()
// Try built-in ping service first
try {
const latency = await node.services.ping.ping(connection.remotePeer)
const rtt = Date.now() - start
rtts.push(latency)
console.log(`✅ Ping ${i} successful (built-in)!`)
console.log(` Reported latency: ${latency}ms`)
console.log(` Measured RTT: ${rtt}ms`)
} catch (builtinError) {
console.log(`⚠️ Built-in ping failed, trying custom ping...`)
// Fallback to custom ping implementation
try {
// Generate random 32-byte payload
const payload = new Uint8Array(PING_LENGTH)
crypto.getRandomValues(payload)
const customStart = Date.now()
const stream = await connection.newStream(CUSTOM_PING_PROTOCOL)
const response = await sendManualPing(stream, payload)
const rtt = Date.now() - customStart
if (response && response.length >= PING_LENGTH) {
// Check if response matches payload
let matches = true
for (let j = 0; j < PING_LENGTH; j++) {
if (payload[j] !== response[j]) {
matches = false
break
}
}
if (matches) {
rtts.push(rtt)
console.log(`✅ Ping ${i} successful (custom)!`)
console.log(` RTT: ${rtt}ms`)
} else {
console.log(`❌ Ping ${i} failed: response mismatch`)
}
} else {
console.log(`❌ Ping ${i} failed: invalid response length`)
}
await stream.close()
} catch (customError) {
console.log(`❌ Custom ping also failed: ${customError.message}`)
}
}
if (i < count) {
await new Promise(resolve => setTimeout(resolve, 1000))
}
} catch (error) {
console.error(`❌ Ping ${i} failed:`, error.message)
}
}
// Stats
if (rtts.length > 0) {
const avg = rtts.reduce((a, b) => a + b, 0) / rtts.length
const min = Math.min(...rtts)
const max = Math.max(...rtts)
console.log(`\n📊 Ping Statistics:`)
console.log(` Packets: Sent=${count}, Received=${rtts.length}, Lost=${count - rtts.length}`)
console.log(` Latency: min=${min}ms, avg=${avg.toFixed(2)}ms, max=${max}ms`)
} else {
console.log(`\n📊 All pings failed (${count} attempts)`)
}
} catch (error) {
console.error('❌ Client error:', error.message)
console.error('Stack:', error.stack)
process.exit(1)
} finally {
await node.stop()
console.log('\n⏹️ Client stopped')
}
}
async function main() {
const args = process.argv.slice(2)
if (args.length === 0) {
console.log('Usage:')
console.log(' node ping.js server # Start ping server')
console.log(' node ping.js client <multiaddr> [count] # Ping a peer')
console.log('')
console.log('Examples:')
console.log(' node ping.js server')
console.log(' node ping.js client /ip4/127.0.0.1/tcp/8000/p2p/12D3Ko... 5')
process.exit(1)
}
const mode = args[0]
if (mode === 'server') {
await runServer()
} else if (mode === 'client') {
if (args.length < 2) {
console.error('❌ Client mode requires target multiaddr')
process.exit(1)
}
const targetAddr = args[1]
const count = parseInt(args[2]) || 5
await runClient(targetAddr, count)
} else {
console.error('❌ Invalid mode. Use "server" or "client"')
process.exit(1)
}
}
main().catch(console.error) Javascript Log
Python Log
Great job @acul71 🎉 |
Beta Was this translation helpful? Give feedback.
-
Ping javascript-python working in both directions (With tcp, noice, mplex | yamux ) "js-v2.x x python-v0.2.9 (tcp, noise, mplex)",success
"js-v2.x x python-v0.2.9 (tcp, noise, yamux)",success
"js-v1.x x python-v0.2.9 (tcp, noise, yamux)",success
"js-v1.x x python-v0.2.9 (tcp, noise, mplex)",success
"python-v0.2.9 x js-v1.x (tcp, noise, mplex)",success
"python-v0.2.9 x js-v2.x (tcp, noise, yamux)",success
"python-v0.2.9 x js-v2.x (tcp, noise, mplex)",success
"python-v0.2.9 x js-v1.x (tcp, noise, yamux)",success look here: libp2p/test-plans#674 |
Beta Was this translation helpful? Give feedback.
-
@dhuseby @seetadev @Nkovaturient |
Beta Was this translation helpful? Give feedback.
-
@acul71 : Great work, Luca. Appreciate your efforts and initiative. Wish to ask the status of interop between py-libp2p and rust-libp2p. Once the requisite test case passes, we should be ready to submit at the test plans repo. On the same note, please let me know if any help is needed on that front. Will connect with Elena and Joao from rust-libp2p. CCing @pacrob |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
🔄 Py ↔ JS libp2p Interoperability:
/ipfs/ping/1.0.0
The goal of this project is to establish interoperability between
py-libp2p
andjs-libp2p
, with a focus on the core/ipfs/ping/1.0.0
protocol.It enables testing, validation, and cross-implementation compatibility between Python and JavaScript libp2p stacks.
🎯 Objective
Ensure that a
py-libp2p
node can connect to and exchange pings with ajs-libp2p
node using:/ipfs/ping/1.0.0
protocol🛠️ Tech Stack
py-libp2p
js-libp2p
/ipfs/ping/1.0.0
✅ Phase 0: Setup & Basic Ping
JS (Listener)
js-libp2p
node with/ipfs/ping/1.0.0
handlerPython (Dialer)
py-libp2p
node/ipfs/ping/1.0.0
and send a 32-byte payload🔍 Phase 1: Interop Validation
Tests
Logs
📦 Directory Structure
🧪 Sample Multiaddr Flow
📊 Success Criteria
/ipfs/ping/1.0.0
opens🚀 Future Roadmap
Following successful ping interop:
/libp2p/identify/1.0.0
testBeta Was this translation helpful? Give feedback.
All reactions