Почему биткойн не накладывает дополнительные ограничения на конкурирующие форки цепочки блоков, кроме длины цепочки? (например, время и количество подтверждений)

В системе проверки работоспособности Биткойн консенсус относительно того, какую цепочку блоков следует считать «истинной» цепочкой блоков, основан только (?) на том, какая цепочка длиннее.

Соответственно, если процитировать хорошо написанный ответ Нейта Элдреджа, типичная атака 51% будет выглядеть так:

  1. Злоумышленник в частном порядке начинает майнить свою собственную цепочку, которая расходится с основной цепочкой в ​​каком-то блоке N.

  2. Злоумышленник вносит монеты в ваш бизнес, отправляя их с адреса A. Назовите эту транзакцию X.

  3. Злоумышленник вставляет в свою цепочку транзакцию X', которая конфликтует с X; обычно X' отправляет монеты с адреса A на другой адрес, принадлежащий злоумышленнику.

  4. Злоумышленник ждет нескольких подтверждений транзакции X в блоках N+1, ..., N+6 (замените 6 любым количеством подтверждений, которое требуется вашему бизнесу) основной цепочки.

  5. Как только будет достаточно подтверждений, чтобы удовлетворить вас, вы доставляете товары или услуги злоумышленнику.

  6. Злоумышленник выпускает свою собственную цепочку, в которой теперь есть блоки, скажем, до N+50. Будучи длиннее, эта цепочка принимается сетью. Эта цепочка содержит не транзакцию X, а X', поэтому у вас нет монет, которые, как вы думали, у вас есть.

Обратите внимание, что вплоть до шага 6 все в сети выглядит совершенно нормально; только злоумышленник знает, что происходит.

Тогда мой вопрос: почему биткойн не указывает максимальную продолжительность времени и/или максимальное количество подтверждений , после которых конкурирующий/разветвляющийся блок отклоняется, даже если он поддерживается более длинной цепочкой (тайно предварительно добытых) дочерних блоков?

Подводя итог этой идее в псевдокоде:

CUTOFF_TIME = 1200 # seconds
CUTOFF_CONFIRMATIONS = 3

is_acceptable_block(new_block, parent_block):
    if not is_valid_block(new_block):
        return false

    if is_first_child(new_block, parent_block):
        return true

    old_block = get_first_child(parent_block)

    if age_difference(new_block, old_block) > CUTOFF_TIME:
        return false

    if child_chain_length(old_block) > CUTOFF_CONFIRMATIONS:
        return false

    return child_chain_length(new_block) > child_chain_length(old_block)

Если бы это было жизнеспособно, то описанный выше сценарий атаки 51% стал бы намного сложнее; и в результате количество времени/подтверждений, которые нужно ждать, прежде чем можно будет безопасно поверить в транзакцию, уменьшится, верно?

Ответы (3)

Тогда мой вопрос: почему биткойн не указывает максимальную продолжительность времени и/или максимальное количество подтверждений, после которых конкурирующий/разветвляющийся блок отклоняется, даже если он поддерживается более длинной цепочкой (тайно предварительно добытых) дочерних блоков?

Потому что вы не можете доказать это узлам, которых не было в сети во время атаки. Это означает, что либо:

  • Злоумышленник может создать новую цепочку, и если к сети присоединится достаточное количество узлов, а новая цепочка будет лучшей, это приведет к ситуации, когда половина узлов считает, что одна цепочка является лучшей, а половина считает, что другая другая цепь лучше.

  • Если вы заставляете новые узлы доверять старым узлам, когда они говорят, что лучшая цепочка — это не настоящая цепочка, вы теперь расширяете круг людей, которым вы доверяете, за счет людей, передающих цепочку, в дополнение к людям, занимающимся ее майнингом. Раньше, если два узла считали разные цепочки лучшими, вы могли загрузить обе и с уверенностью сказать, что одна лучше другой. Если бы вы реализовали это изменение, вам нужно было бы решить, какой узел заслуживает большего доверия.

Если бы это было жизнеспособно, то описанный выше сценарий атаки 51% стал бы намного сложнее; и в результате количество времени/подтверждений, которые нужно ждать, прежде чем можно будет безопасно поверить в транзакцию, уменьшится, верно?

Атака 51% может дублировать выходы с любым количеством подтверждений. Часто цитируемая цифра 6 подтверждений взята из статьи о биткойнах , где Сатоши подсчитал, что у злоумышленника с 10% хэш-мощности сети будет менее 0,1% шансов наверстать упущенное.

