Введение
Блокчейн – это интегрированное решение сразу многих задач информатики, реализованное как единая общедоступная база данных, рассчитанная на постоянную дозапись, при этом прозрачная и поддающаяся криптографической проверке, работающая в распределенной и децентрализованной среде.
Мне много раз доводилось слышать, что технология блокчейна существует, а задачу, которая бы решалась с ее помощью – еще поискать. Я не согласен с такой оценкой, поскольку технологии и информатика, лежащие в основе блокчейна, приложимы на практике для решения повседневных инженерных задач. Один из вариантов использования блокчейна, сразу приходящий на ум – система верификации при управлении зависимостями.
Что, если бы мы хотели гарантировать следующее: всякий раз, когда мы вытягиваем код из VCS (системы контроля версий) этот код будет ровно одинаковым, независимо от того, когда мы его вытянем?
Рисунок 1
На рисунке 1 в упрощенном виде показан такой поток задач в системе, который помог бы нам убедиться, что код, вытягиваемый из системы – точно такой, как и в прошлый раз. Данная система состоит из базы данных, способной поддерживать хеш (значение) для любого репозитория в VCS по некоторой метке (ключу). Мы могли бы построить клиентский инструмент, позволяющий вытянуть код из VCS, хешировать код на диске, запросить значение хеша в базе данных, а затем сравнить два хеша, чтобы убедиться, что они одинаковы. Если ключа не существует, то система могла бы обратиться к VCS напрямую, добавить в базу данных новую запись и вернуть хеш.
Это блестящее решение, поскольку, если хотя бы один байт в коде изменится (с тех пор, как мы впервые вытянули код), то два хеша не совпадут, и мы будем знать, что кто-то что-то начудил с новой версией кода. Это возможно, поскольку разработчик может удалить метку, обновить код и повторно применить метку.
Такая система отлично подходит для индивидуального использования, так как мы сами себе доверяем и знаем, что с базой данных шутить нельзя. Но что, если бы мы хотели доверить работу с нашей системой кому-то другому? В таком случае нам потребовалось бы доказать две вещи:
Записи, уже имеющиеся в базе данных, никогда не обновляются. К базе данных можно применять только две операции: READ (чтение) и APPEND (дозапись).
Проверяемая база данных
Один из способов решить эту задачу – убедиться, что база данных проверяема. Иными словами, что любой сможет проверить, в самом ли деле никакие данные не менялись после того, как были добавлены в базу. Этого можно добиться криптографически.
Рисунок 2
На рисунке 2 показаны изменения, которые нужно внести в базу данных, чтобы сделать ее криптографически проверяемой. Можно было бы добавить два новых поля, которые представляли бы хеш предыдущей записи и номер записи. Хеш вычисляется для всех данных, представленных в каждой записи, поэтому, если изменится любая запись, то и хеш станет другим. Поскольку хеш каждой записи основан на хеше предыдущей записи, эти записи, в сущности, образуют цепочку. Чем выше по цепи та запись, которую вы хотите изменить, тем больше записей под ней также потребуется изменить, чтобы сохранить след криптографической проверки.
При наличии двух таких новых полей проверять базу данных можно когда угодно. Хеши могут производиться начиная с любой записи и проверяться до самого низа. Таким образом, пользователи смогут быть уверены, что мы ничего не нахимичили с базой данных.
Прозрачность
Итак, решение для проблемы с проверкой найдено, но теперь у нас есть проблема с прозрачностью. Система находится на нашем хостинге, поэтому другие, кто захотят ею пользоваться, будут вынуждены нам доверять. Ничто не мешает нам изменить базу данных и вручную поправить все хеши, чтобы с криптографической точки зрения база данных выглядела безукоризненно – а как нас раскусить?
В данном случае нам нужно реализовать в клиентском инструменте такую возможность: должен быть способ скачать себе копию базы данных и сравнить ее с той, что находится в продакшене. Важно, чтобы люди были спокойны и уверены: никаких махинаций в базе данных не происходит. Лучше всего, если вся база данных целиком им не потребуется. Они могут начать с любого места, если след криптографической проверки представляет собой цепочку. Просто им нужно дать возможность обновлять свою копию базы данных с течением времени, так, чтобы она оставалась актуальной.
Централизованное владение
Теперь, когда проблема с прозрачностью решена, что могут предпринять люди, если заметят, что мы изменили базу данных? Мы должны предоставить клиентам возможность перенести базу данных на их собственный хостинг. Никто не должен подвергаться рискам, возникающим, если всего один человек или одна компания владеет базой данных – и полностью ее контролирует. Так решается и еще одна проблема: мы устраняем единую точку отказа и избавляем других от необходимости полностью от нас зависеть, а себя – от необходимости покрывать все убытки собственными средствами.
Как вариант, можно попросить кого-то еще развернуть на собственном хостинге вторую базу данных, а потом поставить обе эти базы данных на балансировщик нагрузки вроде Caddy или расположить за шлюзовым API вроде KrakenD.
К сожалению, если мы так поступим, то базы данных рано или поздно рассинхронизируются.
Рисунок 3
На рисунке 3 показано, что может произойти между базами данных. Поскольку балансировщик нагрузки пытается равномерно распределить запросы между ними, у записей с разными номерами будут встречаться как различающиеся, так и одинаковые ключи.
Но эта проблема исчезает, если хеш-информация по заданному ключу будет одинакова в обеих базах данных. Правда, остается вероятность, что хеши для одного и того же ключа в двух базах данных будут отличаться. Взгляните на ops@v1.7.5 и посмотрите, как может отличаться значение хеша. Код для данной зависимости изменился в период между запросом к оригиналу базы данных и запросом к копии.
Какой вариант правильный? Технически – оба, но пользователю от этого не легче. В данном случае необходимо обеспечить избыточность, при которой любой мог бы обратиться как к первой, так и ко второй базе данных, и результаты таких обращений были бы одинаковы.
Жизнеспособность и репликация
Если у нас будет несколько версий базы данных, то нарушится согласованность, к которой мы так стремились. Значение любого конкретного ключа всегда должно быть одним и тем же, независимо от того, к какой базе данных обращается пользователь. Это непросто, так как мы хотим обеспечить во всех базах данных возможность считывать (READ) и прикреплять (APPEND) записи.
Мы могли бы выделить всего одну базу данных для прикрепления новых записей, а все прочие базы данных занять считыванием. Если в считывающей базе данных не окажется какого-то ключа, то она может отправить запрос в базу данных, прикрепляющую новые записи, и эта работа может быть выполнена там. Затем новая запись может быть реплицирована в других базах данных.
Рисунок 4
Но, если откажет база данных, отвечающая за прикрепление данных, то система умирает, так как в данном решении происходит централизация вокруг дозаписывающей базы данных, которая превращается в единую точку отказа. Одно из решений этой проблемы — избрать новую базу данных, которая будет прикреплять данные, но такое решение очень сложное. В частности, есть проблема: не гарантировано, что в момент выборов все считывающие базы данных будут синхронизированы.
Лучше всего было бы поддерживать децентрализованное решение, при котором каждая база данных могла бы как считывать, так и прикреплять данные. В таком случае система оставалась бы на плаву, даже если какая-нибудь база данных откажет. Чтобы реализовать систему, которая была бы так устроена, нам понадобилась бы пиринговая (P2P) сеть, в которой мы могли бы внедрить одноранговую репликацию.
Рисунок 5
На рисунке 5 представлена новая архитектура, в которой разные люди и объекты могут поддерживать, использовать и делить их собственную базу данных с широкой публикой. Такое решение обеспечивает жизнеспособность и децентрализацию, но, в то же время, ведется единая реплицируемая база данных.
Атомарная дозапись
Вырисовывается новый вопрос: как обеспечить идентичность всех баз данных, когда в разных локальных базах данных происходят разные операции дозаписи? При каждой дозаписи количество записей увеличивается на единицу, и это число привязано к следу криптографической проверки этой базы данных. Нам нужно найти способ реализовать атомарную запись сразу во всех базах данных в этой децентрализованной пиринговой сети.
Можно было бы в упрощенной форме реализовать протокол консенсуса, который координировал бы, какая база данных должна была бы выполнять следующую операцию дозаписи и синхронизировать эти дозаписи в рамках всей пиринговой сети до того, как произойдет следующая дозапись. Существует два популярных протокола консенсуса, на основе которых мы могли бы смоделировать нашу систему: доказательство выполнения работы (PoW) и доказательство полномочий (PoA).
Каковы достоинства и недостатки каждого из рассматриваемых здесь протоколов консенсуса?
Рисунок 6: Доказательство выполнения работы
Недостатки:
- Базам данных приходится конкурировать друг с другом за право довнести новую запись.
- Каждая база данных тратит энергию на эту конкуренцию, а мы не знаем, которая из них победит и когда.
- Отсутствует единообразная последовательность действий между следующими друг за другом операциями дозаписи в базу данных.
Достоинства
- Система остается на 100% децентрализованной.
Рисунок 7: Доказательство полномочий
Недостатки
- Требуется централизованная система регистрации, где узлы уполномочиваются на дозапись.
- Требуется, чтобы такой список уполномоченных узлов был известен всем остальным уполномоченным узлам.
- Требуется такой алгоритм выбора, который все уполномоченные узлы будут выполнять одновременно.
*Который при этом является детерминированным, так что узлы получают один и тот же ответ в каждый прогон, запланированный на определенное время.
*Который является случайным, чтобы все варианты выбора распределялись равномерно.
Достоинства
- Существует единообразная последовательность событий от одной дозаписи в базу данных до другой.
- Удается избавиться от тех растрат энергии, что происходят при доказательстве выполнения работы.
Выбор конкретного протокола консенсуса сводится всего к нескольким вещам.
- Хотим ли мы чистой децентрализацией, либо готовы мириться с некоторой степенью централизации?
- Модель с доказательством выполнения работы достаточно проста, но готовы ли мы мириться с ее расточительностью?
- Модель с доказательством полномочий энергоэффективна, но готовы ли мы мириться с ее добавочной сложностью?
Примечание: ценой еще большего усложнения мы могли бы избавиться в модели с доказательством полномочий от центральной регистрационной системы и выстроить вторую пиринговую сеть узлов, на уровне которой можно обрабатывать регистрацию, координацию и управление выбором.
Я обеими руками за упрощение, кроме тех случаев, когда сложность абсолютно необходимо. При этом, расточительность обязательно отразится на любой системе, как внутри нее, так и вне ее. Эти различные технические компромиссы сложны, поскольку однозначно верного решения не существует.
Ожидающие записи
Есть и еще одна проблема, существующая независимо от того, какой протокол консенсуса мы выберем. На достижение консенсуса всегда требуется некоторое время. Пока идет достижение консенсуса, новая запись, сгенерированная клиентом, должна оставаться в статусе ожидающей, а клиенту необходимо сообщить, что он не получит ответа до тех пор, пока эта ожидающая запись не будет официально добавлена в базу данных. Поэтому становится очень важно, с какой скоростью достигается консенсус.
Более того, клиенты, обращающиеся к разным базам данных, могут порождать множество ожидающих записей, пока идет достижение консенсуса. Эти ожидающие записи должны выдерживаться на перевалочном пункте, пока не начнется следующий раунд консенсуса. Можно добавить в нашу архитектуру пул памяти, в котором и будут храниться эти ожидающие записи.
Рисунок 8
И это еще не все. К этим ожидающим записям из пула памяти должен быть открыт общий доступ в рамках всей пиринговой сети, для обеспечения согласованности и надежности системы. Если мы выберем модель с доказательством выполнения работы, а эти ожидающие записи не будут разделяемыми, то такие ожидающие записи из пула памяти конкретной базы данных, возможно, так никогда и не дождутся дозаписи, поскольку эта база данных никогда не сможет выиграть в состязании. Если выбрать модель с доказательством полномочий, то пользователю придется ждать, пока алгоритм выбора не выберет конкретную базу данных.
Рисунок 9
Теперь, благодаря пулу памяти, можно эффективнее довносить и совместно использовать новые записи. Вместо того, чтобы отправлять по пиринговой сети одну запись за раз, а посылать целый пакет записей, исходя из того, что в данный момент хранится в пуле памяти.
Теперь, когда у нас готовы решения для децентрализованной пиринговой сети, когда ожидающие записи являются разделяемыми, есть протокол консенсуса, обеспечивающий атомарные операции записи, прозрачность, а сама база данных содержит след криптографической проверки, можно приступать к сборке и развертыванию системы. Большая часть инженерных и стратегических аспектов, которыми мы собираемся пользоваться, также задействованы в блокчейновых технологиях.
Какой в этом интерес
Мы нашли решения для технических проблем, но осталось решить и одну нетехническую. Как простимулировать людей на то, чтобы они хостили свою базу таким образом и открыли ее для всеобщего доступа? На эксплуатацию базы данных требуются время, деньги и самоотдача. Мы не можем рассчитывать, что люди перейдут на описанную парадигму по доброте душевной. Это настоящий слон в посудной лавке, поэтому обращаться с ним нужно с величайшей осторожностью.
Может быть, перспектива заиметь безопасный и долговечный исходный код – достаточный стимул. Хостинг базы данных может обойтись практически даром (если использовать доказательство полномочий). Если мы решим, что нам нужна чистая децентрализация и остановимся на доказательстве выполнения работы, то затраты на хостинг базы данных могут стать ощутимыми. Мы будем постоянно в большом количестве сжигать процессорное время.
Если мы выберем доказательство полномочий, то как помешать людям, которые соберутся добавить базу данных и заняться нехорошими делами? Им это ничего не будет стоить кроме символической суммы. Все это может стать для них забавой. Может быть, рассмотрим замену доказательства полномочий на доказательство доли владения (PoS) и потребуем от людей и компаний финансовых вложений за участие?
Как только в системе оказываются замешаны деньги, ситуация начинает катиться к чертям. Можно еще долго рассуждать о стимулах в контексте защиты сети от злоумышленников. Пожалуй, это тема для отдельной статьи.
Заключение
В этой статье было рассмотрено, как различные технологические аспекты блокчейна могут применяться для построения единой базы данных, рассчитанной только на запись, публично доступной, прозрачной и поддающейся криптографической проверке. Такая база данных могла бы работать в распределенной децентрализованной среде и использоваться для управления версиями исходного кода. Мы рассмотрели различные сопутствующие проблемы и компромиссы, на которые, возможно, потребуется пойти при создании такой базы данных.
Наконец, мы затронули вопрос возможных стимулов и поговорили о том, что вариант поощрения нужно выбирать очень аккуратно.
Комментарии (6)
AlexBream
30.08.2022 05:27+2Крайне неубедительный пример "полезного" использования, изобретение велосипеда с квадратными колесами.
Даже если забыть о том, что переписывание публичной истории - плохая практика (хотя ее очень любят гит-бои за "красивые репо в итоге, все кошерно-линейно"), то нужно помнить о том, что у каждого changeset-а уже есть свой (доступный видимый) хэш
You can obviously refer to any single commit by its full, 40-character SHA-1 hash
И при любом изменении данных changeset этот хэш тоже (сюрприз!) меняется, и простейшая проверка при использовании human-friendly адресации на неизменность хэша решает задачу, практически даром, без отягощения вот этим всем модным, но бесполезным
randomsimplenumber
30.08.2022 08:50разработчик может удалить метку, обновить код и повторно применить метку.
В некоторых VCS незаметно не прокатит. В mercurial, например, установка тега это тоже commit, его видно в истории. И, как уже заметили, есть commit id - берите и сравнивайте.
savostin
30.08.2022 20:55Придумали задачу и успешно и красиво ее решили.
Так и не понял какие реальные практические задачи могут потребовать такого решения.
MentalBlood
Для проверки базы не проще будет использовать подпись?
P.S. "перспектива заиметь безопасный и долговечный исходный код" — это обычно к тем кто пишет код, а не к тем кто его хранит )