比特币技术 — 网络与共识层
16 min read

第10讲 P2P 网络协议

Lesson 10: P2P Network Protocol

status author date difficulty

💡 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:

  1. Query the directory: The new node requests active node lists from 9 DNS servers.
  2. Get contact info: Each directory returns 5-20 reliable friends' IP addresses.
  3. 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:

python
python
class 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:

python
python
def 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:

python
python
def 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:

python
python
def 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:

python
python
def 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":

python
python
class 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
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
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
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
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
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
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:

python
python
def 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