# Lesson 10: P2P Network Protocol

![status](https://img.shields.io/badge/Status-Completed-success)
![author](https://img.shields.io/badge/Author-beihaili-blue)
![date](https://img.shields.io/badge/Date-2025--09-orange)
![difficulty](https://img.shields.io/badge/Difficulty-Intermediate-yellow)

> 💡 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](https://www.binance.com/en) [Registration Link](https://www.bsmkweb.cc/register?ref=39797374)

## Table of Contents

- [Introduction: Why Can't Bitcoin Work Like WeChat?](#introduction-why-cant-bitcoin-work-like-wechat)
- [P2P Network: Like a Village Message Game](#p2p-network-like-a-village-message-game)
- [Node Discovery: How Newcomers Join the Village](#node-discovery-how-newcomers-join-the-village)
- [Connection Management: Keeping the Village Harmonious](#connection-management-keeping-the-village-harmonious)
- [Message Propagation: How News Spreads Across the Village](#message-propagation-how-news-spreads-across-the-village)
- [Security Upgrade: Encrypting the Messages](#security-upgrade-encrypting-the-messages)
- [Hands-on Practice: Connecting to the Bitcoin Network](#hands-on-practice-connecting-to-the-bitcoin-network)
- [FAQ](#faq)

## 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
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
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
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
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
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
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
# 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:**
```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](./p2p_examples.py)
>
> 📚 **Dive deep**: [Complete technical documentation](./code_examples/)

---

<div align="center">
<a href="https://github.com/beihaili/Get-Started-with-Web3">🏠 Back to Home</a> |
<a href="https://twitter.com/bhbtc1337">🐦 Follow the Author</a> |
<a href="https://forms.gle/QMBwL6LwZyQew1tX8">📝 Join the Discussion</a>
</div>
