Вы наверняка слышали о том, что Telegram собирается запустить блокчейн-платформу Ton. Но вы могли пропустить новость, что не так давно Telegram объявил конкурс на реализацию одного или нескольких смарт-контрактов для этой платформы.  Команда Serokell с богатым опытом разработки крупных блокчейн проектов не могла остаться в стороне. Мы делегировали на конкурс пятерых сотрудников, а уже через две недели они заняли в нем первое место под (не)скромным рандомным ником Sexy Chameleon. В этой статье я расскажу о том, как им это удалось. Надеемся, за ближайшие десять минут вы как минимум прочитаете интересную историю, а как максимум найдете в ней что-то полезное, что сможете применить в своей работе.  Но давайте начнем с небольшого погружения в контекст. Итак, основными задачами участников стали реализация одного или более из предложенных смарт-контрактов, а также внесение предложений по улучшению экосистемы TON. Конкурс проходил с 24 сентября по 15 октября, а результаты объявили лишь 15 ноября. Довольно долго, учитывая, что за это время Telegram успел провести и огласить результаты контестов по дизайну и по разработке приложений на C++ для тестирования и оценки качества VoIP-звонков в Telegram. Мы выбрали из списка, предложенного организаторами, два смарт-контракта. Для одного из них мы использовали инструменты, распространяющиеся вместе с TON, а второй реализовали на новом языке, разработанном нашими инженерами специально для TON и встроенном в Haskell.  Выбор функционального языка программирования не случаен. В нашем корпоративном блоге  мы часто рассказываем, почему считаем сложность функциональных языков большим преувеличением и почему мы в целом предпочитаем их объектно-ориентированным. Кстати, в нем есть и оригинал этой статьи. Если вкратце, потому что наша специализация — это нестандартные и сложные проекты, требующие особых навыков и зачастую представляющие научную ценность для IT-сообщества. Мы горячо поддерживаем open-source разработку и занимаемся ее популяризацией, а также сотрудничаем с ведущими университетами России в области компьютерных наук и математики.  Интересные задачи конкурса и причастность к горячо любимому нами проекту Телеграм сами по себе были отличной мотивацией, ну а призовой фонд стал дополнительным стимулом. :) Мы пристально следим за новыми разработками в блокчейне, искусственном интеллекте и машинном обучении и стараемся не пропускать ни одного значительного релиза в каждой из сфер, в которых работаем. Поэтому к моменту старта конкурса наша команда уже была знакома с идеями из TON white paper. Однако до начала работы с TON мы не анализировали техническую документацию и фактический исходный код платформы, поэтому первый шаг был достаточно очевиден — тщательное исследование официальной документации на сайте и в репозитории проекта. К началу конкурса код уже был опубликован, поэтому, чтобы сэкономить время, мы решили поискать руководство или выжимку, написанную пользователями. К сожалению, результата это не дало — кроме инструкции по сборке платформы на Ubuntu, других материалов мы не нашли.  Сама документация оказалась тщательно проработанной, но читать ее в некоторых моментах было сложно. Довольно часто нам приходилось возвращаться к тем или иным пунктам и переключаться с высокоуровневых описаний абстрактных идей на низкоуровневые детали реализации. Было бы проще, если бы в спецификации вообще не было подробного описания реализации. Информация о том, как виртуальная машина представляет свой стек, скорее отвлекает разработчиков, создающих смарт-контракты для платформы TON, чем помогает им. В Serokell мы большие поклонники Nix. Мы собираем им наши проекты и разворачиваем их с помощью NixOps, а на всех наших серверах установлена NixOS. Благодаря этому все наши билды воспроизводимы и работают под любой операционной системой, на которую можно установить Nix.  Поэтому мы начали с создания Nix overlay с выражением для сборки TON. С его помощью скомпилировать TON максимально просто: Заметьте, вам не нужно устанавливать никакие зависимости. Nix магическим образом сделает все за вас вне зависимости от того, пользуетесь ли вы NixOS, Ubuntu или macOS. Код смарт-контрактов в TON Network выполняется на TON Virtual Machine (TVM). TVM сложнее, чем большинство других виртуальных машин, и обладает весьма интересным функционалом, например она умеет работать с продолжениями (continuations) и ссылками на данные. Более того, ребята из TON создали целых три новых языка программирования: Fift — универсальный стековый язык программирования, напоминающий Forth. Его супер-способность — возможность взаимодействовать с TVM. FunC — язык программирования смарт контрактов, который похож на C и компилируется в еще один язык — Fift Assembler. Fift Assembler — библиотека Fift для генерации двоичного исполняемого кода для TVM. У Fift Assembler отсутствует компилятор. Это встраиваемый предметно-ориентированный язык (eDSL). Наконец, пришло время посмотреть на результаты наших усилий. Платежный канал (payment channel) — смарт-контракт, который позволяет двум пользователям отправлять платежи за пределами блокчейна. В результате экономятся не только деньги (отсутствует комиссия), но и время (вам не надо ждать, пока обработается очередной блок). Платежи могут быть сколь угодно маленькими и происходить настолько часто, насколько это требуется. При этом сторонам не обязательно доверять друг другу, так как справедливость окончательного расчета гарантирована смарт-контрактом. Мы нашли довольно простое решение проблемы. Две стороны могут обмениваться подписанными сообщениями, каждое из которых содержит два числа — полную сумму, уплаченную каждым из участников. Эти два числа работают как векторные часы в традиционных распределенных системах и задают порядок «произошло до» на транзакциях. Используя эти данные, контракт сможет разрешить любой возможный конфликт.  На самом деле для реализации этой идеи достаточно и одного числа, но мы оставили оба, поскольку так мы смогли сделать более удобный пользовательский интерфейс. Помимо этого, мы решили включить в каждое сообщение размер платежа. Без него, если сообщение по каким-то причинам потеряется, то, хотя все суммы и окончательный рассчет будут корректными, пользователь потерю может не заметить. Чтобы проверить нашу идею, мы поискали примеры использования такого простого и лаконичного протокола платежного канала. К удивлению, мы обнаружили всего два: Стало ясно, что есть смысл подробно описать наш протокол, уделив особое внимание его корректности. После нескольких итераций спецификация была готова, и теперь вы тоже можете на неё посмотреть.  Мы реализовали контракт на FunC, а утилиту командной строки для взаимодействия с нашим контрактом мы полностью написали на Fift, как рекомендовали организаторы. Мы могли бы выбрать любой другой язык для нашего CLI, но нам было интересно попробовать именно Fift, чтобы посмотреть, как он покажет себя в деле. Честно говоря, поработав с Fift, мы не увидели веских причин предпочитать этот язык популярным и активно используемым языкам с развитым инструментарием и библиотеками. Программировать на стековом языке довольно неприятно, поскольку приходится постоянно держать в голове что где лежит в стеке, и компилятор с этим никак не помогает. Поэтому единственным, на наш взгляд, оправданием существования Fift является его роль в качестве хост-языка для Fift Assembler. Но не лучше ли было бы встроить ассемблер TVM в какой-то существующий язык, а не придумывать новый для этой, по сути единственной, цели? Теперь пришло время рассказать о втором нашем смарт-контракте. Мы решили разработать кошелек с мультиподписью, но писать еще один смарт-контракт на FunC было бы слишком скучно. Нам хотелось добавить какую-нибудь изюминку, и ею стал наш собственный язык ассемблера для TVM.  Как и Fift Assembler, наш новый язык встраиваемый, только в качестве хоста вместо Fift мы выбрали Haskell, что позволило нам в полной мере использовать его продвинутую систему типов. При работе со смарт-контрактами, где цена даже небольшой ошибки может быть очень высокой, статическая типизация, на наш взгляд, является большим преимуществом.  Чтобы продемонстрировать, как выглядит ассемблер TVM, встроенный в Haskell, мы реализовали на нем стандартный кошелек. Вот несколько вещей, на который стоит обратить внимание: Вот как выглядит реализация multisig-кошелька на нашем eDSL: Полный исходный код нашего eDSL и контракт кошелька с мультиподписью вы можете найти в этом репозитории. А более подробно рассказал про встроенные языки наш коллега Георгий Агапов. В сумме наша работа заняла 380 часов (вместе со знакомством с документацией, совещаниями и непосредственно разработкой). В конкурсном проекте приняли участие пять разработчиков: СТО, тим-лид, специалисты по блокчейн-платформам и разработчики программного обеспечения на Haskell. Ресурсы для участия в контесте мы нашли без труда, так как дух хакатона, тесная командная работа, необходимость быстрого погружения в аспекты новых технологий — это всегда увлекательно. Несколько бессонных ночей ради достижения максимального результата в условиях ограниченных ресурсов компенсируются бесценным опытом и отличными воспоминаниями. К тому же работа над подобными задачами — всегда хорошая проверка процессов компании, так как добиться действительно достойных результатов без отлично отлаженного внутреннего взаимодействия крайне тяжело. Кроме лирики: мы были впечатлены объемом работы, проделанным командой TON. Им удалось построить сложную, красивую, и самое главное, работающую систему. TON показал себя как платформа, имеющая большой потенциал. Однако для того, чтобы эта экосистема развивалась, нужно сделать еще очень много, как с точки зрения ее использования в блокчейн проектах, так и с точки зрения совершенствования инструментов разработки. Мы гордимся тем, что теперь являемся частью этого процесса.  Если после прочтения этой статьи у вас остались какие-то вопросы или появились идеи о том, как применить TON для решения ваших задач, напишите нам — мы с радостью поделимся опытом. Chief executive officer @ Serokell