Перейти к содержанию
Learning Platform
Средний
20 минут
P2P Peer Discovery Block Propagation Mempool INV IBD

Требуемые знания:

  • 06-mining-pow

Сетевой протокол Bitcoin

Зачем это блокчейну?

Когда вы отправляете Bitcoin-транзакцию, ваш узел передаёт её соседям, те — своим соседям, и через секунды тысячи узлов по всему миру знают о ней. Как работает эта P2P-сеть? Как новый узел находит других? Как блок, найденный майнером в Исландии, за секунды оказывается у майнера в Токио?

Bitcoin — это не сервер и не «блокчейн в облаке». Это одноранговая (peer-to-peer) сеть из тысяч независимых узлов, каждый из которых хранит полную копию блокчейна и самостоятельно проверяет все правила.

# Подключитесь к регтест-узлу и посмотрите на пиров:
bitcoin-cli -regtest getpeerinfo
# Каждый пир -- это отдельный узел Bitcoin, с которым ваш узел обменивается данными

Обнаружение узлов (Peer Discovery)

Когда Bitcoin-узел запускается впервые, ему нужно найти других участников сети. Процесс:

1. DNS Seeds

Узел обращается к захардкоженным DNS-seed серверам:

seed.bitcoin.sipa.be
dnsseed.bluematt.me
seed.bitcoinstats.com
seed.btc.petertodd.net
...

DNS-запрос возвращает IP-адреса активных Bitcoin-узлов. Это начальная точка — дальше узел находит пиров самостоятельно.

2. Handshake (рукопожатие)

Новый узел                   Пир
    |--- version ------------>|    "Привет, я Bitcoin Core v30, regtest"
    |<-- version -------------|    "Привет, я Bitcoin Core v29, regtest"
    |--- verack ------------->|    "Подтверждаю"
    |<-- verack --------------|    "Подтверждаю"
    |                         |    Соединение установлено!

3. Обмен адресами (addr)

После подключения узлы обмениваются списками известных пиров через addr-сообщения. Каждый узел поддерживает базу данных адресов и периодически делится ими.

Результат: через несколько минут новый узел подключён к 8—10 исходящим (outbound) и может принимать до 125 входящих (inbound) соединений.

Распространение блоков

Когда майнер находит новый блок, он должен как можно быстрее доставить его всей сети. Задержка распространения = риск orphan-блоков.

Сетевой протокол Bitcoin P2P
Новый узел находит пиров через DNS seeds и addr-сообщения
DNS queryN1Full Node AN2Miner BN3Full Node CN4SPV WalletN5Miner DN6Full Node EN7Full Node FN8DNS Seed
Полный узел
Майнер
SPV-клиент
1 / 5
Шаг 1: DNS querySPV запрашивает DNS seed для получения адресов узлов

Переключайте вкладки, чтобы увидеть три ключевых потока:

  • Обнаружение узлов — как новый узел подключается к сети
  • Распространение блока — inv -> getdata -> block
  • Передача транзакции — inv -> getdata -> tx

Протокол распространения блока

Майнер                       Узел A                       Узел B
  |--- inv (block_hash) ----->|                             |
  |                           |--- inv (block_hash) ------->|
  |<-- getdata (block_hash) --|                             |
  |--- block (full_data) ---->|                             |
  |                           |<-- getdata (block_hash) ----|
  |                           |--- block (full_data) ------>|
  1. inv (inventory): «У меня есть блок с таким хешем»
  2. getdata: «Пришли мне этот блок»
  3. block: полные данные блока

Headers-first (Bitcoin Core 0.10+)

Современный Bitcoin Core использует оптимизацию headers-first:

  1. Сначала скачать заголовки (80 байт каждый) — дёшево
  2. Проверить цепочку заголовков (PoW, timestamp)
  3. Запросить полные блоки параллельно у нескольких пиров

Распространение транзакций

Транзакции распространяются по той же схеме inv -> getdata -> tx:

Кошелёк (SPV)                Full Node                    Майнер
  |--- inv (tx_hash) -------->|                             |
  |<-- getdata (tx_hash) -----|                             |
  |--- tx (full_data) ------->|                             |
  |                           |  Проверяет транзакцию       |
  |                           |  Добавляет в мемпул         |
  |                           |--- inv (tx_hash) ---------->|
  |                           |                             |
  |                           |<-- getdata (tx_hash) -------|
  |                           |--- tx (full_data) --------->|
  |                           |                     Добавляет в мемпул

Каждый узел самостоятельно проверяет транзакцию перед ретрансляцией:

  • Формат корректный?
  • Входы существуют и не потрачены?
  • Подписи валидны?
  • Комиссия достаточна?

Если проверка не пройдена — транзакция отбрасывается и не ретранслируется.

Мемпул (Memory Pool)

Мемпул — это «зал ожидания» для неподтверждённых транзакций. Каждый узел поддерживает свой мемпул.

Как майнеры выбирают транзакции

Майнеры заполняют блок транзакциями из мемпула, приоритизируя по fee rate (комиссия за виртуальный байт):

