:RU: Ouroboros Leos - обзор от Pi (π) Lanningham

Краткий обзор протокола Ouroboros Leos от Pi (π) Lanningham (CTO Sundaeswap), источник: https://x.com/Quantumplation/status/1797396546108944498?t=hDdLH2XICOB5vWZJL4yFYg&s=19

"Леос основывается на достаточно простых идеях; вопрос в том, как их все объединить, при этом не пожертвовав в устойчивости, безопасности, децентрализации и так далее.
Давайте изучим каждую из этих идей и опасности наивного применения каждой из них.

Во-первых, почему Кардано сейчас “медленный”?
Каждый блок создаётся раз в 20 секунд. Почему бы просто не делать каждый блок раз в секунду, и таким образом сразу увеличить скорость в 20 раз? Или 5 блоков в секунду, увеличив скорость в 100 раз?
Каждый раз, когда создаётся блок, он должен распространиться по сети. Стейк пул, создавший блок, отправляет его своим соседям, те отправляют его дальше своим соседям, те - своим и так далее.
К тому времени, как следующий стейк пул создаст блок, важно, чтобы он знал о предыдущем созданном, иначе он подумает, что кто-то пропустил свой слот, и создаст конфликтующий блок.
Если конфликтов будет слишком много, сеть не сможет определить, какой из них верный, и как двигаться дальше. Транзакции будут упускаться, и злоумышленник сможет повлиять на то, какие блоки будут выбраны, какие транзакции запишутся в блокчейн и так далее.
Злоумышленник может даже усугубить дело, когда настанет его черёд создавать блок, поскольку он сможет сделать несколько валидных блоков. Если мошенник владеет пулом, он может сделать 1000 блоков в предоставленном ему слоте, и отправить их другим участникам, добившись того же эффекта.
Поэтому между блоками должен быть временной промежуток, чтобы те успели распространиться, и дубли успели быть устранены, и это время прямо пропорционально размеру сети и пропускной способности каждого соединения между узлами.
По этой же причине мы не можем произвольно увеличить размер самого блока - большие блоки будут медленней распространяться.
Можем ли мы ускорить сеть, уменьшив размер блока? Если размер блоков будет всего один килобайт, мы сможем чаще их создавать, потому что они будут быстрее распространяться. Но в маленькие блоки помещается меньше транзакций, и этот манёвр не позволит нам повысить пропускную способность сети.
К тому же отсутствию результата приведет и обратная попытка - делать блоки очень большими, но не частыми.

