Глоссарий / Протокол и обновления
Компактная ретрансляция блоков
Другие названия: BIP152.
- Что такое Компактная ретрансляция блоков?
- Компактная ретрансляция блоков заменяет новый блок в сети списком шестибайтовых идентификаторов, которые принимающий узел сопоставляет с транзакциями, уже имеющимися у него, и собирает блок локально.
Определено в BIP-152.
Два узла, которые оба наблюдают за пулом памяти, уже имеют почти все транзакции следующего блока, поэтому повторная их передача является напрасной тратой. Matt Corallo описал это решение как BIP152, и Bitcoin Core включил его в версии 0.13.0, выпущенной 23 августа 2016 года. Для всех, кто запускает узел дома, это разница между терпимыми и нестерпимыми расходами на трафик.
Как это работает
Компактная ретрансляция блоков добавляет в протокол четыре сообщения, и самое интересное из них, cmpctblock, описывает блок, не содержа его.
Сообщение cmpctblock несет заголовок размером 80 байт, nonce размером 8 байт, выбранный отправителем, а затем один шестибайтовый короткий идентификатор для каждой транзакции в блоке. Эти идентификаторы получаются из SipHash-2-4 с ключом, полученным из SHA-256 заголовка, соединенного с этим nonce. Именно nonce делает схему безопасной: идентификаторы различаются для каждого блока и каждого отправителя, поэтому никто не может заранее подготовить две транзакции, идентификаторы которых совпадут и разом заблокируют восстановление во всей сети.
Некоторые транзакции передаются целиком, а не по идентификатору. Транзакция coinbase передается всегда, поскольку ни один узел не мог увидеть ее заранее, а отправитель может предварительно включить любую другую транзакцию, если подозревает, что у получателя ее не окажется.
Затем восстановление происходит на стороне получателя. Узел хеширует каждую транзакцию в собственном пуле памяти тем же ключом, находит каждый короткий идентификатор и заполняет блок. Он также держит небольшой дополнительный пул недавно вытесненных и замененных транзакций, который подхватывает те, что выпали из пула памяти мгновением раньше. Все, чего по-прежнему не хватает, запрашивается по позиции с помощью getblocktxn, и отправитель возвращает только эти транзакции в сообщении blocktxn.
Две причины заставляют перейти к загрузке блока целиком: слишком много отсутствующих транзакций, чтобы ради них стоило совершать обмен по сети, или две разные транзакции, дающие одинаковый шестибайтовый идентификатор. Шесть байт допускают 281 триллион значений, поэтому случайные совпадения крайне редки, а умышленные исключает именно nonce.
Объявление бывает двух видов. В режиме низкой пропускной способности узел объявляет о новом блоке и ждет, пока его запросят. В режиме высокой пропускной способности, который узел включает не более чем для трех узлов, сообщение cmpctblock отправляется сразу в момент появления блока, что экономит обмен по сети на участке, где скорость распространения важнее всего.
Где это видно
Компактную ретрансляцию блоков видно в журнале собственного узла, одна строка на блок, и чтение этого журнала является самым быстрым способом судить о том, здоров ли узел.
Bitcoin Core печатает сводку восстановления, в которой указано, сколько транзакций было предварительно включено, сколько пришло из пула памяти, сколько пришло из дополнительного пула и сколько пришлось запросить. На машине, работающей уже несколько часов, число запрошенных транзакций обычно равно нулю или близко к нему. На машине, запущенной десять минут назад, пул памяти почти пуст, почти все приходится загружать, и первые несколько блоков приходят медленно.
Отсюда следует практическое правило для всех, кто запускает узел, чтобы проверять собственный баланс, а не доверять сайту: оставьте его работать. Узел, перезапущенный прямо перед тем, как он вам понадобится, является узлом, загружающим блоки целиком, и его представление о вершине цепочки будет отставать от публичного обозревателя, пока пул памяти не заполнится снова.