Compact Block Filters — небольшие сводки содержимого блоков Bitcoin. Кошелёк скачивает их и на своём устройстве проверяет, какие блоки могут содержать его платежи. Только затем он запрашивает эти блоки целиком. Это экономит трафик и меньше раскрывает цель поиска. Однако совпадение в фильтре ещё не доказывает наличие платежа и не заменяет полную проверку правил Bitcoin.
Анна ждёт платёж в мобильном кошельке. Кошелёк — приложение или устройство для получения и отправки биткоинов. Блоки — наборы транзакций, но телефону необязательно скачивать каждый набор целиком. Сначала он может просматривать небольшие фильтры, как читатель ищет нужную страницу по указателю книги. Для одного блока и типа фильтра все получают одинаковую сводку; выбор того, что касается Анны, происходит уже в телефоне. Технические документы BIP 157 и BIP 158 делят задачи: первый описывает получение и проверку фильтров, второй — их содержимое и построение. Кошелёк сначала проверяет заголовки блоков, то есть основные данные, связывающие блоки в цепь, затем получает проверочные данные фильтров и сами фильтры. При совпадении он скачивает полный блок и ищет настоящую транзакцию. Похожее название Compact Blocks из BIP 152 относится к другой задаче: быстрой передаче новых блоков между узлами. Узел — программа, которая проверяет транзакции и блоки и обменивается данными с другими участниками сети. [1] [2] [5] [6]
Транзакция Bitcoin создаёт выходы: суммы с условиями их дальнейшего расходования. Код этих условий называется scriptPubKey. Вход новой транзакции указывает на предыдущий выход, который расходуется. Поэтому фильтр basic с идентификатором 0x00 включает скрипты новых выходов и скрипты предыдущих выходов, расходуемых в блоке. Анна может искать и поступления, и расходы. Новые скрипты, начинающиеся с OP_RETURN, исключаются: эта инструкция делает выход нерасходуемым. Исключается и особый вход транзакции coinbase, которая назначает награду майнеру, не расходуя предыдущий выход. Пустые элементы пропускают, повторяющиеся учитывают только раз. Это не список всех идентификаторов транзакций txid, текстовых адресов или данных witness, например подписей. Для правильного построения нужны и предыдущие расходуемые выходы, а не только новый блок. [2]
Сервер может прислать Анне сводку, из которой намеренно удалён её платёж. Поэтому кошелёк проверяет также связи с предыдущими фильтрами. Хеш — короткий цифровой отпечаток данных. Двукратное применение SHA-256 к сохранённому фильтру даёт его double-SHA256. Этот отпечаток соединяют с предыдущим заголовком фильтра и так же хешируют, получая следующий заголовок. Изменение старого фильтра меняет и последующие проверочные данные. Однако защищённый майнингом заголовок блока не содержит хеша этой вспомогательной цепочки фильтров. Если все серверы дадут одинаковую поддельную цепь, её отпечатки могут идеально согласовываться. Математическая согласованность сама по себе не доказывает соответствия сводки настоящему блоку. [1]
Поэтому BIP 157 рекомендует подключения к нескольким независимым узлам, называемым peers в таком обмене. Альтернатива — защищённое соединение с доверенным узлом, например собственным. Получив противоречивые цепочки фильтров, кошелёк находит первое расхождение. Он может восстановить правильный фильтр из соответствующего блока и необходимых предыдущих выходов. Гарантия распознавания правильных фильтров предполагает хотя бы одного честного пира; несколько соединений с одним атакующим не выполняют это условие. Сама цепь тоже меняется: при реорганизации узлы заменяют часть её конца ветвью с большей суммой доказанной работы. Кошелёк должен следовать фильтрам новой ветви и заново оценить затронутые платежи. Найденное ранее подтверждение всё ещё зависит от того, какую цепь принимает сеть. [1] [2]
В прежнем подходе BIP 37 кошелёк отправлял серверу собственный фильтр отслеживаемых данных. Compact Block Filters меняют направление: кошелёк получает общие данные и делает личный выбор на своём устройстве. Это ограничивает утечку сведений об отслеживаемых скриптах. Но поставщик по-прежнему видит, какие полные блоки Анна запрашивает затем, и может связать запросы с её IP-адресом, сетевым адресом соединения. Повторные обращения способны раскрыть дополнительные закономерности. BIP 157 советует случайно выбирать источники полных блоков среди узлов, к которым кошелёк сам открыл соединения. Блок может поступить не от того узла, что предоставил фильтр. Это улучшает приватность, но не гарантирует анонимности. [1]
Фильтры описывают блоки, уже включённые в цепь. Они не охватывают текущий Mempool — неподтверждённые транзакции, которые конкретный узел хранит для передачи дальше или майнинга. Совпадение не доказывает и того, что у Анны есть ключ для расходования найденных средств. Приватный ключ — секретное числовое значение, с помощью которого кошелёк создаёт цифровую подпись, разрешающую потратить средства. Кошелёк должен проверить настоящую транзакцию и её включение в блок. Тем не менее лёгкий клиент не проверяет каждую транзакцию каждого блока по всем правилам, как Full Node, полностью проверяющий узел. За экономией ресурсов стоит реальный компромисс безопасности. Доступность — отдельный вопрос: Pruned Node может удалить старые блоки после проверки и сохранить их фильтры. Анна получит сводку, но полный старый блок ей придётся искать в другом месте. Само удаление старых данных не означает отказа от полной проверки правил. [1] [5]
За малый размер приходится платить: фильтр может ответить «возможно, да», хотя элемента в блоке нет. Это ложное совпадение, или false positive. Анна скачает лишний блок, но кошелёк не найдёт предполагаемый платёж и не должен его учитывать. Правильный фильтр не пропускает элемент, который действительно включает по своим правилам; это свойство не делает надёжными данные, выдуманные нечестным сервером. Технически SipHash-2-4 превращает элементы в числа в диапазоне размером N × M, где N — число элементов. Числа сортируют, а разности компактно сохраняют с помощью кодирования Golomb-Rice. P=19 управляет кодированием, M=784931 влияет на случайные совпадения; вероятность для одного запроса вне множества составляет примерно 1/M. Байт — обычная единица объёма данных. Ключ SipHash — первые 16 байтов хеша блока в порядке little-endian, то есть от младших байтов. Это не секретный ключ кошелька. Здесь SipHash превращает элементы в числа для фильтра, а не шифрует их. Запись фильтра начинается с N в формате CompactSize для неотрицательных целых чисел. [2]
На дату проверки 2026-10-17 оба документа имеют статус Deployed: протокол применяется, но это не означает поддержку каждым кошельком. Этот пример настроек относится именно к Bitcoin Core 29.0. -blockfilterindex создаёт локальный индекс. Для обслуживания других узлов нужны -peerblockfilters и индекс basic; NODE_COMPACT_FILTERS сообщает о поддержке. Программный интерфейс RPC через getblockfilter возвращает поля filter и header выбранного блока. Работающий RPC сам по себе не доказывает, что другие узлы могут получить фильтры по сети. Для читателей спецификации: getcfilters/cfilter передаёт фильтры, getcfheaders/cfheaders — данные связывания, getcfcheckpt/cfcheckpt — контрольные точки вспомогательной цепи. Это названия сетевых сообщений, а не команды, которые должен вводить пользователь мобильного кошелька. [3] [4]
Для полной картины прочитайте эту статью вместе с Neutrino, Full Node, Pruned Node, Приватность в Bitcoin, Compact Blocks, Mempool. На эту статью также ссылаются Compact Block Filters, Neutrino.