Skip to content

P2P 网络

目录

  1. 网络概述
  2. 节点类型
  3. 节点发现
  4. 连接建立
  5. 消息协议
  6. 交易传播
  7. 区块传播
  8. 常见问题

网络概述

P2P 网络的作用

比特币是完全去中心化的网络:

1. 没有中央服务器
2. 所有节点地位相等
3. 每个节点可独立验证交易和区块
4. 通过 P2P 协议通信

网络的关键功能:

1. 交易传播
   交易从一个节点传播到全网
   最终被矿工打包

2. 区块传播
   新区块从矿工传播到全网
   所有节点更新区块链

3. 同步
   新节点可从网络获取完整区块链

4. 共识
   所有节点验证相同规则
   达成一致的账本状态

网络参数

比特币主网参数:

默认端口:8333
测试网端口:18333
Signet 端口:38333

节点类型:
  全节点:约 50-100 GB 磁盘
  轻客户端:几 MB 磁盘(SPV)
  矿工节点:矿池连接

活跃节点数:
  约 10,000-15,000 个可公开发现的节点
  实际节点更多(很多是私有的)

节点类型

全节点(Full Node)

特点:
  1. 下载完整区块链(约 600GB 截止 2024)
  2. 验证所有交易和区块
  3. 维护 UTXO 集合
  4. 接受其他节点的连接

优点:
  最大隐私
  完全独立验证
  可以广播交易而不依赖第三方

缺点:
  高资源要求
  同步时间长(首次运行)
  需要大量存储

轻客户端(Light Client/SPV)

特点:
  只下载区块头
  使用 Merkle 路径验证交易
  依赖全节点

优点:
  低资源要求
  快速同步
  适合移动设备

缺点:
  隐私性较低
  依赖网络上的全节点
  某些攻击下容易受骗

矿池节点(Pool Node)

特点:
  连接到矿池
  接收工作分配
  提交工作证明

工作流程:
  1. 矿工连接矿池
  2. 获取区块模板
  3. 进行 PoW 计算
  4. 提交满足难度要求的区块头
  5. 矿池验证并奖励

节点发现

DNS Seeds(DNS 种子)

比特币内置的 DNS 种子:

作用:
  初始节点获取已知的对等节点地址

工作流程:
  1. 新节点启动
  2. 查询 DNS seed(如 seed.bitcoin.sipa.be)
  3. DNS 返回已知节点地址列表
  4. 新节点连接这些地址

优点:
  快速启动
  无需手动配置

缺点:
  依赖 DNS
  DNS 可能被污染

Addr Relay(地址中继)

机制:
  节点互相分享他们知道的其他节点地址

过程:
  1. 节点 A 连接节点 B
  2. B 发送 ADDR 消息(包含其他已知节点)
  3. A 接收并缓存这些地址
  4. A 可连接到这些新地址

优点:
  去中心化发现
  不依赖 DNS
  自我强化

连接建立

TCP 连接

比特币使用 TCP/IP:

默认设置:
  监听端口:8333
  允许入站连接:是
  最大连接数:125(默认)

连接过程:
  1. TCP 三次握手
  2. 交换版本信息
  3. 建立双向通信

地址支持:
  IPv4:192.168.1.1:8333
  IPv6:[::1]:8333
  Onion:.onion 地址(Tor)

版本握手

Version 消息交换:

字段:
  version:协议版本(70015 等)
  services:节点提供的服务(0x01 = NODE_NETWORK)
  timestamp:当前时间
  receiver:对方地址
  sender:本方地址
  nonce:随机数
  user_agent:客户端标识
  start_height:节点已同步到的区块高度

验证:
  1. 版本号兼容
  2. 检测自连(nonce 匹配)
  3. 网络参数一致

消息协议

消息格式

每条消息有固定头部:

