Ngowahi FunC dadi FunCtional karo Haskell: Kepiye Serokell menang Kompetisi Blockchain Telegram

Sampeyan mbokmenawa wis krungu sing Telegram arep miwiti platform pamblokiran Ton. Nanging sampeyan bisa uga ora kejawab kabar sing durung suwe Telegram ngumumake kompetisi kanggo implementasine siji utawa luwih kontrak pinter kanggo platform iki.

Tim Serokell, kanthi pengalaman ekstensif ing ngembangaken proyek pamblokiran gedhe, ora bisa mandheg. We delegated limang karyawan kanggo kompetisi, lan rong minggu mengko padha njupuk Panggonan pisanan ing (ing) andhap asor acak julukan Sexy Chameleon. Ing artikel iki aku bakal pirembagan bab carane padha nindakake. Muga-muga ing sepuluh menit sabanjure sampeyan bakal maca crita sing menarik, lan paling akeh sampeyan bakal nemokake sing migunani sing bisa ditrapake ing karya sampeyan.

Nanging ayo miwiti kanthi konteks cilik.

Kompetisi lan kahanane

Dadi, tugas utama para peserta yaiku implementasine siji utawa luwih saka kontrak cerdas sing diusulake, uga nggawe proposal kanggo nambah ekosistem TON. Kompetisi kasebut wiwit tanggal 24 September nganti 15 Oktober, lan asile mung diumumake tanggal 15 November. Cukup suwe, amarga sajrone wektu iki Telegram bisa nahan lan ngumumake asil kontes babagan desain lan pangembangan aplikasi ing C ++ kanggo nguji lan netepake kualitas panggilan VoIP ing Telegram.

Kita milih loro kontrak pinter saka dhaptar sing diusulake dening panitia. Kanggo salah siji saka wong-wong mau, kita nggunakake alat sing disebarake karo TON, lan sing kapindho ditindakake ing basa anyar sing dikembangake dening insinyur khusus kanggo TON lan dibangun ing Haskell.

Pilihan basa pamrograman fungsional ora sengaja. Ing kita blog perusahaan Kita asring ngomong babagan kenapa kita mikir kerumitan basa fungsional minangka exaggeration gedhe lan kenapa kita umume luwih seneng karo basa sing berorientasi obyek. Miturut cara, uga ngandhut asli saka artikel iki.

Apa kita malah mutusake kanggo melu?

Singkatnya, amarga spesialisasi kita minangka proyek non-standar lan kompleks sing mbutuhake katrampilan khusus lan asring duweni nilai ilmiah kanggo komunitas IT. We banget ndhukung pembangunan open-source lan melu popularization sawijining, lan uga kerjo bareng karo universities Russian anjog ing lapangan ilmu komputer lan matématika.

Tugas sing menarik saka kompetisi lan keterlibatan ing proyek Telegram sing ditresnani minangka motivasi sing apik banget, nanging dana hadiah dadi insentif tambahan. 🙂

riset blockchain TON

Kita ngawasi kanthi rapet perkembangan anyar ing pamblokiran, intelijen buatan lan pembelajaran mesin lan nyoba ora kantun rilis sing signifikan ing saben wilayah sing kita kerja. Mula, nalika kompetisi diwiwiti, tim kita wis kenal karo ide saka TON kertas putih. Nanging, sadurunge miwiti karya karo TON, kita ora nganalisa dokumentasi teknis lan kode sumber nyata saka platform, supaya langkah pisanan cukup ketok - sinau lengkap saka dokumentasi resmi ing situs lan ing repositori proyek.

Nalika kompetisi diwiwiti, kode kasebut wis diterbitake, mula kanggo ngirit wektu, kita mutusake golek pandhuan utawa ringkesan sing ditulis dening pangguna. Sayange, iki ora menehi asil - kajaba instruksi kanggo ngumpulake platform ing Ubuntu, kita ora nemokake bahan liyane.

Dokumentasi kasebut dhewe diteliti kanthi apik, nanging angel diwaca ing sawetara titik. Cukup asring kita kudu bali menyang titik tartamtu lan ngalih saka deskripsi tingkat dhuwur saka ide abstrak menyang rincian implementasine tingkat rendah.

Iku bakal luwih gampang yen specification ora kalebu gambaran rinci implementasine ing kabeh. Informasi babagan carane mesin virtual makili tumpukan kasebut luwih cenderung ngganggu pangembang nggawe kontrak cerdas kanggo platform TON tinimbang mbantu.

Nix: sijine proyek bebarengan

Ing Serokel, kita dadi penggemar gedhe nix. Kita ngumpulake proyek kita karo wong-wong mau lan nyebarke kanthi nggunakake NixOps, lan diinstal ing kabeh server kita Nix OS. Thanks kanggo iki, kabeh bangunan kita bisa direproduksi lan bisa digunakake ing sistem operasi apa wae sing bisa diinstal Nix.

