Всем доброго времени суток! Я достаточно давно занимаюсь Backend разработкой и последние несколько лет, все больше и больше пишу разные блокчейн проекты (Solidity на EVM). Погружение в блокчейн мне давалось непросто и мой бэкендерский мозг несколько раз ломался, и я решил поделиться своим взглядом на погружение в блокчейн-разработку.

У этого поста, также, есть видео - версия: https://youtu.be/1Rw9zKaU0Mc

Пост получился большой, поэтому начну с навигации:

  1. Коротко про сам блокчейн, что это такое в моем понимании, и с чем я его ассоциирую.

  2. Особенности блокчейн-разработки глазами бэкенд-разработчика.
    Бэкендом занимаюсь уже около 10 лет и бэкендерскому мозгу было непросто изначально понять какие - то вещи в блокчейн-разработке.

  3. Основные термины.
    Как и в любой другой технологии стоит понимать базовую терминологию.

  4. Боли и неприятности.
    Проблема блокчейна в том, что там все завязано на деньги. Если я выкатил hello-world сервис в прод с уязвимостями, то я мало чем рискую. А hello-world проект в блокчейне, который идет в прод, уже связан с деньгами и риском их потерять. Я терял деньги — свои и клиентов и не хочу, чтобы теряли вы.

  5. Заключение

Дисклеймер: все описанное далее исключительно мое мнение. Могу ошибаться и ошибаюсь регулярно:)

Блокчейн — очень крутая технология, которая реально может подвинуть наш мир немножко вперед. Но пока ей много кто пользуется для купи-продай-обмани-наварись. Я не буду и не планирую рассматривать крипту как актив.

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

Скажу лишь одно — крипту для заработка стоит обходить стороной. Если вы разработчик, то лучше пробуйте зарабатывать как разработчик, не надо лезть в инвестиции. А если уж очень хочется в инвестиции, то не в крипту.

Про блокчейн и почему это интересно

Стоит начать с важного. Блокчейн — это не криптовалюта. Блокчейн - это технология, на которой построена криптовалюта, но называть криптовалюту блокчейном всё равно, что всю индустрию разработки называть словом “Javascript”. Да, вроде бы JavaScript - это частный случай разработки, но когда мы говорим про разработку, мы не имеем в виду именно JavaScript. Хотя есть люди, которые имеют в виду только JavaScript…

Идти в блокчейн за деньгами

Первое, что приходит в голову - это деньги. Блокчейн-разрабам платят довольно таки хорошо. Я лично сам открывал такие вакансии, сам лично откликался на подобные вакансии, где за такой же объем времени, проведенный в сутки за работой, можно получить больше, чем тому же backend-разрабу. Блокчейн-разработчики в стартапах, которые построены на базе блокчейна, на вес золота. Особенно хороший блокчейн-разработчик!

Что такое хороший БЧ-разработчик?

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

  1. Если бэкендер опытный, то он точно запускал решения в прод

  2. Если он запускал в прод, значит знает как это запускается и знает, что бывает с продуктом под нагрузкой

  3. Если он держал сервисы под нагрузкой, то точно ловил даунтаймы и падения сервисов

  4. А если он ловил падения сервисов, то возможно их и поднимал.

Опытность фэйлами не изменишь, но опыт фейловых ситуаций позволяет дать понять, что опыт имеется.

Тяжело стать хорошим бч-разработчиком, не потеряв деньги:

  • если с моего контракта еще не воровали деньги, значит я не запускал что - то с реальными деньгами (чтобы на контракте лежала хотя бы $1000)

  • если я не запускал что-то с реальными деньгами или запускал только на тестовых сетях (с фэйковыми деньгами), то я понятия не имею, что меня ждет в реальном токсичном мире блокчейна

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

Идти в блокчейн ради технологии

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

  • дорого

  • неудобно

  • непонятно зачем

А сейчас авиаотрасль — прекрасная часть нашей жизни, соединяющая людей по всей планете на расстоянии нескольких часов. Логистика сейчас на том уровне, на котором и не снилась самим братьям Райт! Весь мир живет иначе благодаря самолетам.

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

Но, увы, ассоциации со словом “блокчейн” достаточно скучны и однообразны:

  • биткоин

  • инвестиции

  • скам

  • эфир, рипл, {подставьте название монеты}

  • пузырь, который скоро лопнет

Ну и классический мем:

Мне вспоминаются слова великого умного человека - Менделеева, который сказал такую фразу:

"Сжигать нефть, это всё равно, что топить печку ассигнациями" Менделеев Д.И.

Если мы возьмём пачку денег бумажных, кинем в печку, печка хорошо разгорится, и деньги даже какое-то время будут давать тепло. Но это абсурд.

Так и с блокчейном. Использовать его только для денег и крипты — плохо, но другое пока не приживается… Одним из главных двигателей любого развития продукта являются деньги. Если есть на чем-то можно хорошенько и мощно заработать, то это "что-то" будет активно развиваться. И поэтому, пока что, на базе блокчейна, по-настоящему, живут финансовые проекты, которые базируются на том, чтобы деньги кому-то заработать, а кому-то потерять.

Теория

Децентрализация

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

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

Но в чем проблема централизованного сервиса? За этим централизованным сервисом есть какой-то владелец, да? Обычно какие-то крупные компании, холдинги, неважно, в нашем случае пусть будет один человек. Этот один человек может такое сказать: "А давайте-ка сделаем так, пусть Антон отправит 100 рублей, но при этом эти 100 рублей никто не получит. Мне они нужнее”.

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

Bitcoin, как раз-таки, и был изобретён для децентрализации управления деньгами.

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

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

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

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

Смарт-контракты?

В блокчейне можно создавать смарт-контракты на языке Solidity (в случае блокчейна на EVM). Смарт-контракт - это программа, которая выполняется в сети блокчейна. Он может содержать механизмы проверки, обработки ошибок и другие функции.

Опять же, в случае с комнатой где мы кричим команды, смарт-контракт - это я заранее каждому участнику в комнате передал код программы: как реагировать на мои команды, что проверять и что сохранять. И потом уже кричу “выполните программу с такими-то параметрами”. Дальше каждый уже исполняет инструкции.

Пример простого смарт-контракта - хранилище информации с функциями добавления и получения данных. Код контракта компилируется в байт-код и передаётся участникам блокчейна для выполнения.

Как обрабатывать те или иные запросы, которые будут отправлены к этому смарт-контракту? Если проводить аналогию с бэкендом, то это сервис, который может обрабатывать запросы POST и GET. POST сохраняет информацию. GET тут информацию, которую мы сохранили, передает обратно. Обычно так устроен любой бэкенд.

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

Например, пользователь 1 приходит, сохраняет контент (пост, например) через метод POST. Дальше приходит пользователь 2 и забирает этот контент методом GET. Пользователи знать не знают, где и как это лежит — для них бэк - это черный ящик.

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

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

Если сравнивать между собой блокчейн и бэкенд, то картина следующая:

  • в обычных сервисах мы пишем бесплатно, читаем бесплатно и зависимо

  • в блокчейне мы пишем платно, читаем бесплатно и независимо.

Например, есть Telegram с централизованной БД. Мы всегда к ней можем бесплатно обратиться и выкачать свои сообщения, фотки, видео и тд. Но если вдруг “вырубить” сервера телеграма, то нам все это будет недоступно.

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

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

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

В общем, базово, стоит иметь в виду — за каждый чих надо платить, если данные меняются. Кстати, деплой контракта — тоже запись в блокчейн и стоит недешево!

Деплой смарт-контракта

В мире бекенда я привык к примерно следующему жизненному циклу разработки фичи:

  1. Написали код

  2. Запушил в гитлаб

  3. GitLab CI запускает тесты, все проверяет

  4. Если все ок, то CI начинает разворачивать новую версию приложения на сервере

То есть мы привыкли работать так, и происходит это бесплатно. Хотя условно бесплатно, потому что за серверы мы всё-таки платим. А что же блокчейном?

В случае с блокчейном нам надо записывать новый код нашего “приложения” (смарт-контракта) в блокчейн. Выше я уже писал — за каждую запись нужно заплатить. Прежде чем делать транзакцию к своему смарт-контракту надо сделать транзакцию с размещением смарт-контракта.

Дальше уже сервер клиента\сервиса будет обращаться к какой-нибудь из нод для получения или сохранения информации в контракт.

Есть огромное количество нод, которые нужно оповестить — “ребята, вот байт-код контракта, алгоритмы которого надо делать при моих транзакциях”. Обязательно надо сделать так, чтобы на всех нодах, которые учатся блокчейне, появился один и тот же код, который будет выполняться одинаково, независимо от того, кто вызывает, как его вызывает. Механика будет одна и неизменна. И более того, нельзя допустить того, чтобы на какой-то из нод смарт-контракт был как-то изменён и работал по-другому.

Ниже пример транзакции, в рамках которой я деплоил достаточно давно контракт в сеть ETH

Это был тестовый контракт, который в бою так и не использовался. За его деплой было заплачено 200 долларов в эфирах. То есть мы еще ничего не сделали с этим контрактом — ни одного запроса, а 200 долларов уже потратили. Я до сих пор грущу, когда вспоминаю этот ошибочный деплой не того контракта…

На тему этого есть забавная картинка про CI в блокчейне.

Хранилище данных

Давайте поговорим про хранилище данных. Мы с вами все привыкли, что у нас на бэкенде есть PostgreSQL, MySQL, MongoDB, Redis и прочие другие сервисы, которые позволяют удобно работать с данными. В случае с блокчейном ничего подобного даже близко нет.

В блокчейне хранилище реализуется, как переменные в классе на других языках. То просто key-value или массивы. Тут нет реляционных таблиц с удобными связями и тд. Просто — пиши в переменную и радуйся.

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

Например, если мы хотим хранить не просто в массиве? А мы хотим информацию сохранять по ключу — для этого есть маппинг.

Знак доллара нарисован неспроста — за каждый set будет браться комиссия сети.

Расчет комиссии

Как всё-таки формируется комиссия? Почему я заплатил 200 долларов за то, чтобы залить какой-то контракт? Как эта комиссия расчитывалась?

Для этого мы вводим новый термин. Есть такая условная единица комиссии, как газ. GAS - это количество попугаев, в которых измеряются те или иные арифметические и не только операции. Каждая сложная операция состоит из ряда примитивных операций. Стоимость каждой примитивной операции описана в ETH Yellow Paper.

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

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

Если я отправил транзакцию с GP (Gas Price) 20, а все остальные отправляют за 30, то мою транзакцию никто не возьмет, пока желающих “покупать” GAS за 30 не станет заметно меньше. В итоге я либо жду, либо сдаюсь и ставлю цену 30. Таких как я становится много и появляются те, кто за скорость готов отдать 35 и так раз-за-разом.

В сети ETH (самая дорогая на момент сейчас) транзакция спокойно может провисеть несколько дней, чтобы залить контракт на 100-200 долларов дешевле. На заре эфира GP стоил реально копейки — за 3 рубля можно было залить контракт и быть довольным результатом. Потом 3 рубля стали 4-мя, 5-ю и теперь несколько сотен долларов, иногда улетают в молоко, ради деплоя контракта.

Для того, чтобы быть уверенным, что у пользователя есть деньги, которые могут быть потребованы за газ, с пользователя сразу списывается GAS LIMIT по тому GAS PRICE, который пользователь выбрал. Деньги блокируются и дальше возвращается сдача из расчета потраченного газа.

Важные моменты про Gas Limit:

  • Gas Limit можно установить любой при отправке

  • При отправке с кошелька «холдится» GasLimit*GasPrice

  • Майнер выполняет операцию, считает сколько ушло GAS

  • На одну и ту-же операцию может потребоваться разное кол-во газа

  • Умножает Gas на Gas price и забирает себе комиссию

  • Если во время выполнения газа начало уходить больше чем GasLimit:

    • Выполнения транзакции останавливается

    • Все изменения хранилища в рамках этой транзакции откатываются

    • Деньги за газ никому не возвращаются

Пример расчета комиссии

Вернемся к контракту, который просто хранилище данных.

  • На его деплой 173 000 GAS

  • Вызов set один раз стоит 50 000 GAS

  • На странице с gas price берем среднюю стоимость. Умножаем количество газа на эту цену

В итоге получаем 0.004 ETH или около 7 долларов за эти действия. А действия эти достаточно примитивны. А иногда цена за газ подскакивает так, что выходит не 7 долларов, а 100 долларов или ждать пока цена за газ упадет.

Боли и неприятности

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

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

Например, я привык, что мы легко могу пройтись по всем элементам чего угодно. Не важно — массив это или объект или карта. В Solidity, для этой цели, придется хранить отдельно массив всех ключей и тогда, при необходимости, проходить по всем ним и по каждому ключу извлекать элементы из карты. Ну и на дополнительную запись в этот массив ключей и его инициализацию мы тоже тратим газ.

Всякие удобные сортировки по ключам нам тоже недоступны. Ну либо доступны за газ…

Логгирование

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

Если в Typescript я привык просто написать console.log(a) и сразу получить в консоли вывод, то тут тоже есть console.log, который работает только при запуске в локальной среде разработки hardhat. И, что прекрасно, после того как я раздебажил что нужно, то перед деплоем контракта надо все эти логгирования удалять, потому что иначе контракт весит больше и дороже его деплой и на проде это вообще не будет работать.

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

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

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

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

Еще одна неприятная штука: в операции записи мы не можем получить информацию из нашей транзакции. Если мы делаем операцию, в которой происходит запись чего-либо в блокчейн (то есть платная транзакция), то return ничего не отдаст нашему сервису, который интегрируется с контрактом. Этот return работает только внутри самого контракта или во view (бесплатных) функциях.

Например, мы бы хотели, чтобы, когда мы добавляем новое значение в наш блокчейн, мы могли захотеть узнать размер хранилища после сохранения (скрин выше). То есть мы можем только через события выяснять, что именно было добавлено. А для этого надо выдернуть события, которые были вызваны внутри этой транзакции.

Работа со строками

Тут для меня был прям сюрприз — работать со строками нормально нельзя. Блокчейн не был создан для строк. Перейдем к примерам.

Код ниже отработает без проблем.

А этот код уже работать не будет:

Я уже давно привык нормально работать со строками, менять символы в строках, разрезать строки, конкатенировать их — всего этого из коробки нет. Также нет возможности вывести длину строки. То есть такой код не скомпилируется:

Если вам уж очень нужна длина строки, то можно пойти через конвертацию в байты и потом считать количество байт. Но проблема в том, что некоторые спецсимволы в байты конвертируются не 1в1. А некоторые просто не конвертируются и транзакция может упасть.

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

Вывод по строкам простой: со строками не работайте и не опирайтесь на строки внутри контракта. Если важно сохранить строки, то сохраняйте байты и опирайтесь на байты, а строки конвертируйте в байты уже на самом сервисе.

Проблема внешних вызовов

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

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

И банальная задача “получить текущую температуру на улице” становится чем-то невозможным. Если погода нам нужна далеко не всегда, то некоторые данные (вроде курса валют или текущего состояния какой-то внешней системы) бывают остро необходимы. Решение заключается в следующем подходе:

  1. У нас есть Operator Contract. С нашего сервиса туда отправляется задача вида “сделай-ка мне запрос на этот сервер с такими-то параметрами”

  2. Контракт эмиттит событие (Event)

  3. На это событие подписывается отдельный бэкенд, извлекает информацию из события, где сказано “куда и с какими параметрами отправить запрос” и ответ “положи сюда в этот контракт”

  4. Сервер отправляет запрос с нужными параметрами, получает ответ

  5. Сервер отправляет ответ в нужный контракт (в анимации выше отправил в оператор контракт)

  6. Дальше происходит то, что должно происходить с этими данными.

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

И, например, на все про все у нас уходит 50к газа на каждый этап. Мы запускаем транзакцию ставим 50к GAS LIMIT и думаем, что у нас будет хорошо. Но, например, механика сохранения новой погоды меняется — теперь при температуре выше 10 градусов нам нужно перевести деньги одному из участников. Логика расширяется и теперь на транзакцию уйдет, например, 80к газа.

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

Также нет нормального рандома, который нельзя предопределить. Этот рандом тоже предоставляется разными провайдерами “как есть” — просто в контракт регулярно пишется рандомное значение. Но доверять такому для реальных финансовых проектов — опасно.

Особого внимание заслуживает факт, что значение переменной block.timestamp задается майнером блока. Конечно сложно представить, что майнер будет заранее знать что именно он смайнит блок, и он может подменить время, но возможность такая гипотетически есть. Эта опасность актуальна в разрезе 15 секунд и если мы опираемся на минуты и большие временные промежутки, то этой проблемы нет.

Вопрос безопасности

Про безопасность много говорить не планирую. Но выделю важный аспект — в блокчейне видно всё и всем. Единственное, что недоступно другим — ваш приватный ключ (если вы его не спалили). Код смарт-контракта выкладывается на открытом виде для того, чтобы пройти аудиты и чтобы пользователи смарт-контракта могли ему доверять.

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

Иммутабельные переменные

Но даже если код контракта не предоставлен, его легко можно декомпилировать. Например, следующий код имеет иммутабельную переменную — она просто заменяется везде на константу в коде далее.

После деплоя этого контракта и открыв его через декомпилятор, мы видим следующее:

То есть это значение переменной мы сразу получаем.

Приватные переменные

Я привык, что в бэкенде я могу быть спокоен, что значение приватных переменных прочитать без доступа к памяти будет проблематично. Тут тоже самое — просто доступ к “памяти” есть у всех.

Мы обозвали переменную amount приватной. Деплоим контракт, и дальше простым сниппетом кода выдергиваем ее значение:

В итоге так можно вытаскивать, что угодно. Так что не вздумайте в контракте хранить хоть чего-нибудь чувствительное!

Деплой контрактов

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

Upgradeable Contracts

Поэтому приходится сразу писать все правильно и хорошо. Я так не умею, и поэтому я быстро пришел к интересному костылю — Upgradeable Contract. Их механика работает следующим образом.

  1. Выкладывается первая версия контракта (Contract V1)

  2. Выкладывается Proxy Contract и у него следующая задача

    1. Все запросы перебрасывать 1в1 на Contract V1

    2. Использовать СВОЁ хранилище, а от целевого контракта использовать только логику

  3. Дальше пользователь уже общается с прокси-контрактом также, как с основным

  4. Если необходимо обновить контракт, то админ

    1. деплоит Contract V2

    2. Через admin-contract говорит proxy-contract что теперь реализация находится на адресе Contract V2

  5. Дальше пользователь также общается с прокси и уже выполняются механики из Contract V2

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

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

Важный момент Upgradeable Contract

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

Небольшое заключение

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

Например, взять права. Сейчас я до сих пор с собой вожу бумажные права, чтобы показать их сотруднику ГИБДД и он, по водяным знакам, понял что эти права выдало действительно ГИБДД, а не я напечатал их себе на принтере.

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

На блокчейне можно построить систему, при которой отдельный участник сети (ГИБДД) записывает подпись факта “у Антона с такими то паспортными данными и тд., есть права категории B”. Не саму строку, а именно подпись. Подпись фиксированного размера и много месте не займет.

В начале рабочей смены сотрудник ГИББД выкачивает себе обновления в блокчейне (новые подписи), и дальше принимает от меня уже факт “я Антон с такими то данными и у меня есть категория B”, берет подпись этого факта из БЧ и понимает, что я действительно имею право ехать дальше.

Благодарю за внимание! Надеюсь, вам понравилось. Буду рад любой обратной связи. Если интересен контент от меня, то приглашаю в свой Telegram и Youtube.

Комментарии (20)


  1. x88
    04.09.2023 20:23
    -2

    Я не смог это дочитать.

    Микс "блокчейн для чайников и выдранные углубленные вещи" с информацией 2 летней давности. Начали про Events, перешли к оракулам, так и не упомянув этот термин. Приводится устаревший, до EIP-1559 механизм подсчета газа.


  1. vagon333
    04.09.2023 20:23

    Полны противоречий.

    Стоит начать с важного. Блокчейн — это не криптовалюта. Блокчейн - это технология ...

    И рядом:

    Проблема блокчейна в том, что там все завязано на деньги. Если я выкатил hello-world сервис в прод с уязвимостями, то я мало чем рискую. А hello-world проект в блокчейне, который идет в прод, уже связан с деньгами и риском их потерять.

    В вашей статье блокчейн привязан к крипте, хотя есть масса других областей использования блокчейн, не имеющих отношения к крипте.


    1. amorev Автор
      04.09.2023 20:23

      Увы, но действительно я лично не делал проектов в проде на БЧ не про деньги. Только делали тестовые сборки проекта по примеру того, что описал в конце статьи (децентрализованная идентификация).

      Я бы с радостью поделился бы этим опытом, если бы он был(

      А так я рад тому, что появляются проекты на БЧ без привязки к крипте


  1. splashx
    04.09.2023 20:23

    Если не сложно, опишите типовые задачи, которые решаются с помощью контрактов


    1. amorev Автор
      04.09.2023 20:23

      Увы, но сейчас с помощью EVM контрактов чаще решаются задачи сбора/раздачи денег. А можно решать задачу вроде той, что я описал в конце статьи.

      Лично я сам не писал ничего полезного на блокчейне, к сожалению. Спроса на это не видел.

      Если говорить про другие блокчейны, то на блокчейне есть проекты в РЖД - https://rzddigital.ru/technology/blokcheyn/, также S7 - https://habr.com/ru/companies/s7/articles/474122/. Но, увы, лично я с ними не общался


      1. splashx
        04.09.2023 20:23
        +1

        Именно такого ответа я и боялся) Инструмент в виде неизменяемого архива - отличная вещь (бумагу можно изменить и подписи с печатями поделать), но никто не придумал зачем это нужно кроме хайпа, спекуляций и манипуляций(


        1. amorev Автор
          04.09.2023 20:23

          Я вообще очень недоволен, что оно так. Но дальше "недовольства" уйти не смог, потому что являюсь клавиатурным героем)


        1. vagon333
          04.09.2023 20:23

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


          1. amorev Автор
            04.09.2023 20:23

            Хайп вообще зло. Надеюсь, все-же, найдется применение блокчейну кроме "купи-продай-обмани-проиграй"


          1. dph
            04.09.2023 20:23

            А зачем тут блокчейн, а не просто подпись?


            1. vagon333
              04.09.2023 20:23

              Потому что:
              - не все типы документов (600+) поддерживают цифровую подпись, а разработка стандарта цифровой подписи для каждого типа - длительный процесс;
              - создатель документа позже находит ошибки, делает правки и заново подписывает. Не разберешься, чья версия верна. И таких версий может быть несколько.


              1. dph
                04.09.2023 20:23

                А зачем типу документов поддерживать подпись? Подпись ставится сверху в любом подписанном контейнере, да хоть PGP.
                Если у создателя несколько подписанных документов - то они все верны, в чем проблема?


                1. vagon333
                  04.09.2023 20:23
                  +1

                  Если у создателя несколько подписанных документов - то они все верны, в чем проблема?

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


                  1. dph
                    04.09.2023 20:23

                    Так это не про достоверность обмена, а про актуальность предоставленной версии, но тут блокчейн тоже не спасет, так как если клиент не отправил документ, то откуда про него кто-нибудь узнает?
                    Это другой кейс вообще и, вообще говоря, не имеет решения вообще, нельзя клиента заставить всем отправлять актуальные данные.
                    Единый же для всех реестр, например, клиентских документов - не требует никакого блочейна, достаточно одной клиентской подписи.


                    1. vagon333
                      04.09.2023 20:23

                      ... но тут блокчейн тоже не спасет,

                      Спорное заявление.
                      По нашему опыту - спасет.

                      Нужен источник правды для каждого документа (Single Source of Truth).
                      Может быть централизованная база, но практика показала ущербность такого решения.
                      Может быть децентрализованная с консенсусом, например, FBA (Federated Byzantine Agreement) где ноды - участники обмена документами.


                      1. dph
                        04.09.2023 20:23

                        А при чем тут блокчейн?
                        1) В этот источник правды клиент должен свой документ поместить. И при этом достоверность документа начинает считаться как "поместил в источник правды" (что совсем не про "клиент взял и поменял данные"), но это ничем не отличается от "клиент обязан уведомить об изменениях".
                        И это не задача про "а
                        2) К этому источнику у всех должен быть доступ, причем авторизованный. Вариант "у всех есть вся база" довольно дорогой и довольно сложный при реализации авторизации

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


      1. dph
        04.09.2023 20:23
        +2

        Ну, задачу описанную в конце - проще решить без блокчейна. Там достаточно один раз подписи закрытым ключем и открытый ключ у полицейского.
        Собственно, почти все задачи блокчейна проще решить без него.


  1. mikegordan
    04.09.2023 20:23

    Не увидел как это масштабируется ? Внутри кода есть потоки ? если 1миллион пользователей вызовут 1 метод, они все будет последовательно по очереди обрабатываться ?


    1. dph
      04.09.2023 20:23

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


    1. amorev Автор
      04.09.2023 20:23

      все последовательно. Более того - если с одного адреса слать транзакции, то только поочереди. Одновременно один адрес может только одну транзакцию делать, а потом уже после нее следующую