Распределённый реестр можно описать как сеть машин, говорящих друг другу правду.
В распределённом реестре сетевые узлы пересылают друг другу сообщения примерно такого рода:
[высказывание] истинно
Узлы отправляют и получают эти истинные высказывания, проверяют их истинность и собирают их в список истинных высказываний, который мы называем реестром:
Это высказывание истинно: ___________ и это высказывание истинно: __________ и это высказывание истинно: ___________ и это высказывание истинно: _________ и это высказывание истинно: ___________ и это высказывание истинно: _________ и …
Эти сообщения обычно содержат высказывания о долгах, такие как «Кендра должна Винсиусу $40». Но вообще высказывания могут быть любыми: «небо голубое», «хвост павлина красочный», «сегодня днём шёл небольшой дождь». В контексте распределённого реестра не имеет значения, истинны ли эти высказывания в нашей (человеческой) реальности. Главное, чтобы они были истинны в реальности, с которой согласны узлы и которая записывается в реестр. Узел может проверить, «истинно» ли сообщение, убедившись, не конфликтует ли оно с какими-либо высказываниями, уже записанными в реестр.
Например, высказывания «у всех кошек шесть лап» и «у всех кошек восемь лап» не могут одновременно быть истинными, поэтому в реестр должно быть включено лишь одно. Распределённый реестр должен гарантировать, что все узлы в конечном итоге согласны с одним и тем же содержимым и что в реестре нет конфликтующих высказываний, – своего рода распределённая машина, говорящая правду.
Принцип матрёшки
В протоколе IOTA есть базовое правило о том, что если я хочу, чтобы другие узлы приняли моё сообщение, я должен публично верифицировать истинность двух или более сообщений, полученных мною от других. Таким образом, в IOTA сообщение будет выглядеть так:
[высказывание] истинно [сообщение] истинно [сообщение] истинно
Первая часть сообщения – это новое высказывание, которое я добавляю в реестр, а вторая – некоторые верифицированные сообщения того же формата, полученные от других узлов.
Из-за этого рекурсивного свойства в итоге сообщения выглядят как-то так:
Поскольку сообщение подтверждает истинность сообщений, на которые оно ссылается, тех, на которые ссылаются они, и т. д., каждое сообщение в итоге содержит всю историю реестра, который в IOTA называется тангл (tangle), по крайней мере с определённой точки зрения и в определённый момент времени. Когда узел отправляет сообщение, он фактически говорит: «Это высказывание истинно: ________ и все сообщения в истории реестра, на которые ссылается это сообщение, вплоть до самого первого отправленного сообщения, также истинны». Каждое сообщение в тангле ведёт к его началу, подобно тому как реки и их притоки ведут к морю.
Конечно, на практике узлы не могут пересылать сообщения, содержащие миллионы или миллиарды вложенных сообщений. Поэтому узлы лишь доказывают, что они ссылаются на эту историю, включая в каждое сообщение хеш сообщений, на которые оно ссылается (которые содержат хеши сообщений, на которые они ссылаются, и т. д.). Так вся история реестра сжимается до очень небольшого количества информации, которую легко можно проверить.
Обещаю заплатить предъявителю по требованию сумму в один фунт
Когда речь идёт о криптовалюте, высказывания в реестре говорят не о погоде или причудливых животных. Они говорят о том, кто кому сколько должен денег. Точно так же как фунт (или любая другая валюта) – это всего лишь обещание заплатить кому-то фунт, цифровые деньги – это обещание заплатить кому-то цифровые деньги. Эти обещания имеют вид высказываний, записанных в реестре и выглядящих примерно так:
C должен D $20
Деньги, которые C должен D, всего лишь отсылка к другому сообщению (или сообщениям), где содержится высказывание с обещанием C $20. Имея это в виду, обновление реестра можно также представить так:
C должен D $20, поскольку [сообщение]
Или:
[B должен C $20, поскольку [сообщение]] истинно C должен D $20, поскольку [сообщение] истинно [сообщение] истинно
И в конечном счёте сообщения начинают выглядеть примерно так:
Стоит отметить, что в модели неизрасходованных выходов транзакций (UTXO) можно пообещать кому-то часть денег, которые должны тебе, а затем пообещать остаток самому себе, или объединить много разных обещаний в одно. Но главное, что цифровые деньги, как и реальные, всего лишь обещание дать кому-то деньги, которые, в свою очередь, представляют собой другое, более старое обещание дать кому-то деньги.
Точно так же сообщение содержит всё прошлое реестра, транзакция, или обновление UTXO, ссылается на всю историю средств, которые она расходует, вроде совокупного индоссамента (передаточной надписи) на обороте чека, вплоть до самого первого сообщения, создавшего все существующие средства.
Порядок вещей
Из-за рекурсивной природы его сообщений в тангле возникают интересные свойства. Например, старые части реестра становится очень сложно изменить. Узел может попытаться отправить сообщение, ссылающееся на другую версию тангла, чьё прошлое отличается от того, которое видят остальные узлы, но это сообщение будет конфликтовать с восприятием всех других узлов и они не будут считать его истинным. Например, если вы попытаетесь изменить какое-нибудь из изображений, вставленных в другое, на обложке альбома Pink Floyd «Ummagumma», то это заметит любой, у кого есть один из сотен тысяч других экземпляров альбома. Как вы убедите всех этих людей, что ваша версия настоящая?
Из простого требования, что сообщение должно подтверждать два прошлых сообщения, следует ещё одно важное свойство: реестр имеет как минимум частичный порядок событий, чувство времени. Может быть невозможно (или, по крайней мере, сложно) определить порядок двух сообщений, не связанных ссылкой, но всегда можно сказать, что сообщение следует после любых сообщений, которые оно подтверждает, и перед любыми сообщениями, которые подтверждают его. Также невозможно создать новое сообщение, на которое ссылается сообщение, уже присутствующее в реестре.
Эти два свойства – (частичный) порядок и неизменяемое прошлое – фундаментальны для любого распределённого реестра. Они тесно взаимосвязаны в том смысле, что «время» бессмысленно, если прошлое можно произвольно менять, как если бы между событиями не было последовательной связи. С такой точки зрения сообщение в распределённом реестре – это не просто высказывание об истине, но также событие [1], которое должно иметь причинно-следственную связь с реальностью, определяемой событиями, предшествующими ему во времени. Точно так же как я не могу пить из стакана, который только что упал на пол и разбился, распределённый реестр предотвращает двойное расходование и воспроизводит минимальное выражение причинно-следственной связи.
Двойное расходование
Рассказывают, что когда Винченцо Перуджа в 1911 г. украл «Мону Лизу», он отнёс её мастеру подделок Иву Шодрону, который создал несколько идеальных копий, проданных разным покупателям, тогда как Шодрон за свою работу получил оригинал. Выдвигалась версия, что оригинал был утрачен и группа торговцев и историков искусства, не достигнув согласия о том, какая из идеально выполненных копий оригинал, тайно выбрали одну и уничтожили остальные, чтобы мы все могли жить спокойно без невыносимой мысли, что «Мона Лиза» на самом деле копия без оригинала [2].
Имея это в виду, представьте, что Беатриса транслирует обновление реестра такого рода:
Беатриса должна Сесилио $20, поскольку [Ариадна должна Беатрисе $20, поскольку […]]
Когда узлы получают это обновление, они проверяют, истинно ли оно, ища в реестре сообщение, где Ариадна обещала $20 Беатрисе, а также не обещала ли Беатриса уже эти $20 кому-то другому. Если оба условия истинны, сообщение не конфликтует с реальностью, записанной в реестре. Высказывание Беатрисы может быть записано, и на него могут ссылаться будущие сообщения [3].
Когда все узлы сети внесли это обновление в реестр, Беатриса отправляет новое сообщение, пытаясь потратить те же средства:
Беатриса должна Далии $20, поскольку [Ариадна должна Беатрисе $20, поскольку […]]
Когда другие узлы получают это сообщение, они проводят такую же проверку, как раньше, и видят, что Беатриса получила средства от Ариадны. Но они также видят сообщение о том, что Беатриса уже отправила те же средства Сесилио. Поскольку новое сообщение конфликтует с реальностью, записанной в реестре, оно будет отклонено.
Однако в определённых ситуациях возможно, что Беатриса отправит оба сообщения почти одновременно и одни узлы увидят первым одно сообщение, а другие – другое. Одни узлы посчитают истинным первое сообщение, другие – второе. Эти конфликтующие мнения представляют две действительных, но взаимоисключающих версии реестра, два возможных будущих записываемой в нём реальности.
Хотя никто посторонний при этом не присутствовал, рассказывают, что эксперты, собравшиеся для подтверждения подлинности знаменитой картины, решили выбрать, какую «Мону Лизу» спасти от уничтожения, с помощью голосования. Точно так же консенсус в распределённом реестре – это вопрос поиска способа, как все узлы сети могут договориться о единой версии реестра, столкнувшись с конфликтом, – установить общее восприятие реальности.
Интересное по теме: Как защититься от атак двойного расходования
Кот жив или мёртв
Простой способ разрешить конфликт – спросить всех участников сети, какую версию реестра они предпочитают, после чего все должны согласиться с тем, за что проголосует большинство.
Первая проблема такого подхода – проблема для всех распределённых реестров – в том, что кто-то может запустить большое количество узлов и отдать нужное число голосов, чтобы повлиять на консенсус или вообще помешать его достижению, вынудив сеть разделиться на две непримиримые реальности.
Решение так называемой атаки Сивиллы – требовать, чтобы узлы доказывали доступ к ограниченному ресурсу, чтобы голосовать и определять консенсус. Например, в Биткойне майнер, способный доказать доступ к определённой вычислительной мощности, получает разрешение делать записи в реестре и, следовательно, голосовать за самый длинный блокчейн. В IOTA тот, кто может доказать доступ к определённому количеству токенов, получает голос, пропорциональный удерживаемому им количеству токенов. Это право голоса называется мана и может быть делегировано любому узлу, участвующему в сети. Мана делает голосование дорогим, так что никто не может отдать как угодно большое количество голосов.
В отличие от многих других распределённых реестров, таких как Биткойн или Эфириум, которые выбирают единственного создателя блока, который записывает обновление в реестр, IOTA – безлидерный протокол. Каждый узел, участвующий в сети, независимо от силы своего голоса, может участвовать в консенсусном процессе.
Это подводит нас к ещё одной проблеме того, чтобы просто спрашивать у каждого узла в сети его мнение о конфликте: каждый узел должен отправить своё мнение каждому другому узлу. В небольшой сети это не создаст никаких трудностей, но когда голосовать будут тысячи или десятки тысяч узлов, при возникновении конфликта передача голосов поглотит большую часть пропускной способности сети, и узлы будут обременены вычислительными издержками верификации подписей всех полученных ими голосов. Безлидерный протокол нуждается в механизме голосования, минимизирующем объём и размер сообщений, с помощью которых передаются голоса.
Быстрый вероятностный консенсус (fast probabilistic consensus (FPC)) – прошедший научную экспертную оценку протокол безлидерного консенсуса с надёжными гарантиями безопасности, который должен быть внедрён в протокол IOTA в конце этого года. Вместо сбора мнений всех узлов в сети, каждый узел спрашивает мнение у случайной выборки узлов. В случае конфликта узлы многократно обновляют своё мнение исходя из мнений выбранных случайным образом других узлов и в итоге договариваются, какой версии реестра придерживаться. Поскольку узлы с сильной маной будут спрашивать чаще, они также могут публиковать своё мнение непосредственно в тангле, что ещё больше минимизирует издержки сообщений. Хотя это очень упрощённое описание FPC, этот протокол голосования имеет доказуемые гарантии безопасности и масштабируется для как угодно большого множества валидаторов.
Выбери своё приключение
Ещё одно возможное, но несколько более экспериментальное решение (консенсус мультивселенной или голосование в тангле) состоит в том, чтобы просто рассматривать все сообщения как голоса. Если я вижу два конфликтующих сообщения, я могу проголосовать за одно из них, отправив новые сообщения, ссылающиеся на то из конфликтующих сообщений, которое я предпочитаю, – то, которое я увидел первым или которое имеет больше голосов. Поскольку каждое сообщение – это высказывание «вся эта история реестра истинна», предпочитая ссылаться на одно из конфликтующих сообщений, узел отдаёт голос – вес которого зависит от его маны – за предпочитаемую им версию реальности реестра.
Если я отдам голос за одну реальность и позже увижу, что большинство других узлов голосуют за другую, я могу перейти на другую сторону и начать отправлять сообщения с той версией реестра, за которую проголосовало больше узлов (если оценивать по весу их маны). Когда 51% сетевой маны (если она контролируется честными узлами) поддержит одну из сторон конфликта, злоумышленник не сможет помешать сети достичь консенсуса, если все узлы в итоге получат одни и те же сообщения. Преимущество данного подхода в том, что дополнительные сообщения не нужны и провернуть потенциальную атаку очень сложно.
Возможный вектор атаки – это когда узел-злоумышленник будет быстро переходить с одной стороны конфликта на другую, голосуя сначала за одну реальность, а затем за другую, так что ни одна реальность не сможет достичь стабильных больше 50% голосов, – что превратит тангл в некое подобие ни живого ни мёртвого кота-зомби Шрёдингера. Хотя осуществить это, вероятно, очень сложно, теоретически такую атаку на метастабильность может провести любой узел независимо от его маны, просто правильно выбрав время голосования.
Однако я считаю, что у этой проблемы может быть простое решение, основанное на фундаментальной идее, сформулированной в начале этой статьи и гласящей, что каждый узел должен проверить истинность высказываний, получаемых им от других узлов.
Данное высказывание ложно
Когда узел отдаёт голос за одну из конфликтующих реальностей, он не только высказывается об истинности сообщений, на которые она ссылается (эти сообщения истинны…), но также делает высказывание второго порядка: «Эту реальность я считаю имеющей наибольший вес одобрения».
Для того чтобы предотвратить произвольное изменение узлом своего мнения, можно использовать тангл, чтобы проверить, голосует ли узел «честно» – т. е. выбирает ли он вместо реальности, по его мнению имеющей меньше голосов, ту, которая имеет больше голосов.
Если рассматривать вес, наблюдаемый в предыдущем голосовании узла за данную реальность, как его «воспринимаемый вес реальности», то можно исключить из консенсуса «нечестные» голоса, выражающие изменение мнения с более тяжёлой на более лёгкую реальность. Таким образом, когда узел меняет своё мнение с реальности A на реальность B, его голос будет «засчитан» (т. е. вес одобрения узла будет применён к реальности B), только если его воспринимаемый вес реальности B больше, чем его воспринимаемый вес реальности A плюс его собственный вес.
На диаграмме выше в момент t = 1 синий узел должен был воспринимать реальность A как имеющую как минимум вес одобрения, наблюдаемый в его предыдущем голосовании, плюс его собственный вес одобрения. Аналогично синий узел должен был воспринимать вес одобрения реальности B в момент второго голосования. Другие узлы могут легко проверить честность изменения синим узлом своего мнения, сравнив эти два значения.
Выполнение такой простой проверки означает, что злоумышленник, пытающийся произвольно изменить мнение, будет вынужден голосовать за ту из конфликтующих реальностей, чей вес растёт, и максимум сможет с большим трудом задержать консенсус на какое-то время.
Данная идея лишь развивает принцип протокольного уровня, согласно которому узел должен проверять высказывания других узлов, поскольку голос за ту или иную реальность равнозначен высказыванию «эта реальность более тяжёлая». Как я пытался показать в этой статье, простое требование, чтобы узлы «говорили правду» в своих высказываниях и о высказываниях других, словно практически неизбежно ведёт к консенсусу как эмерджентному свойству сети.
Идя дальше Биткойна
Прорыв консенсуса Сатоши Накамото был в том, что он разработал протокол распределённого консенсуса, масштабируемого в открытой сети, где участники голосуют за предпочитаемую ими версию реестра, просто передавая новые обновления в реестр.
Однако Биткойн по своему замыслу имеет медленное подтверждение, чтобы избежать одновременного добавления новых блоков множеством майнеров. Если бы параллельно передавались десятки блоков, в сети было бы много разных блокчейнов – конкурирующих версий реестра, – и она не могла бы прийти к согласию об одном самом длинном блокчейне. В некотором смысле, ограничив время подтверждения, чтобы обеспечить линейное обновление реестра, Биткойн не даёт блокчейну превратиться в тангл.
В этом плане недостаток Биткойна в том, что он пошёл недостаточно далеко. IOTA уникальна во многих отношениях, но особенно в том, что она расширяет принципы консенсуса Накамото, чтобы построить бескомиссионный и безлидерный протокол параллельных обновлений реестра, масштабируемого для как угодно большого множества валидаторов. Поскольку все узлы сотрудничают в достижении консенсуса, гонка майнеров упразднена, и сетевая вычислительная мощность используется, чтобы обеспечить безопасность сети максимально эффективным и децентрализованным образом.
Вот почему я заинтересован в этом проекте – одном из немногих пытающихся расширить инновации Биткойна.
Примечания:
[1] Если рассматривать обновления реестра как события в причинно-следственном контексте, то сообщения, которые их передают, – это нечто вроде наблюдений, фиксирующих встречу наблюдателя с событием. Чем больше наблюдателей видят событие или видят, что другие видят событие, тем больше это событие укрепляется в причинно-следственной структуре реальности реестра. В этом смысле различие между событием и наблюдением события стирается на самом микроскопическом уровне причинно-следственной структуры реестра. Конфликт случается, когда разные наблюдатели в сети регистрируют два возможных с причинно-следственной точки зрения, но взаимоисключающих события. Консенсус означает, что все соглашаются «знать» одно из конфликтующих событий, то есть признавать, что это событие «случилось». Можно перефразировать известную загадку: если обновление реестра – это дерево, падающее в лесу, когда рядом никого нет, слышен ли его звук?
[2] Эта часть истории полностью вымышлена ради драматического эффекта.
[3] Поэтому консенсус не зависит от сохранения всей истории реестра всё время. Чтобы прийти к консенсусу, узлам нужно лишь следить за сообщениями, доказывающими текущее состояние реестра. Как только новое состояние подтверждено, узлы могут удалить старую информацию, которая не требуется для выявления конфликта. Распределённый реестр – это машина, говорящая правду, а не бесконечный архив.