Глоссарий / Узлы и ПО
Инвентарь
Другие названия: Сообщение inv.
- Что такое инвентарь?
- Инвентарь представляет собой список идентификаторов объектов, которые узел объявляет своим пирам, сообщая, какие транзакции и блоки у него есть, и при этом не отправляя ни один из них.
Сначала объявить, доставить по запросу. Именно поэтому сеть не тонет в дубликатах: каждая запись стоит 36 байт, четырехбайтовый тег типа плюс 32-байтовый хеш, и одно сообщение inv может нести до 50 000 таких записей. Пир, у которого объект уже есть, никогда его не запрашивает, и пропускная способность на это не тратится.
Как это работает
Запись инвентаря состоит из пары: число, говорящее, что это за вещь, и хеш, который ее идентифицирует.
Коды типов представляют собой небольшие целые числа. 1 означает транзакцию, 2 означает блок, 3 означает отфильтрованный блок из старой схемы фильтров Блума, 4 означает компактный блок, 5 означает транзакцию, идентифицированную по хешу свидетеля. Установка бита 0x40000000 поверх типа помечает вариант со свидетелем, поэтому пир, поддерживающий segwit, запрашивает MSG_WITNESS_BLOCK там, где более старый запросил бы обычный блок.
Обмен идет в три шага. Узел отправляет inv со списком того, что является новым. Пир просматривает список, игнорирует все, что узнает, и отвечает getdata, называя только то, чего у него нет. Узел отправляет эти объекты, по одному сообщению на каждый, или notfound там, где что-то к тому времени уже отброшено. Арифметика, стоящая за пределом в 50 000, заслуживает внимания: 50 000 записей по 36 байт составляют 1 800 000 байт, что с запасом укладывается в потолок 4 000 000 байт на одно сообщение, а Bitcoin Core содержит проверку на этапе компиляции, которое поддерживает согласованность этих двух констант между собой.
Момент объявления является механизмом защиты приватности, а не деталью реализации. Bitcoin Core не объявляет транзакцию в тот момент, когда узнает о ней. Объявления группируются и выпускаются по случайному таймеру, составляющему в среднем две секунды для исходящих пиров и пять для входящих, поэтому наблюдатель, подключенный ко многим узлам, не может по порядку поступления определить, где начался платеж. Блоки пропускают задержку полностью, потому что скрывать нечего, а секунды стоят денег.
Выкрикивать каждый хеш каждому пиру дорого, и Erlay представляет собой предложенное лекарство: пиры периодически сверяют короткие наброски того, что есть у каждого, вместо того чтобы рассылать идентификаторы во все стороны.
Где это видно
Инвентари представляют собой самый шумный элемент сетевого интерфейса узла и самый простой для наблюдения.
Вызов getpeerinfo разбивает трафик по типам сообщений, и inv почти всегда входит в число крупнейших счетчиков. Хорошо связанный узел тратит реальную долю своей пропускной способности на объявление хешей, которые в итоге никому не понадобились. Именно поэтому платеж появляется в одном обозревателе блоков на секунды раньше, чем в другом: это разные наблюдатели, слышащие разные объявления из разных частей сети.
Одна привычка, от которой стоит отвыкнуть: inv не является обязательством. Узел может объявить транзакцию, а через несколько минут вытеснить ее, когда заполнится его пул памяти, и он не обязан никого уведомлять об исправлении.
Инвентарь vs пул памяти
Инвентарь представляет собой сообщение; пул памяти является хранилищем, и только одно из них переживает момент. Сообщение inv говорит пиру, что хеш где-то существует. Пул памяти представляет собой набор неподтвержденных транзакций, которые узел действительно проверил, держит в памяти и готов передавать дальше или майнить, размером 300 МБ по умолчанию с политикой вытеснения, которая отбрасывает самые дешевые первыми. Наблюдение за тем, как ваш txid распространяется через объявления inv, говорит вам, что сеть услышала о вашем платеже. Оно не говорит, что у кого-то он останется через час.