Как мы сделали не blockchain

    Как с помощью smart-contract мы построили систему отбора лучших технологических проектов в ИТ МТС? И в какие «ловушки» мы попали, но смогли выбраться, доказав в итоге, что вести распределенный реестр на мобильных устройствах возможно!



    Для чего понадобилась система на основе blockchain?


    Начнем с самого начала. В МТС есть давняя традиция – выбирать лучший технологический проект, сделанный за год, и награждать его команду. Команда получает призы, уважение и славу. За долгие годы победителями становились различные проекты: от высоконагруженных телеком-систем до систем искусственного интеллекта.

    Выборы лучшего проекта всегда происходили в несколько этапов:

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

    Мы решили, что данная схема недостаточно прозрачна для участников и подумали: почему бы не дать возможность выбирать лучший технологический проект абсолютно всем экспертам в компании? 


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

    Мы прочитали несколько статей про blockchain, и идея построения системы распределенного реестра прочно осела у нас в головах. А что если и нам применить тут smart-contract?

    Нас привлекли следующие свойства:

    • открытость – нет единого сервера, где можно манипулировать информацией;
    • информация, помещенная в распределенный реестр, остается там навсегда;
    • информацию нельзя подделать (ну… практически)

    Не blockchain




    Сам blockchain применять для таких выборов не стоит. Но что, если взять протоколы для построения консенсуса в распределенных системах и применить их к построению консенсуса в человеческих отношениях?

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

    Какие альтернативы


    Самый известный протокол – это PAXOS. В нем отсутствует явный лидер, и все изменения проходят через двухфазный commit. Вначале каждого изменения происходит Propose. Если он прошел успешно, то посылается Accept (принятие изменений).


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

    Алгоритм много где применяется, например, в СУБД Cassandra. Данный протокол нам не понравился с точки зрения сложности его реализации под задачу. Но второй вариант нам подошел – это RAFT. Фактически это эволюция протокола PAXOS с явным лидером.

    Упрощенно протокол можно описать так:
    ·         строится сеть устройств, которые знают друг о друге;
    ·         устройства выбирают среди себя лидера, принимающего «важные решения» (например, о добавлении записи в реестр или изменении состава сети);
    ·         устройство-лидер отвечает за распределение информации по всей сети так, чтобы везде она была идентична;
    ·         как только лидер перестает справляться со своими обязанностями – выбирают нового лидера.

    Прочитать про протокол можно тут.

    Наша реализация


    Что же мы делаем и зачем миру еще один велосипед? 


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

    Давайте посмотрим, в какие «ловушки» мы попали, но смогли выбраться…

    Ловушка номер 1: «Мой адрес не дом и не улица»


    «Неожиданно» выяснилось, что для построения P2P-сети, реализующей распределенный реестр с применением протокола RAFT для репликации данных, каждое устройство может общаться друг с другом, а значит является одновременно и клиентом, и сервером. Поэтому нам потребуется публичный «белый» IP-адрес для каждого мобильного телефона (его может и не быть).

    Количество реальных IPv4 сильно ограничено, поэтому операторы связи применяют технологию NAT (Network Address Translation) в режиме PAT (Port Address Translation), транслируя несколько IP-адресов внутренней сети (которые и раздаются абонентам) в один внешний публичный IP-адрес. Таким образом, исключается возможность принимать входящие соединения из Интернет.

    Хорошая новость – IPv6 много! 


    У нас поддержка IPv6 включена в базовый пакет. Также все современные телефоны поддерживают IPv6, и оператор назначает абоненту публичный «белый» v6-адрес. Наш выбор — IPv6.

    Ловушка номер 2: Все пошли спать


    В отличие от серверов, мобильные телефоны все-таки иногда выключают. Мы обнаружили это при тестировании первого прототипа. Кроме того, Ipv6-адрес, выдаваемый оператором, публичный, но не статичный, каждая новая сессия связи — новый адрес. Адрес мобильного устройства может измениться в любой момент. И если в сети не останется ни одного телефона с известным нам адресом – она просто перестанет существовать (не к чему подключаться, чтобы ее «нарастить»). Поэтому нам пришлось в какой-то мере нарушить свое правило «никаких серверов». Мы сделали в облаке один специальный узел со статичным известным адресом. Его задача – помнить/актуализировать состав сети и не выключаться. То есть это обычный узел, просто с него никто не голосует, и, обратившись к нему, всегда можно получить актуальный список адресов всех участников сети.

    Ловушка номер 3: Идентификация и аутентификация 



    Надо было как-то решить задачу, чтобы голосовать за проекты могли не все, а те, кому это необходимо. Первая идея была такая: вести базу номеров телефонов экспертов. Но от нее отказались, поскольку не хотели давать приложению права на доступ к этой информации.
    В итоге сделали все просто: каждый голос, каждую запись в реестре решили снабжать цифровой подписью на модных эллиптических кривых, которая и будет определять подлинность записи. В корпоративной сети разместили WEB-сервис, который по доменной авторизации определял эксперта и генерировал для него уникальный QR-код с открытым и закрытым ключом шифрования (само собой, на клиентской стороне). Эксперт сканировал код из приложения и подключался. После чего на его телефон «накатывалась» текущая актуальная версия реестра и появлялась возможность проголосовать.

    Ловушка номер 4: Не Android единым 
 



    В ходе тестирования почти «внезапно» выяснилось, что некоторые пользователи являются владельцами небезызвестных моделей мобильных устройств, работающих под управлением операционной системы iOS. И стало понятно — программное обеспечение нашего реестра должно выполняться на разных платформах. Мы посмотрели в сторону языка программирования Kotlin, который не только «модный, стильный, молодежный», но еще и мультиплатформенный.

    Концепт мультиплатформенности в Kotlin подразумевает, что есть часть кода сommon и platform-specific, но поскольку ресурсы нашей команды ограничены, мы поставили перед собой одиозную задачу — использовать единую версию исходного кода под все платформы! Само собой, исполняемый модуль должен быть native под каждую платформу. Кotlin на это оказался способен.

    Сказано — сделано! Мы имеем один единственный SourceSet с исходным кодом, из которого собираем бинарники под все платформы (!), используя «фитчу» dependsOn. Круто? Очень круто!

    Ловушка номер 5: Мобильный трафик не бесплатный 



    Как же нам наиболее эффективно реализовать взаимодействие между узлами сети так, чтобы не потратить весь трафик абонента и не разрядить батарею мобильного устройства? Мы предполагаем, что сеть может состоять из 1000 и более устройств! Самый очевидный вариант — использовать UDP вместо TCP, например, в процедуре выбора «лидера» или при отправке Heartbeat-ов без данных. UDP более экономный, так как использует простую модель передачи данных, без «рукопожатий» и подтверждений. Отлично! Что еще? Конечно, асинхронный ввод-вывод!

    Внимательно читаем документацию по Kotlin Native.

    For all Unix or Windows based targets (including Android and iPhone) we provide the posix platform lib. It contains bindings to platform's implementation of POSIX standard.

    Затем так же внимательно читаем документацию стандарта POSIX и находим удивительную функцию, позволяющую обрабатывать события сокетов в неблокирующем режиме! Окунувшись с головой в удивительный мир корутин, сокетов и C Interop, мы смогли реализовать очень эффективный транспорт. Супер!

    А в каком же виде пересылать данные? 



    Конечно же CBOR!

    Компактный бинарный формат данных, который, по счастливой случайности, реализован в мультиплатформенной бибилиотеке kotlinx.serialization. Просто потрясно!

    Ловушка номер 6: Сериализация 



    На этот раз действительно неожиданно выяснилось, что kotlinx.serialization нет под androidNative (под androidJvm, конечно же, есть). Уважаемые коллеги из JetBrains подтвердили, что на данный момент они не собирают библиотеку под androidNative, и до выпуска Kotlin 1.4 в роадмап места под эту задачу уже нет. 


    Что же делать? Если гора не идет к Магомету, Магомет идет к горе!

    Мы сами собрали kotlinx.serialization под все платформы, в том числе под androidNative! Самое удивительное — все заработало! 


    Ловушка номер 7: Где хранить журнал? 



    Очевидно, в embedded key-value хранилище, но в каком? Мы выбрали libmdbx за компактность кода, скорость, мультиплатформенность, отсутствие WAL-файла. Эта библиотека разрабатывается ребятами из Positive Techlologies и берет начало из легендарной библиотеки LMDB от одного из авторов OpenLDAP Howard Chu. А та, в свою очередь, уходит корнями в реализацию B+tree от Martin Hedenfalk. Кстати, «из коробки» библиотека не собиралась под androidNative. Мы бережно собрали все ошибки, а авторы оперативно предоставили фиксы — за что им отдельная благодарность!

    Ловушка номер 8: C Interop 



    Собрать все это вместе оказалась весьма нетривиальной задачей. Кроме lmdbx и сокетов из posix мы интегрировали библиотеки для формирования\валидации цифровой подписи на эллиптических кривых и вычисления SHA256 с помощью удивительного механизма C Interop. Если простыми словами – из native приложения на Kotlin можно вызвать функцию C-библиотеки, в том числе с указателями на указатели и прочей магией, выглядит это все правда немного странно.

    Вот, например, вызов getaddrinfo с целью получения sockaddr.



    Как тебе такое Илон Маск?

    Линковка С-библиотеки в исполняемый файл Kotlin Native – это отдельный квест, который нам тоже удалось пройти, но не без «костылей». Мы динамически формируем def файл непосредственно в билд-скрипте грэдла, чтобы указывать правильный путь до библиотек относительно корневого каталога проекта и затем подставляем его (def файла) дескриптор в cinterops секцию. В самом же def файле определяется только абсолютный путь, который мало того что может иметь разный формат, если сборка выполняется под разными OS, но собственно на локальных машинах разработчиков, конечно, тоже может отличаться, что очевидно приводит к ошибке во время линковки.

    Про выборы


    Основные выборы мы проводили в течение суток. В тестировании с помощью нашей сети приняли участие чуть больше 20 экспертов. Оценивался 21 проект по 5 категориям, то есть всего в реестр было добавлено более 100 записей с голосами за проекты.

    Вывод


    В результате выполнения этого небольшого исследовательского проекта нам удалось доказать, что вести распределенный реестр на мобильных устройствах – возможно! Это открывает множество возможностей по использованию данной технологии на IoT-устройствах для организации вычислений по принципу Edge-computing. Впереди нас еще ждут испытания на нагрузку, уязвимость к атакам и на отказоустойчивость. Но мы верим, что у нас все получится!

    Авторы статьи: архитекторы и разработчики R&D Центра МТС Дмитрий Дзюба, Алексей Василенко и Семен Неврев
    МТС
    Компания

    Комментарии 14

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

      Вот эта тема совсем не раскрыта. Как вы в итоге защитились от случая, когда фэйковый девайс шлет одно и то же сообщение всем, а не каждому уникальное?
        +1
        Можно чуть подробнее про кейс который о котором вы спрашиваете?
        Попробуем чуть подробнее описать валидацию сообщений. Каждая запись в журнале имеет открытый ключ участника, который эту запись добавил, контрольную сумму записи, и цифровую подпись, сгенерированную закрытым ключом для [запись + контрольная сумма предыдущей записи этого участника]. То есть у нас получается не цепочка блоков, а цепочки записей каждого из участников. Тогда добавление записи в журнал выглядит примерно так: участник определяет контрольную сумму которую добавил именно он сам, формирует цифровую подпись, отправляет запись и подпись лидеру, лидер валидирует цифровую подпись, добавляет в свой локальный журнал, и рассылает ее фоловерам, каждый фоловер также валидирует цифровую подпись и добавляет к себе в журнал. Если подпись оказывается невалидной – запись просто обрезается до нулевого размера. Таким образом – добавить запись от имени другого участника только узнав его закрытый ключ
        –2

        да в мтс походу реально разрабы сидят без дела переизобретают велосипеды

          +1
          не переживайте, наши разработчики все успевают)
          +1

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


          2 фундаментальных проблемы:


          1. RAFT работает, пока все пиры соблюдают протокол. Злоумышленник может перехватить генерацию и как минимум фильтровать поступающие данные.
          2. RAFT подразумевает, что перечень пиров фиксирован и известен заранее всем пирам. Управление перечнем пиров происходит через управление конфигурацией сети. Динамическое добавление/удаление пиров может привести к появлению форков.
            0
            1. RAFT работает, пока все пиры соблюдают протокол. Злоумышленник может перехватить генерацию и как минимум фильтровать поступающие данные.

            Да, действительно такая проблема есть – если злоумышленник будет выбран лидером, он может фильтровать часть или все запросы на добавление в журнал от других участников. Исключить эту проблему полностью нельзя, но можно радикально минимизировать, ведь нам никто не запрещает всегда строго следовать протоколу RAFT, поэтому мы можем например каждые 10 минут принудительно инициировать выбор нового лидера, а в процессе выбора разрешить голосовать за кандидата, только если он не был выбран лидером в 10 последних голосованиях. Таким образом, если злоумышленник и окажется лидером, то на непродолжительный период времени, и случаться это будет редко.

            2.RAFT подразумевает, что перечень пиров фиксирован и известен заранее всем пирам. Управление перечнем пиров происходит через управление конфигурацией сети. Динамическое добавление/удаление пиров может привести к появлению форков.

            Как у нас реализовано добавление в кластер – чтобы новому участнику подключиться к кластеру нужно знать адрес хотя-бы одного действующего участника кластера, подключившись к нему, новичок сообщает свой адрес и получает список адресов всех активных участников, далее он повторяет данный шаг для всего только что полученного списка участников (причем на каждом шаге список может дополняться), до тех пор пока в списке не останется ни одного участника, с которым не было обмена адресами (все это происходит параллельно). Таким образом весь кластер достаточно быстро “узнает” адрес нового участника, а новый участник “узнает” адреса всех активных участников кластера. Как мы “выкидываем” из кластера “offline” участников – кроме адреса участника, мы также храним дату\время последней успешной коммуникации с ним, и если коммуникации не было слишком долго, мы с некоторый периодичностью начинаем отправлять ему PING-запросы, и если коммуникации не было совсем очень долго – просто удаляем такого участника из списка. Таким образом, если в качестве кванта времени для RAFT считать интервал между Heartbeat-ми (а у нас это секунды), то условие, что перечень пиров фиксирован и известен заранее всем пирам – вполне себе выполняется.
              0
              1. И что мешает злоумышленнику запустить 10 пиров для лидеров? 100 пиров? 1000? А учитывая IPv6 это будет физически одна машина, но с несколькими адресами. Проблема не в том, что лидером может стать злоумышленник. Проблема в том, что кто угодно в любой момент может провести перевыбор лидера и стать этим лидером.
              2. В такой схеме даже простой сбой сети может привести к форку, не говоря уже о злонамеренных атаках. В идеале список пиров синхронизируется средствами RAFT, чтобы все пиры в каждый момент времени оперировали строго одним и тем же списком пиров. Если не ошибаюсь, было видео от яндекса про RAFT (достаточно длинное видео с какого-то выступления), где ближе к концу упоминалась эта проблема и описывалось их решение.

              Мы немного по разному смотрим на проблемы RAFT. Я говорю о них как о фундаментальных — их не обойти различного вида ухищрениями. Если мат.модель позволяет атаку — значит сеть уязвима. Усложнить жизнь злоумышленника — да, можно. Но не защититься от атак полностью.


              Повторюсь, RAFT — очень крутой алгоритм. Он простой, он понятный, он быстрый. Но RAFT далеко не идеален.
              Он применим исключительно в закрытых сетях, где есть гарантии, что все соблюдают протокол взаимодействия. Фиксированный список пиров — это скорее особенность протокола, ее реально смягчить, но и полностью динамического списка пиров не получить.

                0
                «И что мешает злоумышленнику запустить 10 пиров для лидеров? 100 пиров? 1000?”

                Вы описываете атаку “51%”, когда злоумышленник получает контроль над большей частью ресурсов распределенной системы, и абсолютной защиты от этой атаки нет в принципе, ей подвержены все открытые сети.

                “А учитывая IPv6 это будет физически одна машина, но с несколькими адресами”.

                Все не так просто: один пир – это один уникальный IPv6 адрес, принадлежащий диапазону адресов мобильного оператора, иначе мы запрещаем подключение к кластеру, то есть один пир – одна SIM-карта и одно мобильное устройство. Но еще раз, атака 51% — это лишь вопрос наличия достаточных ресурсов, а не особенность математической модели, данной атаке подвержены все открытые сети, абсолютной защиты от нее не существует.

                “Проблема в том, что кто угодно в любой момент может провести перевыбор лидера и стать этим лидером”

                Даже если следовать классической версии алгоритма, это не совсем так, лидером может стать только участник имеющий версию журнала, наиболее актуальную для большинства участников. Но если алгоритм несколько расширить, например тем образом, о которым мы писали выше или как-то по другому, то выбирать в себя в лидеры просто так по желанию уже не получится.
                 
                “В такой схеме даже простой сбой сети может привести к форку, не говоря уже о злонамеренных атаках”

                Не совсем понятно о чем идет речь, “split-brain” или что-то еще? Если приведете конкретный кейс, с техническими деталями – будем признательны.

                “Если мат.модель позволяет атаку — значит сеть уязвима. Усложнить жизнь злоумышленника — да, можно. Но не защититься от атак полностью”

                Полностью согласны, более того, не существует абсолютно идеальной мат. модели, и соответственно абсолютно неуязвимой для атак сети. Успешная атака на любую существующую открытую сеть – вопрос приложенных усилий и средств, поэтому их защита строится на принципе, когда затрачиваемые ресурсы не окупаются полученной выгодой от атаки, что очевидно делает саму атаку бессмысленной.
                 
                На самом деле мы сейчас проводим некоторые исследования с целью расширения протокола RAFTдля защиты от “византийских” атак, и мы не одни движемся в этом направлении – поиск по ключевому слову “BFT Raft” выдает несколько достаточно интересных научных статей.
                  0
                  1. Причем здесь "атака 51%"? Я о том, что достаточно 1 измененного пира как минимум для остановки сети (если говорить о классическом RAFT). Небольшие изменения протокола принципиально ничего не меняют (1 пир/10 пиров — разница не принципиальна). Да, для атаки надо, чтобы пир был синхронизирован с остальной сетью. Но это существенное ограничение? Его сложно обойти?
                  2. Не сильно знаком с термином "split-brain". Я о том, что возможен форк истории блоков (если можно так сказать) даже сам по себе, а значит злоумышленник может ситуацию воспроизвести искусственно (и тогда можно говорить об "атаке 51%"), или воспользоваться моментом естественных проблем в сети (и тогда нужны гораздо меньшие усилия).
                    В рамках RAFT ситуация с форками никак не решается — потому как в RAFT ветвлений не должно происходить в принципе.
                    Если говорить о примере, то у меня очень мало данных о вашей сети. Тут возможно множество нюансов. Но если говорить о классическом RAFT — то там сложное управление списком пиров исключительно из-за того, что при пограничных ситуациях неаккуратное добавление нового пира может привести к форку: скажем пройдет выбор лидера с неполной историей. При этом пиры с полной историей могут выбрать своего лидера, в результате чего пойдет формирование уже двух историй. Это худший сценарий. Возможно, вся сеть просто остановится (на сколько помню, есть сценарии, когда при добавлении нового пира могут не пройти выборы нового лидера вообще). Понятное дело, что в общем случае этих проблем не будет — я говорю именно о пограничных условиях. Пограничные условия — это около 50% пиров активны, еще около 50% непонятно чем занимаются и добавляемый пир как раз меняет эти условные "51%/49%" на "51%/51%" (возможно как раз термин "split-brain" тут применим). К слову, при статичном списке пиров это невозможно в принципе — RAFT просто остановится, пока не соберет кворум в сети.

                  "BFT Raft" — это хорошо, но это пока на уровне идей? Есть рабочий алгоритм? Есть открытый блокчейн на нем? После всех изменений в "BFT Raft", сколько в нем от оригинального RAFT?


                  RAFT интересен в первую очередь своей простотой. Он крайне простой, он понятный для человека (а это крайне важно). При этом RAFT очень быстрый (если сеть справится с потоком данных от лидера).
                  Но за все приходится платить — для RAFT платой стала область применения — исключительно закрытые сети (справедливости ради надо сказать, что он и не предназначался никогда для открытых сетей). Поэтому на RAFT, на сколько мне известно, нет открытых блокчейнов.


                  P.S. причина появления оригинального комментария в том, что в самой статье нет ни одного упоминания о проблемах RAFT. Причем, на мой взгляд, RAFT в принципе не подходит для указанного применения. Я хочу, чтобы у читателя складывалась полная картина об алгоритме.


                  Повторюсь — описанные мной проблемы, это фундаментальные проблемы RAFT, возникающие исключительно при использовании протокола RAFT в открытой сети. Эти проблемы очень легко воспроизвести (1 атакующий пир) или они могут произойти сами по себе (в результате временного разделения сети на изолированные сегменты).
                  Да, проблемы можно немного ослабить тем или иным "костылем". Но это не решает их полностью. Если же они будут решены полностью — то это будет уже не RAFT.
                  Например, если от RAFT останется принцип "следуй за лидером", а сам лидер будет назначаться по другому.


                  Для закрытых сетей описанных проблем нет. Все пиры по определению строго соблюдают протокол синхронизации. Нет проблемы с изменением перечня пиров, если придерживаться простого принципа — все операции над перечнем пиров можно производить только при полном кворуме в сети (т.е. 100% пиров активны и полностью синхронизированы). Это несколько избыточный, но зато достаточно простой принцип.


                  P.P.S. на сколько вижу, R&D Центр МТС прекрасно понимает описанные проблемы. Но почему-то в статье их упустил… Как понимаю, не все ловушки удалось обойти...


                  В общем дальнейший диалог считаю бессмысленным. Я говорю, что RAFT тут не подходит, причем совершенно не подходит. Вы говорите, что "RAFT + подпорки — и все ОК". ОК, с вас полное описание всех "подпорок", чтобы можно было конструктивно обсудить квест по натягиванию совы на глобус (и можно ли после всего результат назвать RAFTом?).


                  Ну или как вариант — вы реально применили чистый RAFT в открытой сети… Хотя "местное голосование" — это ни разу не открытый враждебный мир… Но тогда хочется привести слова Пушкина:


                  О сколько нам открытий чудных
                  Готовят просвещенья дух
                  И опыт, сын ошибок трудных,
                  И гений, парадоксов друг,
                  И случай, бог изобретатель.
                    0
                    «Но если говорить о классическом RAFT — то там сложное управление списком пиров исключительно из-за того, что при пограничных ситуациях неаккуратное добавление нового пира может привести к форку: скажем пройдет выбор лидера с неполной историей»

                    Как нам кажется, Вы ссылаетесь на раздел «6 Cluster membership changes» вот этого описания протокола raft.github.io/raft.pdf. Мы не зря в самом первом ответе писали про таймауты и квант времени: в данной статье в качестве значения electionTimeout используются миллисекунды, а конфигурация узлов описана примерно так «нужно остановить все узлы, поправить конфигурацию и запустить, и лучше не делать это вручную, так как если запуститься в процессе конфигурации запуститься процедура выбора лидера (интервал которой напомним предполагается от 10-500 мс), то есть вероятность, что случится что-то страшное». Очевидно здесь предполагается, что время, необходимое для конфигурации кластера сопоставимо либо намного больше значения electionTimeout, действительно в этом случае возможен выбор лидера когда кластер находится в каком-то промежуточном состоянии. Мы же значение electionTimeout установили более 10 секунд (на порядки больше чем в статье!), а добавление единичного узла у нас выглядит так – одновременно всем узлам рассылается команда, которая: останавливает таймер election, добавляет новый узел в список узлов, запускает таймер election. Время выполнения этой команды –  примерно миллисекунды, ну либо десятки миллисекунд. То есть в нашем случае, время конфигурации кластера на несколько порядков(!) меньше значения electionTimeout, и вероятность инициации выбора лидера в процессе конфигурации стремится к нулю. Само собой мы многократно проверяли данный механизм и на стенде, и на «бою», то есть мониторили состояние кластера в течение всего процесса голосования пользователями на мобильных устройствах, и его корректная работоспособность полностью подтвердилась.
                     
                    «В рамках RAFT ситуация с форками никак не решается — потому как в RAFT ветвлений не должно происходить в принципе»
                     
                    Даже если обратиться к «классическому» алгоритму, это не совсем так, в том же документе выше вполне ясно описана процедура разрешения конфликтов в журнале (форков\ветвлений, назвать можно как угодно) «If an existing entry conflicts with a new one (same index but different terms), delete the existing entry and all that follow it (§5.3)» Само собой в рамках тестов нашей реализации мы не раз «соединяли» в один кластер множество узлов у которых журналы отличались начиная с определенного элемента или даже полностью. Вполне ожидаемо, лидер всегда выбирался из большинства узлов с одинаковым журналом, и успешно реплицировал его меньшинству, замещая их версии, соблюдая тем самым наше основное требование – у всех участников единая копия журнала, а возникновение кратковременных «форков» для нас не является критичным (кстати, такая известная «открытая» блокчейн-сеть как «Bitcoin» допускает «форки» и ситуация с ними никак не решается, позволяя тем самым успешно проводить такие атаки, как например «Double-spending», но тем не менее она все-таки «подходит»).
                     
                    В любом случае спасибо за интересную дискуссию и предоставленную информацию, мы ее обязательно учтем.
                      0

                      Мы немного по разному смотрим на проблемы…
                      Вы говорите о том, что вероятность возникновения проблем ничтожно мала.
                      Для меня же сам факт наличия подобной вероятности является проблемой. Какая бы вероятность не была — если проблема теоретически возможна, то ее следует устранить. Законы Мерфи еще ни кто не отменял… А ручной старт распределенного сервиса после рассинхронизации — удовольствие крайне сомнительное даже в закрытых сетях… А уж в открытых, тем более если говорить о IoT устройствах...


                      Что касается форков…
                      Да, в классических блокчейнах форки — это норма жизни. Но там о них знают, там о них помнят, там их учитывают.


                      RAFT же допускает форки исключительно в неподтвержденной (незакоммиченной) части истории. Они решаются достаточно просто — "следуй за лидером и не парься".
                      При этом RAFT дает гарантию, что закомиченная запись не откатится никогда!


                      RAFT тем и крут (помимо прочего) — закомиченная часть не откатывается, закомиченным данным сервиса можно полностью доверять! Базы данных не зря зачастую именно RAFT используют! Атаки вида "double-spending" невозможны в принципе!


                      А Вы готовы дать подобную гарантию?

            0
            Молодцы, было интересно почитать. Вспомнился сериал Кремниевая долина)
            А подскажите какие-нибудь материалы по теме распределённого реестра на мобильных устройствах?

            Это открывает множество возможностей по использованию данной технологии на IoT-устройствах...
            Можете привести несколько конкретных примеров?
              0
              «А подскажите какие-нибудь материалы по теме распределённого реестра на мобильных устройствах?»

              Мы подобных материалов найти не смогли, так что будем рады любой информации.

              «Это открывает множество возможностей по использованию данной технологии на IoT-устройствах…

              Можете привести несколько конкретных примеров?»

              В качестве примера могут подходить любые задачи, требующие обмена информацией между распределенными узлами сети. Например, если подключить все автомобили в единую сеть, то можно строить единую карту дорожной обстановки основываясь на камерах/сенсоров участников сети. При этом, поскольку такая карта нужна локально (для участников движения, находящихся по близости) то передавать ее в центр обработки данных и потом скачивать обратно – не эффективно. Удобнее создавать ее с помощью локальных кластеров. А саму карту можно использовать, например, как еще один канал получения информации о дорогах для самодвижущихся автомобилей. Кстати, это вполне реальная задача, которую пытается решать Intel в своем подразделении Mobileye.
                0

                Пожалуйста, поправьте в статье: libmdbx или MDBX, но не lmdbx.
                И если вас не затруднит, то добавьте "mdbx" в теги.

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                Самое читаемое