Dadi kita miwiti nggawe Nix overlay karo ekspresi kanggo perakitan TON. Kanthi bantuan, kompilasi TON gampang banget:

$ cd ~/.config/nixpkgs/overlays && git clone https://github.com/serokell/ton.nix
$ cd /path/to/ton/repo && nix-shell
[nix-shell]$ cmakeConfigurePhase && make

Elinga yen sampeyan ora perlu nginstal dependensi. Nix bakal nindakake kabeh kanggo sampeyan, apa sampeyan nggunakake NixOS, Ubuntu, utawa macOS.

Pemrograman kanggo TON

Kode kontrak cerdas ing TON Network lumaku ing TON Virtual Machine (TVM). TVM luwih Komplek saka paling mesin virtual liyane, lan wis fungsi menarik banget, Contone, bisa karo tutugan и pranala menyang data.

Kajaba iku, wong lanang saka TON nggawe telung basa pamrograman anyar:

lima iku basa program tumpukan universal sing meh podho Dhuwur. Kemampuan super dheweke yaiku kemampuan kanggo sesambungan karo TVM.

FunC minangka basa pamrograman kontrak pinter sing padha karo C lan dikompilasi menyang basa liya - Fift Assembler.

Assembler kaping lima - Lima perpustakaan kanggo ngasilake kode eksekusi binar kanggo TVM. Fifth Assembler ora duwe compiler. Iki Embedded Domain Spesific Language (eDSL).

Kompetisi kita kerja

Pungkasan, wektune kanggo ndeleng asil usaha kita.

Saluran pambayaran ora sinkron

Saluran pambayaran minangka kontrak cerdas sing ngidini rong pangguna ngirim pembayaran ing njaba blockchain. Akibaté, sampeyan ora mung nyimpen dhuwit (ora ana komisi), nanging uga wektu (sampeyan ora kudu ngenteni blok sabanjure diproses). Pembayaran bisa dadi cilik kaya sing dikarepake lan asring dibutuhake. Ing kasus iki, para pihak ora kudu saling percaya, amarga keadilan penyelesaian pungkasan dijamin dening kontrak cerdas.

Kita nemokake solusi sing cukup prasaja kanggo masalah kasebut. Rong pihak bisa ijol-ijolan pesen sing ditandatangani, saben ngemot rong nomer-jumlah lengkap sing dibayar saben partai. Iki nomer loro bisa kaya jam vektor ing sistem mbagekke tradisional lan nyetel "kedaden sadurunge" urutan ing transaksi. Nggunakake data iki, kontrak bakal bisa ngatasi konflik sing bisa ditindakake.

Nyatane, siji nomer cukup kanggo ngetrapake ide iki, nanging kita ninggalake loro amarga kanthi cara iki kita bisa nggawe antarmuka pangguna sing luwih trep. Kajaba iku, kita mutusake kanggo nyakup jumlah pembayaran ing saben pesen. Tanpa iku, yen pesen ilang kanggo sawetara alesan, banjur, sanajan kabeh jumlah lan pitungan final bakal bener, pangguna bisa uga ora sok dong mirsani mundhut.

Kanggo nyoba ide kita, kita goleki conto nggunakake protokol saluran pembayaran sing prasaja lan ringkes. Kaget, kita nemokake mung loro:

  1. Description pendekatan sing padha, mung kanggo kasus saluran unidirectional.
  2. Tutorial, sing njlèntrèhaké gagasan sing padha karo kita, nanging tanpa nerangake akeh rincian penting, kayata kabeneran umum lan tata cara resolusi konflik.

Dadi jelas manawa bisa njlèntrèhaké protokol kita kanthi rinci, kanthi mènèhi perhatian khusus marang kabeneran. Sawise sawetara iterasi, spesifikasi wis siyap, lan saiki sampeyan uga bisa. deleng dheweke.

Kita ngetrapake kontrak kasebut ing FunC, lan kita nulis sarana baris perintah kanggo sesambungan karo kontrak kita kabeh ing Fift, kaya sing disaranake para panitia. Kita bisa milih basa liyane kanggo CLI kita, nanging kita padha kasengsem ing nyoba Fit kanggo ndeleng carane nindakake ing laku.

Jujur, sawise nggarap Fift, kita ora weruh alasan sing kuat kanggo milih basa iki tinimbang basa sing populer lan aktif digunakake kanthi alat lan perpustakaan sing dikembangake. Pemrograman ing basa basis tumpukan cukup ora nyenengake, amarga sampeyan kudu terus-terusan njaga apa sing ana ing tumpukan, lan kompiler ora mbantu.

