Blockchain-разработка глазами Backend-разработчика
Всем доброго времени суток! Я достаточно давно занимаюсь Backend разработкой и последние несколько лет, все больше и больше пишу разные блокчейн проекты (Solidity на EVM). Погружение в блокчейн мне давалось непросто и мой бэкендерский мозг несколько раз ломался, и я решил поделиться своим взглядом на погружение в блокчейн-разработку.
Пост получился большой, поэтому начну с навигации:
- Коротко про сам блокчейн, что это такое в моем понимании, и с чем я его ассоциирую.
- Особенности блокчейн-разработки глазами бэкенд-разработчика. Бэкендом занимаюсь уже около 10 лет и бэкендерскому мозгу было непросто изначально понять какие - то вещи в блокчейн-разработке.
- Основные термины. Как и в любой другой технологии стоит понимать базовую терминологию.
- Боли и неприятности. Проблема блокчейна в том, что там все завязано на деньги. Если я выкатил hello-world сервис в прод с уязвимостями, то я мало чем рискую. А hello-world проект в блокчейне, который идет в прод, уже связан с деньгами и риском их потерять. Я терял деньги — свои и клиентов и не хочу, чтобы теряли вы.
- Заключение
Дисклеймер: все описанное далее исключительно мое мнение. Могу ошибаться и ошибаюсь регулярно:)
Блокчейн — очень крутая технология, которая реально может подвинуть наш мир немножко вперед. Но пока ей много кто пользуется для купи-продай-обмани-наварись. Я не буду и не планирую рассматривать крипту как актив.
Да, есть куча разных роликов и постов, которые рассказывают про “вот, такая - то крипта сейчас может вырасти, такая крипта упала. Ребят, давайте инвестируем, закупаем...” Я вам про это ничего рассказывать не буду.
Скажу лишь одно — крипту для заработка стоит обходить стороной. Если вы разработчик, то лучше пробуйте зарабатывать как разработчик, не надо лезть в инвестиции. А если уж очень хочется в инвестиции, то не в крипту.
Про блокчейн и почему это интересно
Стоит начать с важного. Блокчейн — это не криптовалюта. Блокчейн - это технология, на которой построена криптовалюта, но называть криптовалюту блокчейном всё равно, что всю индустрию разработки называть словом “Javascript”. Да, вроде бы JavaScript - это частный случай разработки, но когда мы говорим про разработку, мы не имеем в виду именно JavaScript. Хотя есть люди, которые имеют в виду только JavaScript…
Первое, что приходит в голову - это деньги. Блокчейн-разрабам платят довольно таки хорошо. Я лично сам открывал такие вакансии, сам лично откликался на подобные вакансии, где за такой же объем времени, проведенный в сутки за работой, можно получить больше, чем тому же backend-разрабу. Блокчейн-разработчики в стартапах, которые построены на базе блокчейна, на вес золота. Особенно хороший блокчейн-разработчик!
Что такое хороший БЧ-разработчик?
Вряд ли можно стать хорошим backend-разработчиком, ниразу не уронив и не починив прод. Возможно, я просто неудачник и учусь только через негативный опыт, но у меня такая теория:
- Если бэкендер опытный, то он точно запускал решения в прод
- Если он запускал в прод, значит знает как это запускается и знает, что бывает с продуктом под нагрузкой
- Если он держал сервисы под нагрузкой, то точно ловил даунтаймы и падения сервисов
- А если он ловил падения сервисов, то возможно их и поднимал.
Опытность фэйлами не изменишь, но опыт фейловых ситуаций позволяет дать понять, что опыт имеется.
Тяжело стать хорошим бч-разработчиком, не потеряв деньги:
- если с моего контракта еще не воровали деньги, значит я не запускал что - то с реальными деньгами (чтобы на контракте лежала хотя бы $1000)
- если я не запускал что-то с реальными деньгами или запускал только на тестовых сетях (с фэйковыми деньгами), то я понятия не имею, что меня ждет в реальном токсичном мире блокчейна
- если я не знаю, что меня ждет, то я основательно обожгусь при первом запуске и тут вопрос команды/компании, которая готова взять на себя риск быть первым плательщиком за мой косяк.
Про блокчейн сейчас я скажу тоже самое — это дорого, неудобно и непонятно зачем. Пока не погрузился в бч-разработку для меня действительно это выглядело чем-то бесполезным для обмана инвесторов (=стрижки хомяков). Но если посмотреть на это с другой стороны — это возможность децентрализованно хранить любые факты без возможности их подмены. “без возможности подмены” — важная деталь.
Но, увы, ассоциации со словом “блокчейн” достаточно скучны и однообразны:
- биткоин
- инвестиции
- скам
- эфир, рипл, {подставьте название монеты}
- пузырь, который скоро лопнет
Мне вспоминаются слова великого умного человека - Менделеева, который сказал такую фразу:
"Сжигать нефть, это всё равно, что топить печку ассигнациями" Менделеев Д.И.
Если мы возьмём пачку денег бумажных, кинем в печку, печка хорошо разгорится, и деньги даже какое-то время будут давать тепло. Но это абсурд.
Так и с блокчейном. Использовать его только для денег и крипты — плохо, но другое пока не приживается… Одним из главных двигателей любого развития продукта являются деньги. Если есть на чем-то можно хорошенько и мощно заработать, то это "что-то" будет активно развиваться. И поэтому, пока что, на базе блокчейна, по-настоящему, живут финансовые проекты, которые базируются на том, чтобы деньги кому-то заработать, а кому-то потерять.
Теория
Децентрализация
В чем отличие централизованного от децентрализованного сервиса? Давайте сначала рассмотрим централизованный. Есть я и еще кто-то, и мы решили сделать между нами сервис. Пусть это будет банк или вообще любой другой сервис, для того, чтобы мне, другому человеку, чего-то через сервис передать.
Централизованные сервисы имеют своих владельцев. Проблема заключается в том, что владелец может принимать негативные решения, забирая деньги. Причем это может быть не только “забрать деньги себе”. Например, можно написать “у нас есть в банке 100500 рублей” и надеяться, что все вкладчики не пойдут за этими деньгами… как это было с SVB и другими погибшими недавно банками.
Bitcoin, как раз-таки, и был изобретён для децентрализации управления деньгами.
Если сравнивать между собой блокчейн и бэкенд, то картина следующая:
- в обычных сервисах мы пишем бесплатно, читаем бесплатно и зависимо
- в блокчейне мы пишем платно, читаем бесплатно и независимо.
Например, есть Telegram с централизованной БД. Мы всегда к ней можем бесплатно обратиться и выкачать свои сообщения, фотки, видео и тд. Но если вдруг “вырубить” сервера телеграма, то нам все это будет недоступно.
Для того чтобы виртуальная машина EVM выполнила какую-то команду смарт-контракта, в которой предусмотрена запись информации в блокчейн, то мы должны заплатить. Она выполняет какие-то расчеты, складывает что-то, умножает, перемножает, и в итоге появляется новый артефакт в хранилище блокчейна, который обновляется на всех нодах, участвующих в блокчейне.
Любой участник сети может запустить себе полную ноду, куда будет закачаны сотни гигабайт данных блокчейна и работать с ними локально. А можно пользоваться легковесной версии ноды, которая не будет хранить в себе весь блокчейн, но через нее можно будет обращаться к полноценным нодам в сети и извлекать нужную информацию.
Идея в том, что каждая запись в блокчейн представляет собой блок, в котором собрана пачка транзакций, в которых происходят изменения состояния блокчейна. Каждый следующий блок зависит от предыдущего цепочкой на основании алгоритмов хэширования.
В общем, базово, стоит иметь в виду — за каждый чих надо платить, если данные меняются. Кстати, деплой контракта — тоже запись в блокчейн и стоит недешево!
Деплой смарт-контракта
В мире бекенда я привык к примерно следующему жизненному циклу разработки фичи:
- Написали код
- Запушил в гитлаб
- GitLab CI запускает тесты, все проверяет
- Если все ок, то CI начинает разворачивать новую версию приложения на сервере
Логгирование
Также неприятно дела обстоят с логгированием. Дебажить я привык через дебаггер в среде разработки, но тут стоит забыть даже про нормальное логгирование.
Если в Typescript я привык просто написать console.log(a) и сразу получить в консоли вывод, то тут тоже есть console.log, который работает только при запуске в локальной среде разработки hardhat. И, что прекрасно, после того как я раздебажил что нужно, то перед деплоем контракта надо все эти логгирования удалять, потому что иначе контракт весит больше и дороже его деплой и на проде это вообще не будет работать.
В итоге получается, что когда мы запустили проект уже в бой, мы хотим увидеть что не так, мы не можем увидеть, что пошло не так. Но мы можем увидеть, что пошло так. Есть система событий внутри смарт-контрактов. Вот, допустим, пример: мы хотим иметь событие того, что был добавлен новый элемент под таким индексом с таким-то значением.
Мы внутри метода set этот вызываем это событие и логи эти мы можем увидеть только при успешном выполнении. Если что-то пошло не так, или у вас там были множественные вызовы контрактов, если у нас транзакция упала, то логи тоже не сохранились, поскольку информация в блокчейне откатывается назад.
Если у вас произошло событие и после него упало в простом контракте, то тут информация в эксплорере будет видна.. Но в случае, если вас используется цепочки из нескольких контрактов, и допустим у вас есть в первом контракте вызвались одни события, потом вызывается второй контракт, который вызывает другие события, и потом все падает то, что было вызвано внутри второго контракта, будет удалено точно полностью раз и навсегда.
Надо быть очень внимательным, когда мы хотим логгировать происходящее внутри блокчейна, и иметь в виду то, что нормальное логирование, которое мы привыкли, нам здесь попросту не доступно.
Еще одна неприятная штука: в операции записи мы не можем получить информацию из нашей транзакции. Если мы делаем операцию, в которой происходит запись чего-либо в блокчейн (то есть платная транзакция), то return ничего не отдаст нашему сервису, который интегрируется с контрактом. Этот return работает только внутри самого контракта или во view(бесплатных) функциях.
Например, мы бы хотели, чтобы, когда мы добавляем новое значение в наш блокчейн, мы могли захотеть узнать размер хранилища после сохранения (скрин выше). То есть мы можем только через события выяснять, что именно было добавлено. А для этого надо выдернуть события, которые были вызваны внутри этой транзакции.
Работа со строками
Тут для меня был прям сюрприз — работать со строками нормально нельзя. Блокчейн не был создан для строк. Перейдем к примерам.
Код ниже отработает без проблем.
В итоге можно написать контракт, который работает со строками и проверить на обычных строках. А потом прилетит строка, которую не обработается и все будет падать или длина строки будет считаться неверно из-за особенных символов.
Вывод по строкам простой: со строками не работайте и не опирайтесь на строки внутри контракта. Если важно сохранить строки, то сохраняйте байты и опирайтесь на байты, а строки конвертируйте в байты уже на самом сервисе.
Проблема внешних вызовов
Следующая сложность, которая является продолжением основной фичи блокчейна — изолированность. Все данные, которые находятся в блокчейне, рождаются внутри блокчейна или же передаются ему из-вне. Но сам блокчейн никогда не сможет стучаться во внешний мир — только в другие контракты.
- У нас есть Operator Contract. С нашего сервиса туда отправляется задача вида “сделай-ка мне запрос на этот сервер с такими-то параметрами”
- Контракт эмиттит событие (Event)
- На это событие подписывается отдельный бэкенд, извлекает информацию из события, где сказано “куда и с какими параметрами отправить запрос” и ответ “положи сюда в этот контракт”
- Сервер отправляет запрос с нужными параметрами, получает ответ
- Сервер отправляет ответ в нужный контракт (в анимации выше отправил в оператор контракт)
- Дальше происходит то, что должно происходить с этими данными.
Получается такая длинная цепочка. Печаль истории в том, что деньги забираются при моем первом запросе вида “а сходи за мне по такому запросу” и на втором запросе, который уже делает сервер, выполнивший запрос.
И, например, на все про все у нас уходит 50к газа на каждый этап. Мы запускаем транзакцию ставим 50к GAS LIMIT и думаем, что у нас будет хорошо. Но, например, механика сохранения новой погоды меняется — теперь при температуре выше 10 градусов нам нужно перевести деньги одному из участников. Логика расширяется и теперь на транзакцию уйдет, например, 80к газа.
В итоге, уже на второй транзакции, вся цепочка рушится из-за нехватки газа на операцию. Такой огород вокруг внешних вызовов усложняет подобные проекты. Скорее всего, если у вас жесткая завязка на внешний мир, то вам и не стоит выбирать блокчейн для проекта.
Также нет нормального рандома, который нельзя предопределить. Этот рандом тоже предоставляется разными провайдерами “как есть” — просто в контракт регулярно пишется рандомное значение. Но доверять такому для реальных финансовых проектов — опасно.
Особого внимание заслуживает факт, что значение переменной block.timestampзадается майнером блока. Конечно сложно представить, что майнер будет заранее знать что именно он смайнит блок, и он может подменить время, но возможность такая гипотетически есть. Эта опасность актуальна в разрезе 15 секунд и если мы опираемся на минуты и большие временные промежутки, то этой проблемы нет.
Вопрос безопасности
Про безопасность много говорить не планирую. Но выделю важный аспект — в блокчейне видно всё и всем. Единственное, что недоступно другим — ваш приватный ключ (если вы его не спалили). Код смарт-контракта выкладывается на открытом виде для того, чтобы пройти аудиты и чтобы пользователи смарт-контракта могли ему доверять.
Процедура аудита — нанимается компания, которая смотрит код контракта и проверяет, что именно этот контракт выложен под этому адресу. Проверяется вопрос безопасности контракта и того, что он выполняет то, что декларируется разработчиками. Дальше компания-аудитор размещает у себя на сайте информацию вида “этот контракт был нами верифицирован — может верить”
Иммутабельные переменные
Но даже если код контракта не предоставлен, его легко можно декомпилировать. Например, следующий код имеет иммутабельную переменную — она просто заменяется везде на константу в коде далее.
Небольшое заключение
На этом мой пост подходит к концу. В блокчейне много болей, но возможность децентрализировать хранение данных и выполнение операций, иногда того стоят. Например, на блокчейне можно построить удобное хранение данных, подтверждающих право доступа.
Например, взять права. Сейчас я до сих пор с собой вожу бумажные права, чтобы показать их сотруднику ГИБДД и он, по водяным знакам, понял что эти права выдало действительно ГИБДД, а не я напечатал их себе на принтере.
Казалось бы — почему бы ему онлайн не проверять, что у меня есть право ехать на этой машине? А онлайн есть далеко не везде и на дорогах, зачастую, интернета нет вообще или есть ужасно медленный. Поэтому пока гаишники опираются на глаза и знания водяных знаков, чтобы понять наличие у меня открытой категории.
На блокчейне можно построить систему, при которой отдельный участник сети (ГИБДД) записывает подпись факта “у Антона с такими то паспортными данными и тд., есть права категории B”. Не саму строку, а именно подпись. Подпись фиксированного размера и много месте не займет.
В начале рабочей смены сотрудник ГИББД выкачивает себе обновления в блокчейне (новые подписи), и дальше принимает от меня уже факт “я Антон с такими то данными и у меня есть категория B”, берет подпись этого факта из БЧ и понимает, что я действительно имею право ехать дальше.
Благодарю за внимание! Надеюсь, вам понравилось. Буду рад любой обратной связи. Хорошие новости) новый дроп от Ноткоина. Можно залутать 40$ без всяких условий.