FunCти Хаскелл менен FunCtionalга айландыруу: Серокелл Telegram Blockchain конкурсун кантип жеңип алды

Сиз бул Telegramды уккандырсыз Тон блокчейн платформасын ишке киргизүү алдында турат. Бирок сиз Telegramдан көп өтпөй кабарды сагынган болушуңуз мүмкүн конкурс жарыялады бул платформа үчүн бир же бир нече акылдуу келишимдерди ишке ашыруу үчүн.

Ири блокчейн долбоорлорун иштеп чыгууда чоң тажрыйбасы бар Serokell командасы четте тура алган жок. Биз беш кызматкерди сынакка тапшырдык, эки жумадан кийин алар секси хамелеон деген жөнөкөй кокустук лакап аты менен анда биринчи орунду алышты. Бул макалада мен алар муну кантип кылганы жөнүндө сүйлөшөм. Жакынкы он мүнөттө сиз жок дегенде кызыктуу окуяны окуйсуз жана эң көп дегенде андан өзүңүздүн ишиңизде колдоно турган пайдалуу нерсени табасыз деп ишенебиз.

Бирок бир аз контексттен баштайлы.

Мелдеш жана анын шарттары

Ошентип, катышуучулардын негизги милдеттери бир же бир нече сунушталган акылдуу келишимдерди ишке ашыруу, ошондой эле TON экосистемасын жакшыртуу боюнча сунуштарды киргизүү болду. Сынак 24-сентябрдан 15-октябрга чейин өтүп, жыйынтыгы 15-ноябрда гана чыгарылды. Бир топ убакыттан бери, бул убакыттын ичинде Telegram Telegramдагы VoIP чалуулардын сапатын тестирлөө жана баалоо үчүн C++ тилинде тиркемелерди иштеп чыгуу жана иштеп чыгуу боюнча сынактарды өткөрүүгө жана анын жыйынтыгын жарыялоого жетишкенин эске алганда.

Уюштуруучулар сунуштаган тизмеден эки акылдуу келишимди тандап алдык. Алардын бири үчүн биз TON менен бөлүштүрүлгөн куралдарды колдондук, ал эми экинчиси биздин инженерлер тарабынан атайын TON үчүн иштелип чыккан жана Хаскеллге курулган жаңы тилде ишке ашырылган.

Функционалдык программалоо тилин тандоо кокусунан эмес. Биздин корпоративдик блог Биз көп учурда функционалдык тилдердин татаалдыгы эмне үчүн чоң апыртма деп ойлойбуз жана эмне үчүн биз аларды объектиге багытталган тилдерден артык көрөбүз. Айтмакчы, ал да камтыйт бул макаланын оригиналы.

Эмне үчүн биз катышууну чечтик?

Кыскасы, биздин адистештирүү өзгөчө көндүмдөрдү талап кылган жана көбүнчө IT коомчулугу үчүн илимий баалуулукка ээ болгон стандарттуу эмес жана татаал долбоорлор болгондуктан. Биз ачык булактарды иштеп чыгууну катуу колдойбуз жана аны жайылтуу менен алектенебиз, ошондой эле информатика жана математика тармагында Орусиянын алдыңкы университеттери менен кызматташат.

Сынактын кызыктуу тапшырмалары жана сүйүктүү Telegram долбоорубузга тартылуу өзү эле эң сонун мотивация болгон, бирок байге фонду кошумча стимул болуп калды. 🙂

TON blockchain изилдөө

Биз блокчейн, жасалма интеллект жана машина үйрөнүү боюнча жаңы өнүгүүлөрдү кылдаттык менен көзөмөлдөйбүз жана биз иштеген ар бир чөйрөдө бир дагы маанилүү чыгарылышты өткөрүп жибербөөгө аракет кылабыз. Ошондуктан, сынак башталганда биздин команда мурунтан эле алардын идеялары менен тааныш болчу TON ак кагаз. Бирок, TON менен иштөөнү баштоодон мурун, биз техникалык документтерди жана платформанын чыныгы баштапкы кодун талдаган жокпуз, андыктан биринчи кадам айкын болду - расмий документтерди кылдат изилдөө. сайты жана долбоордун репозиторийлери.

Сынак башталганга чейин код жарыяланган болчу, андыктан убакытты үнөмдөө үчүн биз тарабынан жазылган гид же корутунду издөөнү чечтик. колдонуучулар тарабынан. Тилекке каршы, бул эч кандай натыйжа берген жок - Ubuntu боюнча платформаны чогултуу боюнча нускамалардан тышкары, биз башка материалдарды тапкан жокпуз.

Документтин өзү жакшы изилденген, бирок кээ бир жерлерде окуу кыйын болгон. Көбүнчө биз белгилүү бир пункттарга кайтып келип, абстракттуу идеялардын жогорку деңгээлдеги сыпаттамаларынан төмөнкү деңгээлдеги ишке ашыруунун деталдарына өтүүгө туура келди.

Эгерде спецификацияда ишке ашыруунун толук сүрөттөлүшү такыр эле камтылбаса, жеңил болмок. Виртуалдык машина анын стектерин кантип чагылдырары жөнүндө маалымат TON платформасы үчүн акылдуу келишимдерди түзүп жаткан иштеп чыгуучуларга жардам бергенден көрө алагды кылат.

Nix: долбоорду чогуу коюу

Серокелде биз чоң күйөрмандарбыз Орозгул. Биз аны менен долбоорлорубузду чогултуп, аларды колдонобуз NixOps, жана биздин бардык серверлерибизде орнотулган Nix OS. Мунун аркасында биздин бардык түзүмдөр кайталанууга жөндөмдүү жана Nix орнотула турган каалаган операциялык системада иштейт.

Ошентип, биз түзүү менен баштадык TON жыйындысы үчүн туюнтма менен Nix катмары. Анын жардамы менен TON компиляциясы мүмкүн болушунча жөнөкөй:

$ 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 тармагындагы акылдуу келишим коду TON виртуалдык машинасында (TVM) иштейт. TVM башка виртуалдык машиналарга караганда татаалыраак жана абдан кызыктуу функцияларга ээ, мисалы, алар менен иштей алат уландысы и маалыматтарга шилтемелер.

Мындан тышкары, ТОНдун балдары үч жаңы программалоо тилин түзүштү:

беш окшош универсалдуу стек программалоо тили Төртүнчү. Анын супер жөндөмү TVM менен өз ара аракеттенүү жөндөмдүүлүгү.

FunC окшош акылдуу келишим программалоо тили болуп саналат C жана башка тилге түзүлөт - Fift Assembler.

Бешинчи Ассамблея — TVM үчүн экилик аткарылуучу кодду түзүү үчүн беш китепкана. Бешинчи Ассемблердин компилятору жок. Бул Камтылган домендин өзгөчө тили (eDSL).

Биздин мелдеш иштейт

Акырында, аракетибиздин натыйжасын кароого убакыт жетти.

Асинхрондук төлөм каналы

Төлөм каналы - бул эки колдонуучуга блокчейнден тышкары төлөмдөрдү жөнөтүүгө мүмкүндүк берген акылдуу келишим. Натыйжада, сиз акчаны гана эмес (комиссия жок), ошондой эле убакытты да үнөмдөйсүз (кийинки блоктун иштетилишин күтүүнүн кереги жок). Төлөмдөр каалагандай аз жана талапка жараша болушу мүмкүн. Бул учурда тараптар бири-бирине ишенүүгө милдеттүү эмес, анткени акыркы эсептешүүнүн адилеттүүлүгү акылдуу келишим менен кепилденет.

Биз көйгөйдүн бир кыйла жөнөкөй чечүү жолун таптык. Эки тарап кол коюлган билдирүүлөрдү алмаша алышат, алардын ар бири эки номерден турат — ар бир тарап төлөгөн толук сумма. Бул эки сан сыяктуу иштейт вектордук саат салттуу бөлүштүрүлгөн системаларда жана транзакциялар боюнча "мурда болгон" тартибин орнотуңуз. Бул маалыматтарды колдонуу менен келишим мүмкүн болгон чыр-чатакты чече алат.

Чындыгында, бул идеяны ишке ашыруу үчүн бир сан жетиштүү, бирок биз экөөнү тең калтырдык, анткени ушундай жол менен колдонуучу интерфейсин ыңгайлуураак кылып алмакпыз. Мындан тышкары, биз ар бир билдирүүгө төлөм суммасын киргизүүнү чечтик. Ансыз, кандайдыр бир себептерден улам билдирүү жоголсо, анда бардык суммалар жана акыркы эсептөө туура болсо да, колдонуучу жоготууну байкабай калышы мүмкүн.

Биздин идеяны текшерүү үчүн, биз ушундай жөнөкөй жана кыска төлөм каналынын протоколун колдонуунун мисалдарын издедик. Таң калыштуусу, биз экөөнү гана таптык:

  1. баяндоо окшош ыкма, бир багыттуу канал үчүн гана.
  2. Окуу куралы, бул биздикиндей эле идеяны сүрөттөйт, бирок жалпы тууралык жана чыр-чатакты чечүү жол-жоболору сыяктуу көптөгөн маанилүү деталдарды түшүндүрбөйт.

Протоколубузду анын тууралыгына өзгөчө көңүл буруп, кеңири баяндап берүүнүн мааниси бар экени белгилүү болду. Бир нече кайталоодон кийин, спецификация даяр болду, эми сиз да жасай аласыз. ага кара.

Биз келишимди FunCде ишке ашырдык жана уюштуруучулар сунуштагандай, толугу менен Fiftте келишимибиз менен өз ара аракеттенүү үчүн буйрук сабынын утилитасын жаздык. Биз CLI үчүн каалаган башка тилди тандап алмакпыз, бирок биз Фиттин иш жүзүндө кандай аткарылганын көрүү үчүн аракет кылып көргүбүз келди.

Чынын айтсам, Fift менен иштегенден кийин биз бул тилди өнүккөн куралдары жана китепканалары бар популярдуу жана жигердүү колдонулган тилдерден артык көрүүгө эч кандай орчундуу себептерди көргөн жокпуз. Стекке негизделген тилде программалоо абдан жагымсыз, анткени стекте эмне бар экенин дайыма башыңызда сактап турушуңуз керек жана компилятор буга жардам бербейт.

Ошондуктан, биздин оюбузча, Fiftтин бар экендигинин бирден-бир негизи бул Fift Assembler үчүн кабыл алуучу тил катары анын ролу. Бирок бул бир гана максат үчүн жаңы тилди ойлоп тапкандан көрө, TVM ассемблерин кандайдыр бир тилге киргизген жакшы эмеспи?

TVM Haskell eDSL

Эми экинчи акылдуу келишимибиз жөнүндө сөз кылууга убакыт келди. Биз көп кол тамгалуу капчыкты иштеп чыгууну чечтик, бирок FunCде дагы бир акылдуу келишим жазуу өтө кызыксыз болмок. Биз кандайдыр бир даам кошкубуз келди жана бул TVM үчүн өзүбүздүн ассемблер тилибиз болчу.

Fift Assembler сыяктуу эле, биздин жаңы тилибиз орнотулган, бирок биз Fiftтин ордуна Хаскеллди хост катары тандап алдык, бул бизге анын өркүндөтүлгөн типтеги тутумунун бардык мүмкүнчүлүктөрүн пайдаланууга мүмкүндүк берди. Кичинекей катанын баасы өтө жогору болушу мүмкүн болгон акылдуу келишимдер менен иштөөдө, биздин оюбузча, статикалык терүү чоң артыкчылык болуп саналат.

TVM ассемблери Хаскеллге орнотулган кандай экенин көрсөтүү үчүн биз ага стандарттуу капчыкты ишке киргиздик. Бул жерде бир нече нерсеге көңүл буруш керек:

  • Бул келишим бир функциядан турат, бирок сиз каалагандай колдоно аласыз. Сиз кабыл алуучу тилде жаңы функцияны аныктаганыңызда (б.а. Хаскелл), биздин eDSL сизге анын TVMде өзүнчө көнүмүш болуп калышын же жөн эле чалуу учурунда сызылганын тандоого мүмкүндүк берет.
  • Хаскелл сыяктуу функциялардын компиляция убагында текшерилүүчү түрлөрү бар. Биздин eDSLде функциянын киргизүү түрү функция күткөн стектин түрү, ал эми натыйжанын түрү чалуудан кийин өндүрүлө турган стектин түрү.
  • Коддо аннотациялар бар stacktype, чакыруу пунктунда күтүлгөн стек түрүн сүрөттөп. Баштапкы капчык келишиминде бул жөн гана комментарийлер болгон, бирок биздин eDSLде алар чындыгында коддун бир бөлүгү жана компиляция убагында текшерилет. Эгер код өзгөрсө жана стек түрү өзгөрсө, алар иштеп чыгуучуга көйгөйдү табууга жардам берген документация же билдирүү катары кызмат кыла алат. Албетте, мындай аннотациялар иштөө убактысынын иштешине таасирин тийгизбейт, анткени алар үчүн TVM коду түзүлбөйт.
  • Бул дагы эле эки жуманын ичинде жазылган прототиби, ошондуктан долбоор боюнча дагы көп иштер жасалышы керек. Мисалы, сиз төмөндөгү коддо көргөн класстардын бардык инстанциялары автоматтык түрдө түзүлүшү керек.

Multisig капчыкты ишке ашыруу биздин eDSLде ушундай көрүнөт:

main :: IO ()
main = putText $ pretty $ declProgram procedures methods
  where
    procedures =
      [ ("recv_external", decl recvExternal)
      , ("recv_internal", decl recvInternal)
      ]
    methods =
      [ ("seqno", declMethod getSeqno)
      ]

data Storage = Storage
  { sCnt :: Word32
  , sPubKey :: PublicKey
  }

instance DecodeSlice Storage where
  type DecodeSliceFields Storage = [PublicKey, Word32]
  decodeFromSliceImpl = do
    decodeFromSliceImpl @Word32
    decodeFromSliceImpl @PublicKey

instance EncodeBuilder Storage where
  encodeToBuilder = do
    encodeToBuilder @Word32
    encodeToBuilder @PublicKey

data WalletError
  = SeqNoMismatch
  | SignatureMismatch
  deriving (Eq, Ord, Show, Generic)

instance Exception WalletError

instance Enum WalletError where
  toEnum 33 = SeqNoMismatch
  toEnum 34 = SignatureMismatch
  toEnum _ = error "Uknown MultiSigError id"

  fromEnum SeqNoMismatch = 33
  fromEnum SignatureMismatch = 34

recvInternal :: '[Slice] :-> '[]
recvInternal = drop

recvExternal :: '[Slice] :-> '[]
recvExternal = do
  decodeFromSlice @Signature
  dup
  preloadFromSlice @Word32
  stacktype @[Word32, Slice, Signature]
  -- cnt cs sign

  pushRoot
  decodeFromCell @Storage
  stacktype @[PublicKey, Word32, Word32, Slice, Signature]
  -- pk cnt' cnt cs sign

  xcpu @1 @2
  stacktype @[Word32, Word32, PublicKey, Word32, Slice, Signature]
  -- cnt cnt' pk cnt cs sign

  equalInt >> throwIfNot SeqNoMismatch

  push @2
  sliceHash
  stacktype @[Hash Slice, PublicKey, Word32, Slice, Signature]
  -- hash pk cnt cs sign

  xc2pu @0 @4 @4
  stacktype @[PublicKey, Signature, Hash Slice, Word32, Slice, PublicKey]
  -- pubk sign hash cnt cs pubk

  chkSignU
  stacktype @[Bool, Word32, Slice, PublicKey]
  -- ? cnt cs pubk

  throwIfNot SignatureMismatch
  accept

  swap
  decodeFromSlice @Word32
  nip

  dup
  srefs @Word8

  pushInt 0
  if IsEq
  then ignore
  else do
    decodeFromSlice @Word8
    decodeFromSlice @(Cell MessageObject)
    stacktype @[Slice, Cell MessageObject, Word8, Word32, PublicKey]
    xchg @2
    sendRawMsg
    stacktype @[Slice, Word32, PublicKey]

  endS
  inc

  encodeToCell @Storage
  popRoot

getSeqno :: '[] :-> '[Word32]
getSeqno = do
  pushRoot
  cToS
  preloadFromSlice @Word32

Биздин eDSL жана көп кол капчык келишимибиздин толук баштапкы кодун бул жерден тапса болот бул репозиторий. Жана башкалар майда-чүйдөсүнө чейин айтып берди курулган тилдер жөнүндө, биздин кесиптешибиз Георгий Агапов.

Мелдеш жана ТОН жөнүндө корутунду

Жалпысынан биздин ишибиз 380 саатты алды (документтер менен таанышуу, жолугушуулар жана иш жүзүндө иштеп чыгууну кошкондо). Конкурстук долбоорго беш иштеп чыгуучу катышты: CTO, команданын лидери, блокчейн платформасынын адистери жана Haskell программалык камсыздоону иштеп чыгуучулар.

Биз сынакка кыйынчылыксыз катышуу үчүн ресурстарды таптык, анткени хакатондун духу, тыгыз командада иштөө жана жаңы технологиялардын аспектилерине тез сүңгүп кетүү зарылчылыгы ар дайым кызыктуу. Чектелген ресурстардын шарттарында максималдуу натыйжаларга жетүү үчүн бир нече уйкусуз түндөр баа жеткис тажрыйба жана сонун эскерүүлөр менен толукталат. Мындан тышкары, мындай тапшырмалардын үстүндө иштөө ар дайым компаниянын процесстеринин жакшы сыноосу болуп саналат, анткени жакшы иштеген ички өз ара аракеттенишпестен, чыныгы татыктуу натыйжаларга жетүү өтө кыйын.

Ырдын текстин эске албаганда: ТОН командасынын эмгегинин көлөмү бизди таң калтырды. Алар татаал, кооз, эң башкысы жумушчу системаны түзө алышты. TON өзүн чоң потенциалы бар платформа катары далилдеди. Бирок, бул экосистеманы өнүктүрүү үчүн, блокчейн долбоорлорунда колдонуу жагынан да, өнүктүрүү куралдарын жакшыртуу жагынан дагы көп нерсени жасоо керек. Биз азыр бул процесстин бир бөлүгү болгонубузга сыймыктанабыз.

Бул макаланы окугандан кийин дагы эле суроолоруңуз болсо же көйгөйлөрүңүздү чечүү үчүн ТОНду кантип колдонуу керектиги боюнча идеяларыңыз болсо, бизге жаз — биз езубуздун тажрыйбабыз менен бөлүшүүгө кубанычта болобуз.

Source: www.habr.com

Комментарий кошуу