Mulane, miturut pendapat kita, mung kabeneran kanggo orane Fift yaiku peran minangka basa inang kanggo Fift Assembler. Nanging apa ora luwih apik kanggo nampilake assembler TVM menyang sawetara basa sing wis ana, tinimbang nggawe sing anyar kanggo tujuan iki?

TVM Haskell eDSL

Saiki wektune kanggo ngomong babagan kontrak cerdas sing kapindho. Kita mutusake kanggo ngembangake dompet multi-signature, nanging nulis kontrak pinter liyane ing FunC bakal mboseni. We wanted kanggo nambah sawetara roso, lan iku basa assembly kita dhewe kanggo TVM.

Kaya Fift Assembler, basa anyar kita ditempelake, nanging kita milih Haskell minangka host tinimbang Fift, supaya kita bisa njupuk kauntungan saka sistem jinis majeng. Nalika nggarap kontrak cerdas, ing ngendi biaya kesalahan cilik bisa uga dhuwur banget, ngetik statis, miturut pendapat kita, minangka kauntungan gedhe.

Kanggo nduduhake apa TVM assembler katon kaya ditempelake ing Haskell, kita dipun ginakaken dompet standar ing. Ing ngisor iki sawetara perkara sing kudu digatekake:

  • Kontrak iki kalebu siji fungsi, nanging sampeyan bisa nggunakake akeh sing disenengi. Nalika sampeyan nemtokake fungsi anyar ing basa host (yaiku Haskell), eDSL kita ngidini sampeyan milih apa sampeyan pengin dadi rutinitas sing kapisah ing TVM utawa mung inline ing titik telpon.
  • Kaya Haskell, fungsi duwe jinis sing dicenthang ing wektu kompilasi. Ing eDSL kita, jinis input fungsi minangka jinis tumpukan sing dikarepake fungsi kasebut, lan jinis asil yaiku jinis tumpukan sing bakal diprodhuksi sawise telpon.
  • Kode kasebut nduweni anotasi stacktype, njlèntrèhaké jinis tumpukan samesthine ing titik telpon. Ing kontrak dompet asli iki mung komentar, nanging ing eDSL kita bener-bener dadi bagian saka kode lan dicenthang ing wektu kompilasi. Dheweke bisa dadi dokumentasi utawa pernyataan sing mbantu pangembang nemokake masalah yen kode ganti lan jinis tumpukan diganti. Mesthine, anotasi kasebut ora mengaruhi kinerja runtime, amarga ora ana kode TVM sing digawe kanggo dheweke.
  • Iki isih prototipe sing ditulis ing rong minggu, dadi isih akeh karya sing kudu ditindakake ing proyek kasebut. Contone, kabeh conto kelas sing sampeyan deleng ing kode ing ngisor iki kudu digawe kanthi otomatis.

Iki minangka implementasi dompet multisig ing eDSL kita:

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

Kode sumber lengkap kontrak eDSL lan dompet multi-tanda tangan bisa ditemokake ing gudang iki. Lan liyane marang ing rinci babagan basa sing dibangun, kolega kita Georgy Agapov.

Kesimpulan babagan kompetisi lan TON

Gunggunge, karya kita njupuk 380 jam (kalebu familiarization karo dokumentasi, rapat lan pembangunan nyata). Lima pangembang melu proyek kompetisi: CTO, pimpinan tim, spesialis platform blockchain lan pangembang piranti lunak Haskell.

Kita nemokake sumber daya kanggo melu kontes tanpa angel, amarga semangat hackathon, kerja tim sing cedhak, lan kabutuhan cepet nyemplungake awake dhewe ing aspek teknologi anyar mesthi nyenengake. Sawetara bengi sing ora bisa turu kanggo entuk asil maksimal ing kahanan sumber daya sing winates diimbangi karo pengalaman sing larang regane lan kenangan sing apik banget. Kajaba iku, nggarap tugas kasebut mesthi dadi tes sing apik babagan proses perusahaan, amarga angel banget kanggo entuk asil sing bener tanpa interaksi internal sing apik.

Lyrics aside: kita padha kesengsem dening jumlah karya sijine dening tim TON. Dheweke bisa mbangun sistem kerja sing rumit, ayu, lan sing paling penting. TON wis mbuktekake dhewe minangka platform kanthi potensial gedhe. Nanging, supaya ekosistem iki bisa berkembang, luwih akeh sing kudu ditindakake, ing babagan panggunaan ing proyek pamblokiran lan babagan nambah alat pangembangan. Kita bangga saiki dadi bagian saka proses iki.

Yen sawise maca artikel iki sampeyan isih duwe pitakon utawa duwe ide babagan cara nggunakake TON kanggo ngatasi masalah sampeyan, nulis kanggo kita - kita bakal seneng nuduhake pengalaman kita.

Source: www.habr.com

Add a comment