Каманда Serokell з багатым вопытам распрацоўкі буйных блокчейн праектаў не магла застацца ў баку. Мы дэлегавалі на конкурс пецярых супрацоўнікаў, а ўжо праз два тыдні яны занялі ў ім першае месца пад (ня)сціплым рандомным нікам Sexy Chameleon. У гэтым артыкуле я раскажу пра тое, як ім гэта ўдалося. Спадзяемся, за бліжэйшыя дзесяць хвілін вы як мінімум прачытаеце цікавую гісторыю, а як максімум знойдзеце ў ёй нешта карыснае, што зможаце прымяніць у сваёй працы.
Але давайце пачнем з невялікага апускання ў кантэкст.
Конкурс і яго ўмовы
Такім чынам, асноўнымі задачамі ўдзельнікаў сталі рэалізацыя аднаго ці больш з прапанаваных смарт-кантрактаў, а таксама занясенне прапаноў па паляпшэнні экасістэмы TON. Конкурс праходзіў з 24 верасня па 15 кастрычніка, а вынікі аб'явілі толькі 15 лістапада. Даволі доўга, улічваючы, што за гэты час Telegram паспеў правесці і абвясціць вынікі кантэстаў па дызайне і па распрацоўцы прыкладанняў на C++ для тэставання і адзнакі якасці VoIP-званкоў у Telegram.
Мы выбралі са спіса, прапанаванага арганізатарамі, два смарт-кантракты. Для аднаго з іх мы выкарыстоўвалі прылады, якія распаўсюджваюцца разам з TON, а другі рэалізавалі на новай мове, распрацаваным нашымі інжынерамі спецыяльна для TON і убудаваным у Haskell.
Выбар функцыянальнай мовы праграмавання не выпадковы. У нашым карпаратыўным блогу мы часта распавядаем, чаму лічым складанасць функцыянальных моў вялікім перабольшаннем і чаму мы ў цэлым аддаем перавагу іх аб'ектна-арыентаваным. Дарэчы, у ім ёсць і арыгінал гэтага артыкула.
Чаму мы ўвогуле вырашылі ўдзельнічаць
Калі сцісла, таму што наша спецыялізацыя — гэта нестандартныя і складаныя праекты, якія патрабуюць адмысловых навыкаў і часцяком уяўляюць навуковую каштоўнасць для IT-супольнасці. Мы горача падтрымліваем open-source распрацоўку і займаемся яе папулярызацыяй, а таксама супрацоўнічаем з кіроўнымі ўніверсітэтамі Расіі ў вобласці кампутарных навук і матэматыкі.
Цікавыя задачы конкурсу і дачыненне да горача любімага намі праекту Тэлеграм самі па сабе былі выдатнай матывацыяй, ну а прызавы фонд стаў дадатковым стымулам. 🙂
Даследаванне блокчейна TON
Мы пільна сочым за новымі распрацоўкамі ў блокчэйне, штучным інтэлекце і машынным навучанні і стараемся не прапускаць ніводнага значнага рэлізу ў кожнай са сфер, у якіх працуем. Таму да моманту старту конкурсу наша каманда ўжо была знаёмая з ідэямі з TON white paper. Аднак да пачатку працы з TON мы не аналізавалі тэхнічную дакументацыю і фактычны зыходны код платформы, таму першы крок быў дастаткова відавочны - стараннае даследаванне афіцыйнай дакументацыі на сайце і ў рэпазітары праекта.
Да пачатку конкурсу код ужо быў апублікаваны, таму, каб зэканоміць час, мы вырашылі пашукаць кіраўніцтва ці выцісканне, напісанае карыстальнікамі. Нажаль, выніку гэта не дало - акрамя інструкцыі па зборцы платформы на Ubuntu, іншых матэрыялаў мы не знайшлі.
Сама дакументацыя аказалася старанна прапрацаванай, але чытаць яе ў некаторых момантах было складана. Даволі часта нам даводзілася вяртацца да тых ці іншых пунктаў і пераключацца з высокаўзроўневых апісанняў абстрактных ідэй на нізкаўзроўневыя дэталі рэалізацыі.
Было б прасцей, калі б у спецыфікацыі ўвогуле не было падрабязнага апісання рэалізацыі. Інфармацыя аб тым, як віртуальная машына прадстаўляе свой стэк, хутчэй адцягвае распрацоўшчыкаў, якія ствараюць смарт-кантракты для платформы TON, чым дапамагае ім.
Nix: збіраем праект
У Serokell мы вялікія прыхільнікі Nix. Мы збіраем ім нашы праекты і разгортваем іх з дапамогай NixOps, а на ўсіх нашых серверах усталявана АС Nix. Дзякуючы гэтаму ўсе нашы білды ўзнаўляльныя і працуюць пад любой аперацыйнай сістэмай, на якую можна ўсталяваць Nix.
$ cd ~/.config/nixpkgs/overlays && git clone https://github.com/serokell/ton.nix
$ cd /path/to/ton/repo && nix-shell
[nix-shell]$ cmakeConfigurePhase && make
Заўважце, вам не трэба ўстанаўліваць ніякія залежнасці. Nix магічным чынам зробіць усё за вас па-за залежнасцю ад таго, ці карыстаецеся вы NixOS, Ubuntu ці macOS.
Праграмаванне для TON
Код смарт-кантрактаў у TON Network выконваецца на TON Virtual Machine (TVM). TVM складаней, чым большасць іншых віртуальных машын, і валодае вельмі цікавым функцыяналам, напрыклад яна ўмее працаваць з працягамі (continuations) и спасылкамі на дадзеныя.
Больш за тое, хлопцы з TON стварылі цэлых тры новыя мовы праграмавання:
Fift — універсальная сцяковая мова праграмавання, якая нагадвае Чацвёртае. Яго супер-здольнасць - магчымасць узаемадзейнічаць з TVM.
FunC - мова праграмавання смарт кантрактаў, які падобны на C і кампілюецца ў яшчэ адну мову - Fift Assembler.
Нарэшце, надышоў час паглядзець на вынікі нашых намаганняў.
Асінхронны плацежны канал
Плацежны канал (payment channel) - смарт-кантракт, які дазваляе двум карыстальнікам адпраўляць плацяжы за межамі блокчейна. У выніку эканомяцца не толькі грошы (адсутнічае камісія), але і час (вам не трэба чакаць, пакуль апрацуецца чарговы блок). Плацяжы могуць быць колькі заўгодна маленькімі і адбывацца настолькі часта, наколькі гэта патрабуецца. Пры гэтым бакам не абавязкова давяраць адзін аднаму, таму што справядлівасць канчатковага разліку гарантавана смарт-кантрактам.
Мы знайшлі даволі простае вырашэнне праблемы. Два бакі могуць абменьвацца падпісанымі паведамленнямі, кожны з якіх утрымлівае два чысла — поўную суму, выплачаную кожным з удзельнікаў. Гэтыя два лікі працуюць як вектарны гадзіннік у традыцыйных размеркаваных сістэмах і задаюць парадак "адбылося да" на транзакцыях. Выкарыстоўваючы гэтыя дадзеныя, кантракт зможа вырашыць любы магчымы канфлікт.
Насамрэч для рэалізацыі гэтай ідэі дастаткова і аднаго ліку, але мы пакінулі абодва, паколькі так мы змаглі зрабіць больш зручны карыстацкі інтэрфейс. Апроч гэтага, мы вырашылі ўключыць у кожнае паведамленне памер плацяжу. Без яго, калі паведамленне па нейкіх прычынах згубіцца, то, хоць усе сумы і канчатковы разлік будуць карэктнымі, карыстач страту можа не заўважыць.
Каб праверыць нашу ідэю, мы пашукалі прыклады выкарыстання такога простага і лаканічнага пратакола плацежнага канала. Да здзіўлення, мы выявілі ўсяго два:
Апісанне падобнага падыходу, толькі для выпадку аднанакіраванага канала.
Тутарыял, у якім апісана тая ж ідэя, што і ў нас, толькі без тлумачэння многіх важных дэталяў, такіх як агульная карэктнасць і працэдура вырашэння канфліктаў.
Стала ясна, што ёсць сэнс падрабязна апісаць наш пратакол, надаўшы адмысловую ўвагу яго карэктнасці. Пасля некалькіх ітэрацый спецыфікацыя была гатова, і зараз вы таксама можаце на яе паглядзець.
Мы рэалізавалі кантракт на FunC, а ўтыліту каманднага радка для ўзаемадзеяння з нашым кантрактам мы цалкам напісалі на Fift, як рэкамендавалі арганізатары. Мы маглі б выбраць любую іншую мову для нашага CLI, але нам было цікава паспрабаваць менавіта Fift, каб паглядзець, як ён пакажа сябе ў справе.
Шчыра кажучы, папрацаваўшы з Fift, мы не ўбачылі важкіх прычын аддаваць перавагу гэтай мове папулярным і актыўна выкарыстоўваемым мовам з развітым інструментарыем і бібліятэкамі. Праграмаваць на стэкавай мове даволі непрыемна, паколькі даводзіцца ўвесь час памятаць што дзе ляжыць у стэку, і кампілятар з гэтым ніяк не дапамагае.
Таму адзіным, на наш погляд, апраўданнем існавання Fift з'яўляецца яго роля ў якасці хост-мовы для Fift Assembler. Але ці не лепш было б убудаваць асэмблер TVM у нейкую існуючую мову, а не прыдумляць новую для гэтай, па сутнасці адзінай, мэты?
TVM Haskell eDSL
Цяпер прыйшоў час расказаць аб другім нашым смарт-кантракце. Мы вырашылі распрацаваць кашалёк з мультыподпісам, але пісаць яшчэ адзін смарт-кантракт на FunC было б занадта сумна. Нам хацелася дадаць якую-небудзь разыначку, і ёю стала наша ўласная мова асэмблера для TVM.
Як і Fift Assembler, наша новая мова ўбудаваная, толькі ў якасці хаста замест Fift мы абралі Haskell, што дазволіла нам у поўнай меры выкарыстаць яго прасунутую сістэму тыпаў. Пры працы са смарт-кантрактамі, дзе кошт нават невялікай памылкі можа быць вельмі высокай, статычная тыпізацыя, на наш погляд, з'яўляецца вялікай перавагай.
Каб прадэманстраваць, як выглядае асэмблер TVM, убудаваны ў Haskell, мы рэалізавалі на ім стандартны кашалёк. Вось некалькі рэчаў, на які варта звярнуць увагу:
Гэты кантракт складаецца з адной функцыі, але вы можаце выкарыстоўваць колькі заўгодна. Калі вы вызначаеце новую функцыю на мове хаста (гэта значыць на Haskell), наш eDSL дазваляе вам выбраць, ці вы хочаце, каб яна ператварылася ў асобную падпраграму ў TVM або проста ўбудавана ў месца выкліку.
Як і ў Haskell, у функцый ёсць тыпы, якія правяраюцца падчас кампіляцыі. У нашым eDSL тып ўваходу функцыі гэта тып стэка, які функцыя чакае, а тып выніку гэта тып стэка, які атрымаецца пасля выкліку.
У кодзе ёсць анатацыі stacktype, якія апісваюць чаканы тып стэка ў кропцы выкліку. У арыгінальным кантракце кашалька гэта былі проста каментарыі, але ў нашым eDSL яны фактычна з'яўляюцца часткай кода і правяраюцца падчас кампіляцыі. Яны могуць служыць дакументацыяй ці сцвярджэннямі, якія дапамагаюць распрацоўніку знайсці праблему ў выпадку, калі пры змене кода тып стэка зменіцца. Само сабой, такія анатацыі не ўплываюць на прадукцыйнасць падчас выканання, паколькі ніякі TVM код для іх не генеруецца.
Гэта ўсё яшчэ прататып, напісаны за два тыдні, таму над праектам трэба яшчэ шмат працы. Напрыклад, усе асобнікі класаў, якія вы бачыце ў прыведзеным ніжэй кодзе, павінны генеравацца аўтаматычна.
Вось як выглядае рэалізацыя multisig-кашалька на нашым eDSL:
Поўны зыходны код нашага eDSL і кантракт кашалька з мультыподпісам вы можаце знайсці ў гэтым рэпазітары. А больш падрабязна расказаў пра ўбудаваныя мовы наш калега Георгій Агапаў.
Высновы аб конкурсе і TON
У суме наша праца заняла 380 гадзін (разам са знаёмствам з дакументацыяй, нарадамі і непасрэдна распрацоўкай). У конкурсным праекце прынялі ўдзел пяць распрацоўшчыкаў: СТА, цім-лід, спецыялісты па блокчэйн-платформах і распрацоўшчыкі праграмнага забеспячэння на Haskell.
Рэсурсы для ўдзелу ў кантэсце мы знайшлі без працы, бо дух хакатона, цесная камандная праца, неабходнасць хуткага апускання ў аспекты новых тэхналогій - гэта заўсёды займальна. Некалькі бяссонных начэй дзеля дасягнення максімальнага выніку ва ўмовах абмежаваных рэсурсаў кампенсуюцца бясцэнным досведам і выдатнымі ўспамінамі. Да таго ж праца над падобнымі задачамі – заўсёды добрая праверка працэсаў кампаніі, бо дамагчыся сапраўды годных вынікаў без выдатна адладжанага ўнутранага ўзаемадзеяння вельмі цяжка.
Акрамя лірыкі: мы былі ўражаныя аб'ёмам працы, праведзеным камандай TON. Ім удалося пабудаваць складаную, прыгожую, і самае галоўнае, працуючую сістэму. TON паказаў сябе як платформа, якая мае вялікі патэнцыял. Аднак для таго, каб гэтая экасістэма развівалася, трэба зрабіць яшчэ вельмі шмат, як з пункту гледжання яе выкарыстання ў блокчейн праектах, так і з пункту гледжання ўдасканалення інструментаў распрацоўкі. Мы ганарымся тым, што зараз з'яўляемся часткай гэтага працэсу.
Калі пасля прачытання гэтага артыкула ў вас засталіся нейкія пытанні ці з'явіліся ідэі аб тым, як прымяніць TON для вырашэння вашых задач, напішыце нам - Мы з радасцю падзелімся вопытам.