fee_rate = fee / vbytes (сатоши/вБ)

Транзакции с большей fee rate включаются первыми. При заполненном мемпуле транзакции с низкой fee rate могут ждать часами или быть удалены.

RBF (Replace-by-Fee)

Если транзакция «застряла» в мемпуле (низкая комиссия), отправитель может создать замену с той же входной UTXO, но с более высокой комиссией. Узлы примут замену, если:

  • Оригинал был помечен как replaceable (nSequence < 0xFFFFFFFF-1)
  • Новая комиссия выше старой

CPFP (Child-Pays-for-Parent)

Получатель может «подтолкнуть» застрявшую транзакцию, создав дочернюю транзакцию, которая тратит выход застрявшей, с высокой комиссией. Майнеру выгодно включить обе транзакции — суммарная fee rate выше порога.

# Проверить мемпул на регтесте:
bitcoin-cli -regtest getmempoolinfo
# {
#   "loaded": true,
#   "size": 0,              # количество транзакций
#   "bytes": 0,             # размер в байтах
#   "usage": 64,            # использование памяти
#   "mempoolminfee": 0.00001000
# }

Initial Block Download (IBD)

Новый узел должен скачать и проверить все блоки с Genesis-блока (2009) до текущего. Это называется Initial Block Download.

Процесс

  1. Скачать заголовки — запросить цепочку заголовков у пиров (headers-first)
  2. Проверить заголовки — каждый заголовок: корректный PoW, правильный prev_hash, валидный timestamp
  3. Скачать блоки — параллельно у нескольких пиров (разные диапазоны высот)
  4. Проверить транзакции — каждая транзакция в каждом блоке проверяется полностью
  5. Построить UTXO set — после проверки всех блоков у узла есть актуальный набор неизрасходованных выходов

Время IBD

На 2025 год полная синхронизация занимает от нескольких часов до суток в зависимости от оборудования (CPU для проверки подписей, SSD для UTXO set, пропускная способность). Блокчейн Bitcoin занимает ~600 ГБ.

Формат сообщений

Каждое P2P-сообщение Bitcoin имеет структуру:

[Magic bytes: 4 байта]     Идентификатор сети (mainnet/testnet/regtest)
[Command: 12 байт]         Название команды (version, inv, block, tx, ...)
[Length: 4 байта]           Длина payload
[Checksum: 4 байта]        Первые 4 байта SHA-256d от payload
[Payload: N байт]          Данные сообщения
СетьMagic bytes
Mainnet0xf9beb4d9
Testnet30x0b110907
Regtest0xfabfb5da

Magic bytes позволяют узлу сразу определить, к какой сети принадлежит соединение. Checksum обеспечивает целостность данных.

Современные улучшения

BIP 152: Compact Block Relay

Вместо отправки полного блока (~1-2 МБ) отправляется компактный блок — заголовок + укороченные ID транзакций. Поскольку принимающий узел уже имеет большинство транзакций в мемпуле, он восстанавливает блок локально. Уменьшает время распространения в ~10 раз.

BIP 324: Encrypted P2P (v2 transport)

Начиная с Bitcoin Core 26, P2P-соединения могут быть зашифрованы (Noise Protocol). Это защищает от:

  • Перехвата трафика ISP
  • Определения, какие транзакции отправляет конкретный узел
  • Man-in-the-middle на уровне сети

Алгоритмический уровень

Подключитесь к регтест-узлу и исследуйте сеть:

# Информация о подключённых пирах:
bitcoin-cli -regtest getpeerinfo
# Каждый пир: addr, version, subver, pingtime, bytessent, bytesrecv

# Информация о мемпуле:
bitcoin-cli -regtest getmempoolinfo
# size, bytes, usage, mempoolminfee

# Информация о сети:
bitcoin-cli -regtest getnetworkinfo
# version, subversion, protocolversion, connections

Структура ответа getpeerinfo

[
  {
    "id": 0,
    "addr": "127.0.0.1:18444",
    "addrbind": "127.0.0.1:52348",
    "network": "not_publicly_routable",
    "services": "0000000000000409",
    "version": 70016,
    "subver": "/Satoshi:30.2.0/",
    "inbound": false,
    "bip152_hb_to": true,
    "bytessent": 12345,
    "bytesrecv": 67890,
    "pingtime": 0.001
  }
]

Практика

Запустите регтест-узел и исследуйте P2P-протокол:

# Запустите Docker-контейнер с Bitcoin Core
# docker compose -f labs/bitcoin/docker-compose.yml up -d

# Подключитесь и исследуйте:
bitcoin-cli -regtest getpeerinfo
bitcoin-cli -regtest getmempoolinfo
bitcoin-cli -regtest getnetworkinfo

Что дальше?

Мы изучили, как работает сеть Bitcoin — от обнаружения узлов до распространения блоков и транзакций. В следующих уроках перейдём к Lightning Network — протоколу второго уровня (Layer 2), который позволяет проводить тысячи транзакций в секунду без записи каждой из них в блокчейн.

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс