Найти в Дзене
Галера Морева

Blockchain-разработка глазами Backend-разработчика

Всем доброго времени суток! Я достаточно давно занимаюсь Backend разработкой и последние несколько лет, все больше и больше пишу разные блокчейн проекты (Solidity на EVM). Погружение в блокчейн мне давалось непросто и мой бэкендерский мозг несколько раз ломался, и я решил поделиться своим взглядом на погружение в блокчейн-разработку. У этого поста, также, есть видео - версия: https://youtu.be/1Rw9zKaU0Mc Пост получился большой, поэтому начну с навигации: Дисклеймер: все описанное далее исключительно мое мнение. Могу ошибаться и ошибаюсь регулярно:) Блокчейн — очень крутая технология, которая реально может подвинуть наш мир немножко вперед. Но пока ей много кто пользуется для купи-продай-обмани-наварись. Я не буду и не планирую рассматривать крипту как актив. Да, есть куча разных роликов и постов, которые рассказывают про “вот, такая - то крипта сейчас может вырасти, такая крипта упала. Ребят, давайте инвестируем, закупаем...” Я вам про это ничего рассказывать не буду. Скажу лишь одно —
Оглавление

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

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

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

  1. Коротко про сам блокчейн, что это такое в моем понимании, и с чем я его ассоциирую.
  2. Особенности блокчейн-разработки глазами бэкенд-разработчика.
    Бэкендом занимаюсь уже около 10 лет и бэкендерскому мозгу было непросто изначально понять какие - то вещи в блокчейн-разработке.
  3. Основные термины.
    Как и в любой другой технологии стоит понимать базовую терминологию.
  4. Боли и неприятности.
    Проблема блокчейна в том, что там все завязано на деньги. Если я выкатил hello-world сервис в прод с уязвимостями, то я мало чем рискую. А hello-world проект в блокчейне, который идет в прод, уже связан с деньгами и риском их потерять. Я терял деньги — свои и клиентов и не хочу, чтобы теряли вы.
  5. Заключение

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

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

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

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

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

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

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

-2

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

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

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

  1. Если бэкендер опытный, то он точно запускал решения в прод
  2. Если он запускал в прод, значит знает как это запускается и знает, что бывает с продуктом под нагрузкой
  3. Если он держал сервисы под нагрузкой, то точно ловил даунтаймы и падения сервисов
  4. А если он ловил падения сервисов, то возможно их и поднимал.

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

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

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

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

-3

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

  • дорого
  • неудобно
  • непонятно зачем

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

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

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

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

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

-4

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

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

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

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

Теория

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

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

-5

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

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

-6

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

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

-7

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

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

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

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

-8

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

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

-9

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

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

-10

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

-11

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

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

-12

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

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

-13

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

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

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

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

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

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

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

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

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

  1. Написали код
  2. Запушил в гитлаб
  3. GitLab CI запускает тесты, все проверяет
  4. Если все ок, то CI начинает разворачивать новую версию приложения на сервере
-14

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

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

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

-15

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

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

-16

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

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

-17

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

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

-18

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

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

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

-19

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

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

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

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

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

-20

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

Если я отправил транзакцию с 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, для этой цели, придется хранить отдельно массив всех ключей и тогда, при необходимости, проходить по всем ним и по каждому ключу извлекать элементы из карты. Ну и на дополнительную запись в этот массив ключей и его инициализацию мы тоже тратим газ.

-21

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

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

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

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

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

-22

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

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

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

-23

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

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

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

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

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

-24

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

-25

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

-26

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

-27

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

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

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

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

-28

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

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

-29
  1. У нас есть Operator Contract. С нашего сервиса туда отправляется задача вида “сделай-ка мне запрос на этот сервер с такими-то параметрами”
  2. Контракт эмиттит событие (Event)
  3. На это событие подписывается отдельный бэкенд, извлекает информацию из события, где сказано “куда и с какими параметрами отправить запрос” и ответ “положи сюда в этот контракт”
  4. Сервер отправляет запрос с нужными параметрами, получает ответ
  5. Сервер отправляет ответ в нужный контракт (в анимации выше отправил в оператор контракт)
  6. Дальше происходит то, что должно происходить с этими данными.

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

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

-30

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

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

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

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

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

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

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

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

-31

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

-32

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

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

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

-33

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

-34

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

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

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

Upgradeable Contracts

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

  1. Выкладывается первая версия контракта (Contract V1)
  2. Выкладывается Proxy Contract и у него следующая задача
    Все запросы перебрасывать 1в1 на Contract V1
    Использовать СВОЁ хранилище, а от целевого контракта использовать только логику
  3. Дальше пользователь уже общается с прокси-контрактом также, как с основным
  4. Если необходимо обновить контракт, то админ
    деплоит Contract V2
    Через admin-contract говорит proxy-contract что теперь реализация находится на адресе Contract V2
  5. Дальше пользователь также общается с прокси и уже выполняются механики из Contract V2

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

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

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

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

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

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

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

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

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

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

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