┌─────────────────────────────────────┐
│ Magic Bytes (4 字节)                │
│ 0x0709110B (主网)                  │
├─────────────────────────────────────┤
│ Command (12 字节)                   │
│ "tx", "block", "addr" 等            │
├─────────────────────────────────────┤
│ Length (4 字节)                     │
│ 消息体大小                          │
├─────────────────────────────────────┤
│ Checksum (4 字节)                   │
│ SHA256(SHA256(body)) 前 4 字节      │
├─────────────────────────────────────┤
│ Payload (可变长度)                  │
│ 实际消息数据                        │
└─────────────────────────────────────┘

常见消息类型

inv (inventory):
  告诉对方有哪些新交易/区块
  接收方可请求完整数据

getdata:
  请求完整的交易或区块

tx:
  传输完整交易

block:
  传输完整区块

ping/pong:
  心跳,检测连接是否活跃

addr:
  分享已知节点地址

mempool:
  请求对方内存池中的交易 ID

feefilter:
  告诉对方最小费率要求

交易传播

交易传播流程

1. 用户/应用提交交易到本地节点

2. 本地节点验证
   ✓ 签名有效
   ✓ UTXO 存在且未被花费
   ✓ 费用足够
   → 添加到 mempool

3. 发送 INV 消息
   向连接的所有对等节点广播:
   "我有新交易 TXID:abc123..."

4. 对等节点应答
   发送 GETDATA 请求:
   "请给我完整交易"

5. 发送完整交易
   本地节点发送 tx 消息
   包含完整序列化交易

6. 重复
   对等节点重复步骤 2-5
   最终交易传播到全网

传播延迟:
  通常 < 1-2 秒
  距离越远延迟越大

内存池管理

内存池(mempool):
  节点临时存储未确认的交易

大小限制:
  默认:300 MB
  可配置

驱逐策略(mempool 满时):
  最低费率的交易被驱逐
  或使用年龄作为因素

交易生命周期:
  1. 进入内存池(未确认)
  2. 被打包到区块(1 确认)
  3. 从内存池移除

区块传播

区块传播流程

1. 矿工生成新区块
   
2. 广播 INV 消息
   "我有新区块 BLOCKID:xyz789..."

3. 对等节点请求
   发送 GETDATA

4. 接收完整区块
   接收 block 消息

5. 验证区块
   ✓ PoW 有效
   ✓ 所有交易有效
   ✓ 符合共识规则
   → 添加到本地链

6. 转播
   向其他对等节点转播

传播延迟:
  通常 < 5 秒
  全网同步:< 30 秒

区块压缩(BIP 152)

紧凑区块格式:

优点:
  减少传输数据量(约 80% 减少)
  加快同步速度

方式:
  发送区块头 + 交易 ID 列表
  对等节点从内存池重建大部分交易
  缺失的交易再单独请求

流程:
  1. 发送紧凑区块
  2. 接收方从 mempool 匹配
  3. 请求缺失的交易(通常很少)
  4. 完整区块组装

常见问题

Q1: 为什么需要多个节点连接?

A:

  1. 冗余性:一个节点离线不影响网络
  2. 隐私性:多节点查询增加隐私
  3. 快速同步:可从多个源获取数据

Q2: 节点可以拒绝其他节点连接吗?

A:

  • 可以基于 IP 黑名单
  • 但比特币鼓励连接接受
  • 限制连接违反 P2P 精神

Q3: 如何防止 P2P 网络攻击?

A:

  1. Sybil 攻击:靠 PoW 共识防护
  2. DDoS 攻击:有速率限制和 IP 黑名单
  3. 身份攻击:比特币不依赖身份

Q4: Tor 支持是否降低隐私?

A:

  • Tor 支持提高隐私
  • 允许隐藏 IP 地址
  • 比特币核心支持 Tor 节点

Q5: 为什么有节点不转播交易?

A:

  1. 可能已禁用 relay 功能
  2. mempool 已满,费率过低
  3. 系统资源限制