Чтобы понять идею, которая позволит нам запихнуть больше транзакций в блоки, нам нужно понимать, как в принципе транзакции попадают в блоки.
Когда вы создаёте и отправляете транзакцию с помощью вашего любимого децентрализованного приложения, она отправляется в узел Кардано. Узел отправляет её своим соседям, а те - своим и так далее. Звучит знакомо? Этот подход называется “распространением слухов”, и он используется как для блоков, так и для транзакций.
Но почему с транзакциями нет тех же проблем, что с и блоками? Мы же отправляем транзакции когда хотим, а не каждые 20 секунд.
Ключевая разница в том, что мы не чередуем и не финализируем эти транзакции. Когда мы их распространяем их по сети, мы не создаём конфликт.
Когда наступает момент создать блок, соответствующий узел собирает все транзакции, о которых знает, и запихивает в блок, и начинает его распространять. (Заметьте, что таким образом одна транзакция путешествует по сети два раза - вот где пространство для оптимизации!)
Что если мы будем записывать в блоки для финализации и сортировки не сами транзакции, а их хэши?
Если все и так знают про эти транзакции, поскольку их уже ранее везде распространили, зачем их распространять второй раз, но уже в блоке?
88кб блок например может содержать в себе до ~2700 транзакций в виде ссылки, или по другому, 100 транзакций требуют всего ~3кб места в блоке.
И не важно, выберем ли мы более частые но маленькие блоки, или оставим редкие, но содержащие больше транзакций.
Однако в таком подходе есть серьёзный изъян. Что если производитель блока уже знает про транзакцию, но она ещё не достигла всех узлов сети? Некоторые пулы будут знать о транзакции и примут блок, но другие будут ждать саму транзакцию для подтверждения блока.
И вот, снова конфликт. Что ещё хуже, злоумышленник может помещать произвольные байты вместо ссылок в блоке, и спамить ими окружающих, заставляя дожидаться транзакций, которые никогда не придут.
Чтобы обеспечить нормальное функционирования блокчейна, нам нужен способ доказывать, что “в данном блоке есть транзакции, о которых вы можете не знать, но они точно до вас дойдут от честного узла”.
Другими словами, нам требуется механизм подтверждений, “endorsement”, что достаточное количество узлов знают про транзакцию, чтобы считать данные достоверными.
(Вот откуда берётся термин “подтверждения ввода”, “input endorsers”, и вот что имеется в виду в научной статье, когда заявляется, что они обеспечивают “доступность данных”).
В статье Леос говорится: пусть узлы создают “вводные блоки”, “input blocks” (с транзакциями) настолько быстро, насколько смогут. Затем, по специальному графику, стейк пул будет предлагать “подтверждающий блок”, “endorsement block”, который будет содержать все “вводные блоки”, “input blocks”, о которых пул знает.
Другие пулы будут голосовать за подтверждающий блок своим стейком, если они видели все содержащиеся в нём вводные блоки.
И как только кто-то увидит достаточное количество голосов (в виде подписей соответствующим стейком) от достаточного количества пулов, он создаст нормальный блок Ораборос.
И уже этот блок может свободно распространяться, и при этом содержать тысячи транзакций. Ораборос будет работать как обычно, без опасности разделения, форка под влиянием злоумышленника.

Доказательство, помещённое в блок, гарантирует, что как минимум половина стейка подписалась под ним, означая, что как минимум одна честная сторона хранит транзакции, которые со временем до нас дойдут.

Отлично, мы только что описали схему, по которой мы можем финализировать и чередовать транзакции без риска разделения блокчейна.
Однако остаётся небольшая проблема: Конфликты.
Так как узлы подтверждают новый блок беря за основу подтверждения, “endorsements” других узлов, а не валидируют транзакции сами, становится возможной ситуация, когда два разных вводных, “input” блока будут содержать конфликтующие транзакции.
Эта проблема решается вводом некоего правила, как разрешать такого рода конфликты.
В случае eUTXO например это супер просто: вы выкидываете одну из транзакций, использующую один и тот же ввод, “input”.
Для избегания спама вы можете ввести залог: если кто-то подпишет две транзакции, использующие один и тот же ввод, “input”, он потеряет небольшое количество Ады. Т.е. ввести механизм, похожий на залог для “плохих” скриптов.

В итоге, Леос позволит проводить транзакции настолько быстро, насколько быстро сеть будет пропускать “вводные блоки”, “input blocks”; честные узлы будут “подтверждать”, “endorse” эти транзакции, как только их получат и провалидируют с помощью “подтверждающих блоков”, “endorsement blocks”, и эти “подтверждающие блоки” будут проголосованы половиной стейка в нормальном, медленном Ораборос Леос.
Тут есть также дополнительное классное следствие, которое позволит избежать повторных вычислений: если достаточное количество стейка подтвердит транзакцию, мне не нужно перезапускать скрипт, я могу довериться, что она верна.
Опять, же помогает модель eUTXO, потому что каждая транзакция точно описывает изменение состояния счетов, “ledger” без необходимости перезапускать скрипты.
Если какой-то оракл говорит мне: “да, эта транзакция точно верна”, я могу просто убрать потраченные вводы, “inputs”, и добавить новые выводы, “outputs”.

Полная версия Ораборос Леос содержит множество других мелких деталей, которые я опустил, такие как возможность “подтверждающим блокам” ссылаться на другие “подтверждающие блоки”, и возможность распараллеливания процесса, со смещением (трубопровод, “pipeline”). Но эти моменты не так важны для передачи основной идеи."

2 Likes