Ваше первое замечание хорошее. Узел сможет проверить предложенные мной ограничения только в том случае, если он будет получать объявления о блоках в режиме реального времени. Тем не менее, это не сразу очевидно для меня "you're now expanding the circle of people you trust to the people relaying the chain". Под этим я подразумеваю: разве вы уже (в существующей сегодня сети биткойнов) не расширяете доверие к узлам-ретрансляторам? Я думал, что эта проблема доверия уже существует, но она не представляет проблемы, учитывая стимулы узлов поддерживать сеть в целом в работоспособном состоянии.
Кроме того, я не уверен, что ваш 2-й абзац должен опровергать мое предложение, которое вы цитировали. В любом случае, ваш ответ в его нынешнем виде очень ценится. :)
@Уилл aren't you already extending trust to relaying nodesОчень мало. Они могут не сообщать вам о блоках, но как только вы подключитесь к одному узлу, который не сотрудничает с эмбарго, вы загрузите лучшую цепочку.

Во-первых, небольшое пояснение: если предположить, что обе цепочки имеют действительные блоки, побеждает цепочка с наибольшим количеством доказательств работы, а не обязательно цепочка с наибольшим количеством блоков.

Во-вторых, спасибо за псевдокод. Всегда приятно отвечать на вопрос, написанный понятным кодом.

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

Почему? Потому что разные узлы могут иметь разное внешнее состояние. Допустим, злоумышленнику удается разделить сеть так, что все в Европе работают в одной цепочке, а все в Северной Америке работают в другой цепочке:

        /--> C  -> D  -> E  -> F  -> G  Europe Chain
A -> B -
        \--> C` -> D` -> E` -> F`       North America Chain

Поскольку эти два форка отличаются более чем на 3 блока, даже при восстановлении полной сети ваш код не позволяет узлам и майнерам в Северной Америке переключиться на более сильную европейскую цепочку — это означает, что сеть останется разветвленной навсегда.

Я считаю полезным всегда спрашивать себя: «Как новые узлы, которые впервые загружают цепочку блоков, придут к консенсусу с активными в настоящее время узлами без доверия?»

Ваше первое утверждение действительно верно? Не как я это понял... Я понял, что если есть два блока одинаковой длины, которые одновременно решают два майнера, то он разветвляется, пока не будет решен следующий блок, и победителем становится самый длинный, так что временные разветвления - это что-то это может случиться и ожидается, но вероятность того, что форк произойдет, очень низка, и экспоненциально снижается вероятность того, что они оба сосуществуют для каждого добавленного блока.
Доказательство работы рассчитывается на основе целевой сложности, а не хеша заголовка. (Конечно, хэш должен быть <=целью, чтобы блок был действительным.) Это означает, что два блока с одним и тем же родителем будут иметь одинаковое доказательство работы, если только они не находятся на границе изменения сложности. Если бы у нас не было изменений сложности, было бы правильно сказать, что побеждает самая длинная вилка. Как вы сказали, случайные разветвления довольно распространены, но длинные случайные разветвления (> 2 блоков) крайне редки.
Хорошо, что узлы могут проверять ограничения, которые я предложил, только в том случае, если они получают объявления о блоках в режиме реального времени (в отличие от последующей загрузки цепочки). Кроме того, хороший момент об изменении сложности, так что +1 и к этому ответу.
@DavidA.Harding: Разве даже при изменении границы сложности два блока одинаковой высоты с общим родителем не будут иметь одну и ту же цель? Я думаю, вам понадобится вилка длиной не менее двух блоков, чтобы иметь блоки на одной высоте с разными целями.
@Murch, ты прав. Наверное, я недостаточно хорошо обдумал это. Спасибо!

Такой вид существует с контрольно- пропускными пунктами . Источник Bitcoin Core содержит список хэшей блоков определенной высоты, и стандартный клиент отклонит любую цепочку, не содержащую эти блоки такой высоты, поэтому он не примет вилку, которая расходится до последней контрольной точки. Периодически сопровождающие Bitcoin Core будут добавлять в этот список некоторые относительно свежие (но не слишком свежие) блоки.

Чтобы понять, насколько недавно, последняя контрольная точка в репозитории git для Bitcoin Core находится на высоте 295000 (добыто в апреле 2014 года), а текущая высота — 339431. 44431 блок, или около 9 месяцев работы. Чувствую лучше сейчас? :-)

Хотя то, что вы сказали, верно, контрольные точки Bitcoin Core в основном являются артефактом метода загрузки блоков, используемого в серии 0.9.x и ранее. С блоками в первую очередь легко накормить новый узел действительной, но не самой сильной цепочкой с сотнями гигабайт бесполезных транзакций. С новым методом «сначала заголовки» в Bitcoin Core 0.10.0 это больше не проблема, а контрольные точки не так важны. Возможно, их даже можно будет заменить независимой от цепочки проверкой полного доказательства работы (цепной работы).
@DavidA.Harding, контрольные точки также служат для ускорения проверки подписи (поскольку сценарии перед последней контрольной точкой не проверяются). Даже при синхронизации по заголовкам контрольные точки по-прежнему полезны для определения того, когда следует пропустить проверку подписи.