第10讲 P2P 网络协议
Lesson 10: P2P Network Protocol
💡 The Bitcoin peer-to-peer(P2P) network is the core of decentralization, enabling nodes around the world to work together without a central server. This chapter will explain in the most intuitive way how this "centralized network" operates.
Recommended exchange for buying BTC / ETH / USDT: Binance Registration Link
Table of Contents
Introduction: Why Can't Bitcoin Work Like WeChat?
Imagine what would happen if WeChat had no Tencent servers.
WeChat's reality:
- You send a message → Tencent servers → Your friend receives it.
- If Tencent servers go down → WeChat stops working worldwide.
- If the government shuts down Tencent → WeChat disappears entirely.
But Bitcoin achieved the impossible:
- With 13,000 nodes globally, there's no headquarters and no CEO.
- Processes transactions 24/7 without any downtime.
- No government can shut down the entire network.
How was this "impossible" feat accomplished? The answer lies in the P2P (peer-to-peer) network protocol.
💡 Think About It
Before learning about P2P networks, consider this:
- If you live in a village with no chief, how would you let everyone know about something?
- Without a post office, how would you send letters to distant friends?
- Without a telephone company, how would everyone stay in touch?
P2P Network: Like a Village Message Game
Centralized vs. Decentralized
Centralized network (WeChat model):
User A → Tencent Server ← User B
↑
Single point of failure
It's like a village where only the chief handles messages — if the chief gets sick, the entire village can't communicate.
P2P network (Bitcoin model):
Node A ↔ Node B ↔ Node C
↕ ↕ ↕
Node D ↔ Node E ↔ Node F
No chief needed to pass messages
Just like villagers communicating directly, even if several leave, everyone else continues talking.
The Network's Magical Properties
The Bitcoin P2P network is like an ideal village:
- 🏘️ Equality: Every villager is equal. There's no "chief."
- 🔄 Fault tolerance: Any villager leaving doesn't affect the whole village.
- 🚫 Censorship resistance: No central point can be shut down.
- 🤝 Self-organization: Villagers automatically maintain and optimize relationships.
Connection strategy (Social Rules for Villagers):
- Each villager proactively contacts 8 friends (outbound connections).
- Accepts up to 125 friend requests (inbound connections).
- Opens the door on port 8333 by default.
Node Discovery: How Newcomers Join the Village
A new node joining the network faces a "chicken-and-egg" problem: you need to know the addresses of other nodes to connect, but how do you get your first friend's contact info?
Step 1: Check the Phone Directory (DNS Seeds)
Bitcoin provides new villagers with 9 "phone directories":
🔍 DNS seed discovery process:
- Query the directory: The new node requests active node lists from 9 DNS servers.
- Get contact info: Each directory returns 5-20 reliable friends' IP addresses.
- Attempt to connect: The new node contacts these addresses to establish its first batch of connection.
📞 Bitcoin's 9 "phone directories":
seed.bitcoin.sipa.be— Pieter's authoritative directory.dnsseed.bluematt.me— Matt's community directory.seed.bitcoinstats.com— Statistics website's directory.- (Plus 6 more distributed worldwide as backups)
Phone directory advantages:
- 🏢 Independently maintained: 9 different people maintain them, hence they won't all fail at once.
- 🔄 Auto-updated: Only returns the addresses of the most recently active nodes.
- 🌍 Globally distributed: Spread across different countries for fault tolerance.
Step 2: Friends Introduce Friends (Address Propagation)
Once connected to your first friend, finding more becomes easy:
New villager → Connects to Villager A → "Hey, who else do you know?"
Villager A → "I know Villagers B, C, D — here are their contact details"
New villager → Connects to Villager B → "Do you know anyone else?"
Villager B → "I know Villagers E, F, G..."
Like a snowball effect — your social circle grows larger and larger!
Step 3: Build an Address Book (Persistent Storage)
Smart villagers record their friends' contact info in a notebook:
pythonclass BitcoinAddressBook: def __init__(self): self.trusted_friends = [] # Verified reliable friends self.potential_friends = [] # Heard about but haven't contacted yet def save_friend(self, friend_address): """Save a friend's contact info""" if self.test_connection(friend_address): self.trusted_friends.append(friend_address) print(f"✅ {friend_address} is a reliable friend, saved") else: self.potential_friends.append(friend_address) print(f"📝 {friend_address} noted, will contact later") def load_address_book(self): """On next startup, look up old friends from the address book""" print("📖 Opening address book, looking for old friends...") return self.trusted_friends
Connection Management: Keeping the Village Harmonious
The Wisdom of Making Friends
A Bitcoin node is like a socially adept villager with a complete "friendship strategy":
Active friending (8 outbound connections):
- Proactively finds and contacts 8 friends.
- Prioritizes contacting reliable friends from the address book.
- If old friends are unreachable, seeks new ones.
Passive friending (125 inbound connections):
- Accepts contact requests from other villagers.
- But can't accept everyone, we must guard against malicious harassment.
- Maintains a reasonable social circle.
Friend Circle Diversity
A smart villager won't only befriend neighbors:
pythondef choose_diverse_friends(potential_friends): """Choose a diverse friend circle""" selected_friends = [] # Geographic diversity: don't pick friends all from the same neighborhood regions = {} for friend in potential_friends: region = get_network_region(friend) if region not in regions: regions[region] = [] regions[region].append(friend) # Select at most 2 friends from each region for region, friends in regions.items(): selected_friends.extend(friends[:2]) print(f"Selected {min(2, len(friends))} friends from {region}") return selected_friends[:8] # 8 friends total
Benefits of diversity:
- 🌍 Geographic distribution: Avoid having friends from the same region.
- 🔄 Version compatibility: Include friends running both old and new versions.
- ⏰ Time distribution: Include friends who are online at different times.
Health Checks: Keeping Friendships Fresh
Villagers regularly greet each other to ensure friendships endure:
pythondef keep_friendship_alive(): """Regularly greet friends to stay connected""" for friend in my_friends: # Send a "hello" every 90 seconds send_ping(friend, "Hey, are you still there?") # Wait for reply response = wait_for_pong(friend, timeout=30) if response: print(f"✅ {friend} replied: All good!") update_friend_status(friend, "online") else: print(f"❌ {friend} didn't reply, may be offline") find_new_friend_to_replace(friend)
Message Propagation: How News Spreads Across the Village
Village Broadcasting System
The Bitcoin network is like an efficient village broadcasting system, but without a broadcasting station:
Traditional broadcasting:
Villager A → Broadcasting station → Whole village listens
↑
Single point of failure
Bitcoin-style propagation:
Villager A → Tells friends → Friends tell their friends → News spreads village-wide
Smart Propagation Strategy
To prevent the "telephone game" from becoming chaotic, Bitcoin uses clever propagation mechanisms:
pythondef spread_news_efficiently(news): """Efficient news propagation method""" # Step 1: Create a news summary news_summary = create_summary(news) # "I have important news" # Step 2: Send the summary to friends first for friend in my_friends: send_message(friend, { "type": "I have news", "summary": news_summary, "full_news": None # Don't send full news yet }) # Step 3: Friends ask "What news?" def handle_friend_request(friend, request): if request.type == "Tell me more": send_message(friend, { "type": "Full news", "content": news # Now send the full news }) # Step 4: After receiving it, friends continue propagating to their friends print("📢 News begins spreading through the village...")
Why this design?
- 💾 Saves bandwidth: Send a summary first; those who need it request details.
- 🚫 Avoids duplication: Everyone remembers news they've heard and doesn't re-propagate.
- ⚡ Fast propagation: Reaches 95% of the network in an average of 12 seconds.
Message Format: The Village's "Common Language"
All villagers use a unified message format:
pythondef create_bitcoin_message(message_type, content): """Create a standard Bitcoin message""" # The village's "dialect identifier" magic_word = b'\xf9\xbe\xb4\xd9' # Mainnet magic number # Message type (max 12 characters) command = message_type.ljust(12, b'\x00')[:12] # Message length length = len(content) # Message "signature" (prevents message distortion) signature = hashlib.sha256(hashlib.sha256(content).digest()).digest()[:4] # Assemble the full message full_message = magic_word + command + length.to_bytes(4, 'little') + signature + content return full_message # Example: Create a "greeting" message greeting = create_bitcoin_message(b'version', b'Hello, Bitcoin network!') print(f"Message length: {len(greeting)} bytes")
Security Upgrade: Encrypting the Messages
Risks of transmitting messages in plain text
Previously, villagers communicated in plaintext, like shouting:
Villager A shouts: "I want to transfer 1 bitcoin to Villager B!"
Eavesdropper snickers: "Heh, now I know A's financial situation..."
What's the problem?
- 🕵️ Privacy leak: Others can hear all your conversations.
- 🎭 Identity exposure: Easy to track and analyze.
- 🔍 Traffic analysis: Governments could monitor network traffic.
BIP 324: Encrypting the Messages
In 2024, the Bitcoin network began using "encrypted communication":
pythonclass SecretTalk: def __init__(self): self.my_secret_key = generate_random_key() # My key self.friend_public_key = None # Friend's public key self.shared_secret = None # Shared secret def establish_secret_channel(self, friend): """Establish an encrypted channel with a friend""" # Step 1: Exchange public keys (like exchanging secret codes) my_public_key = derive_public_key(self.my_secret_key) send_to_friend(friend, my_public_key) self.friend_public_key = receive_from_friend(friend) # Step 2: Generate shared secret (mathematical magic) self.shared_secret = calculate_shared_secret( self.my_secret_key, self.friend_public_key ) print("✅ Encrypted channel established! You can whisper now") def send_secret_message(self, friend, message): """Send an encrypted message""" # Encrypt the message with the shared secret encrypted_message = encrypt_with_secret(message, self.shared_secret) send_to_friend(friend, encrypted_message) print(f"🔐 Sent encrypted message to {friend}") def receive_secret_message(self, encrypted_message): """Receive an encrypted message""" # Decrypt the message with the shared secret original_message = decrypt_with_secret(encrypted_message, self.shared_secret) print(f"📨 Decrypted message received: {original_message}") return original_message
Benefits of encryption:
- 🛡️ Privacy protection: Outsiders can't eavesdrop on conversations.
- 🔒 Tamper-proof: Message modifications are detected.
- 🔑 Forward secrecy: Even if keys are compromised, past conversations remain safe.
- 🔄 Backward compatiblity: You can still communicate with friends who use the old method.
Hands-on Practice: Connecting to the Bitcoin Network
Preparation: Install Bitcoin Client
bash# Download and install Bitcoin Core # Visit https://bitcoin.org/en/download # Or use a package manager (Mac) brew install bitcoin # Or use a package manager (Ubuntu) sudo apt-get install bitcoin
Step 1: Start Your Bitcoin Node
bash# Start a Bitcoin node (testnet) bitcoind -testnet -daemon # Wait a few seconds for the node to start sleep 5 # Check if the node is running properly bitcoin-cli -testnet getnetworkinfo
Step 2: View Your Friend Circle
bash# Check how many friends are connected bitcoin-cli -testnet getconnectioncount # View friends' detailed info bitcoin-cli -testnet getpeerinfo | head -20
You'll see output like:
json{ "id": 1, "addr": "192.168.1.100:18333", "version": 70016, "subver": "/Satoshi:25.0.0/", "inbound": false, "bip152_hb_to": true, "bip324": true }
Step 3: Observe Message Propagation
python#!/usr/bin/env python3 """ Simple Bitcoin network listener Observe P2P message propagation """ import socket import struct import hashlib import time class BitcoinNetworkListener: def __init__(self, host='127.0.0.1', port=18333): self.host = host self.port = port self.socket = None def connect_to_node(self): """Connect to the local Bitcoin node""" try: self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.connect((self.host, self.port)) print(f"✅ Successfully connected to {self.host}:{self.port}") return True except Exception as e: print(f"❌ Connection failed: {e}") return False def send_version_message(self): """Send a version message for the handshake""" # Simplified version; actual implementation is more complex version_payload = struct.pack('<I', 70015) # Protocol version magic = b'\x0b\x11\x09\x07' # Testnet magic number command = b'version'.ljust(12, b'\x00') length = len(version_payload) checksum = hashlib.sha256(hashlib.sha256(version_payload).digest()).digest()[:4] message = magic + command + struct.pack('<I', length) + checksum + version_payload self.socket.send(message) print("📤 Version message sent") def listen_for_messages(self): """Listen for network messages""" print("👂 Listening for P2P messages...") while True: try: data = self.socket.recv(1024) if data: self.parse_message(data) time.sleep(1) except KeyboardInterrupt: print("\n🛑 Stopped listening") break def parse_message(self, data): """Parse received messages""" if len(data) >= 24: # Minimum 24 bytes for message header magic = data[:4] command = data[4:16].rstrip(b'\x00').decode('ascii', errors='ignore') length = struct.unpack('<I', data[16:20])[0] print(f"📨 Received message: {command}, length: {length} bytes") # Usage example if __name__ == "__main__": listener = BitcoinNetworkListener() if listener.connect_to_node(): listener.send_version_message() listener.listen_for_messages()
Step 4: Test Network Connectivity
bash# Create a simple test script cat > test_p2p.py << 'EOF' #!/usr/bin/env python3 import subprocess import json def test_bitcoin_network(): """Test Bitcoin network connectivity""" print("🔍 Testing Bitcoin P2P network connectivity...\n") # Test 1: Check network status print("📊 Network status:") result = subprocess.run(['bitcoin-cli', '-testnet', 'getnetworkinfo'], capture_output=True, text=True) if result.returncode == 0: info = json.loads(result.stdout) print(f"Version: {info['version']}") print(f"Connections: {info['connections']}") print(f"Network: {info['networkactive']}") print(f"Protocol version: {info['protocolversion']}") # Test 2: Check peers print("\n👥 Peer info:") result = subprocess.run(['bitcoin-cli', '-testnet', 'getpeerinfo'], capture_output=True, text=True) if result.returncode == 0: peers = json.loads(result.stdout) for i, peer in enumerate(peers[:3]): # Show only the first 3 print(f"Node {i+1}: {peer['addr']} (version: {peer['version']})") # Test 3: Check blockchain sync status print("\n⛓️ Blockchain sync status:") result = subprocess.run(['bitcoin-cli', '-testnet', 'getblockchaininfo'], capture_output=True, text=True) if result.returncode == 0: info = json.loads(result.stdout) print(f"Current block: {info['blocks']}") print(f"Verification progress: {info['verificationprogress']:.2%}") if __name__ == "__main__": test_bitcoin_network() EOF # Run the test python3 test_p2p.py
FAQ
❓ Why did Bitcoin choose P2P instead of a more efficient architecture?
Answer: It's like asking "why democracy instead of dictatorship?" P2P may not be the most efficient, but it provides invaluable properties:
- 🏛️ Decentralization: No single point of failure; no one can shut down the entire network.
- 🛡️ Censorship resistance: No government or organization can take control.
- 🌍 Global accessibility: Anyone can participate, no permission required.
- 💪 Robustness: The network keeps running even if most nodes go offline.
Efficiency can be improved through technical optimization, but once decentralization is lost, it's very hard to recover.
❓ Can DNS seeds become a single point of failure?
Answer: No! DNS seeds are just "beginner's guides," not essential:
Multiple safeguards:
- 9 independent DNS seed servers distributed globally.
- Even if 8 fail, 1 is enough.
- Existing nodes have their own "address books" and don't depend on DNS seeds.
- Nodes share friends' contact information with each other.
In practice:
- DNS seeds are only used on first startup.
- A running network doesn't depend on DNS seeds at all.
- Even if all DNS seeds disappear, the existing network continues operating normally.
❓ Why limit the number of connections? Why isn't more always better?
Answer: Just like your social circle — more isn't always better:
Too few connections:
- Easy to be isolated (eclipse attack).
- Slow message propagation.
- Network can easily split.
Too many connections:
- Consumes large amounts of bandwidth.
- Heavy computational burden processing messages.
- Susceptible to flood attacks.
The magic number 8 + 125:
- 8 outbound connections: Ensures network connectivity.
- 125 inbound connections: Serves other nodes.
- An optimal balance point that has been verified through years of practice.
❓ Will BIP 324 encryption slow down the network?
Answer: Almost not at all! Modern encryption algorithms are very efficient:
Performance comparison:
ChaCha20 encryption speed: ~1 GB/s (modern CPU)
Bitcoin network bandwidth: ~1 MB/s (typical node)
Encryption overhead: < 1% CPU usage
Practical benefits:
- 🔐 Privacy protection: Outsiders can't snoop on your transactions.
- 🛡️ Security improvement: Prevents man-in-the-middle attacks.
- 📊 Traffic obfuscation: Makes traffic analysis difficult.
- 🚀 Future extensibility: Lays the groundwork for more features.
The minimal performance overhead combined with a huge security boost is absolutely worthwhile!
❓ Do regular users need to run a full node?
Answer: It's not required, but strongly recommended for those who have the necessary resources:
Light nodes (SPV) are suitable for:
- Mobile wallet users.
- Occasional Bitcoin users.
- Users with limited network access.
Full nodes are suitable for:
- Frequent Bitcoin users.
- Users who care about network security and decentralization.
- Users with stable network and storage space.
Benefits of running a full node:
- 🔒 Highest security: Verify all transactions yourself.
- 🌐 Support the network: Serve other users.
- 🗳️ Participate in governance: Have a voice in protocol upgrades.
- 📊 Complete data: Query any historical data.
❓ How to detect and prevent cyberattacks?
Answer: The Bitcoin network has multiple layers of defense:
Common attack types:
- 🌑 Eclipse attack: Malicious nodes surround you, blocking the real network.
- 👥 Sybil attack: Attacker creates many fake identities.
- 🌊 Flood attack: Sending massive amounts of spam messages to clog the network.
Defense strategies:
pythondef detect_potential_attacks(): """Detect potential network attacks""" # Detect eclipse attacks peer_diversity = check_peer_diversity() if peer_diversity < 0.5: print("⚠️ Warning: Connections lack diversity, possible eclipse attack") # Detect abnormal traffic message_rate = get_message_rate() if message_rate > NORMAL_THRESHOLD * 10: print("⚠️ Warning: Abnormal message rate, possible flood attack") # Detect version concentration version_distribution = get_version_distribution() if max(version_distribution.values()) > 0.8: print("⚠️ Warning: Connected node versions are too concentrated") # Automatic defense measures def auto_defense(): """Automatic defense mechanisms""" # Diversify connections ensure_geographic_diversity() ensure_version_diversity() # Implement rate limiting implement_rate_limiting() # Monitor abnormal behavior monitor_peer_behavior()
Summary
The Bitcoin P2P network is a carefully designed distributed system, like an ideal village with no chief:
🏛️ Design Philosophy
- Decentralization first: Willing to sacrifice efficiency to ensure decentralization.
- Mathematical proof: Using cryptography to replace trust in authority.
- Adaptability: The network automatically adapts to environmental changes.
🔧 Technical Features
- Multiple discovery: DNS seeds + hardcoded nodes + peer-to-peer propagation.
- Smart connections: A balanced strategy of 8 outbound + 125 inbound connections.
- Efficient propagation: Flood-based broadcasting + deduplication mechanism.
- Privacy upgrade: BIP 324 provides end-to-end encryption.
🌟 Practical Value
- Understanding the network layer of blockchain.
- Providing design references for other P2P applications.
- Mastering core distributed systems technology.
The Bitcoin P2P network proves that without centralized authority, we can still build a secure, reliable, global network system. Everyone running a Bitcoin node is a guardian of this decentralized financial network.
🔗 Full code implementation: p2p_examples.py
📚 Dive deep: Complete technical documentation
Challenge Quiz
Complete 5 questions, you need to get all correct to unlock the next chapter
If this lesson was helpful, please consider supporting the author ☕
Support Author · Buy Me a Coffee