Anda mungkin pernah mendengar bahwa Telegram akan meluncurkan platform blockchain Ton . Tapi Anda bisa melewatkan berita bahwa belum lama ini Telegram mengumumkan kompetisi untuk implementasi satu atau lebih kontrak pintar untuk platform ini.
Tim Serokell dengan pengalaman yang kaya dalam mengembangkan proyek-proyek blockchain besar tidak bisa menjauh. Kami mendelegasikan lima karyawan ke kontes, dan dua minggu kemudian mereka mengambil tempat pertama di bawahnya dengan julukan acak sederhana (tidak) Sexy Chameleon. Dalam artikel ini saya akan berbicara tentang bagaimana mereka berhasil. Kami berharap bahwa dalam sepuluh menit ke depan Anda setidaknya akan membaca cerita yang menarik, dan paling banyak Anda akan menemukan sesuatu yang berguna di dalamnya yang dapat Anda terapkan dalam pekerjaan Anda.
Tapi mari kita mulai dengan sedikit menyelam ke dalam konteksnya.
Persaingan dan kondisinya
Jadi, tugas utama para peserta adalah implementasi satu atau lebih dari kontrak pintar yang diusulkan, serta membuat proposal untuk meningkatkan ekosistem TON. Kompetisi diadakan dari 24 September hingga 15 Oktober, dan hasilnya diumumkan hanya pada 15 November. Untuk waktu yang lama, mengingat bahwa selama ini Telegram berhasil melakukan dan mengumumkan hasil kontes pada desain dan pengembangan aplikasi dalam C ++ untuk menguji dan mengevaluasi kualitas panggilan VoIP di Telegram.
Kami memilih dua kontrak pintar dari daftar yang diusulkan oleh penyelenggara. Untuk salah satu dari mereka, kami menggunakan alat yang didistribusikan dengan TON, dan yang kedua kami implementasikan dalam bahasa baru yang dikembangkan oleh para insinyur kami secara khusus untuk TON dan terintegrasi dengan Haskell.
Pilihan bahasa pemrograman fungsional tidak disengaja. Di blog korporat kami , kami sering berbicara tentang mengapa kami menganggap kompleksitas bahasa fungsional sebagai hal yang berlebihan dan mengapa kami umumnya memilih mereka untuk berorientasi objek. Ngomong-ngomong, itu juga berisi yang asli dari artikel ini .
Mengapa kami memutuskan untuk berpartisipasi
Singkatnya, karena spesialisasi kami adalah proyek non-standar dan kompleks yang memerlukan keterampilan khusus dan seringkali bernilai ilmiah bagi komunitas TI. Kami dengan hangat mendukung pengembangan open-source dan terlibat dalam popularisasi, serta bekerja sama dengan universitas-universitas terkemuka di Rusia di bidang ilmu komputer dan matematika.
Tugas-tugas menarik dari kontes dan keterlibatan dalam proyek Telegram, yang sangat kami cintai, dalam diri mereka sendiri adalah motivasi yang sangat baik, tetapi dana hadiah menjadi insentif tambahan. :)
Penelitian TON Blockchain
Kami memantau dengan cermat perkembangan baru dalam blockchain, kecerdasan buatan dan pembelajaran mesin dan berusaha untuk tidak melewatkan satu pun rilis signifikan di setiap area tempat kami bekerja. Karena itu, pada saat kompetisi dimulai, tim kami sudah terbiasa dengan ide-ide dari TON white paper . Namun, sebelum mulai bekerja dengan TON, kami tidak menganalisis dokumentasi teknis dan kode sumber aktual platform, sehingga langkah pertama cukup jelas - studi menyeluruh tentang dokumentasi resmi di situs web dan di repositori proyek .
Pada awal kontes, kode sudah diterbitkan, jadi untuk menghemat waktu, kami memutuskan untuk mencari panduan atau memeras yang ditulis oleh pengguna . Sayangnya, ini tidak memberikan hasil - terlepas dari instruksi untuk membangun platform di Ubuntu, kami tidak menemukan bahan lain.
Dokumentasi itu sendiri dikembangkan secara menyeluruh, tetapi sulit untuk membacanya di beberapa titik. Cukup sering, kami harus kembali ke poin-poin tertentu dan beralih dari deskripsi ide abstrak tingkat tinggi ke detail implementasi level rendah.
Akan lebih mudah jika spesifikasi sama sekali tidak memiliki deskripsi implementasi. Informasi tentang bagaimana mesin virtual menyajikan tumpukannya lebih mengganggu bagi pengembang yang membuat kontrak pintar untuk platform TON daripada membantu mereka.
Nix: membangun proyek
Di Serokell, kami adalah penggemar berat Nix . Kami mengumpulkan proyek kami untuk mereka dan menggunakan mereka menggunakan NixOps , dan NixOS diinstal pada semua server kami. Berkat ini, semua build kami dapat direproduksi dan bekerja di bawah sistem operasi apa pun tempat Nix dapat diinstal.
Jadi kami mulai dengan membuat overlay Nix dengan ekspresi untuk membangun TON . Menggunakannya untuk mengkompilasi TON sesederhana mungkin:
$ cd ~/.config/nixpkgs/overlays && git clone https://github.com/serokell/ton.nix $ cd /path/to/ton/repo && nix-shell [nix-shell]$ cmakeConfigurePhase && make
Perhatikan bahwa Anda tidak perlu menginstal dependensi apa pun. Nix secara ajaib akan melakukan segalanya untuk Anda, apakah Anda menggunakan NixOS, Ubuntu atau macOS.
Pemrograman untuk TON
Kode kontrak pintar TON Network dijalankan pada TON Virtual Machine (TVM). TVM lebih rumit daripada kebanyakan mesin virtual lainnya, dan memiliki fungsionalitas yang sangat menarik, misalnya, ia dapat bekerja dengan kelanjutan dan tautan ke data .
Selain itu, TON guys menciptakan tiga bahasa pemrograman baru:
Fift adalah bahasa pemrograman stack universal yang mengingatkan pada Forth . Kemampuan supernya adalah kemampuan untuk berinteraksi dengan TVM.
FunC adalah bahasa pemrograman kontrak pintar yang mirip dengan C dan dikompilasi ke bahasa lain - Fift Assembler.
Fift Assembler - Fift library untuk menghasilkan kode biner yang dapat dieksekusi untuk TVM. Fift Assembler tidak memiliki kompiler. Ini adalah bahasa khusus domain tertanam (eDSL) .
Karya kompetitif kami
Akhirnya, saatnya untuk melihat hasil dari upaya kami.
Saluran Pembayaran Asinkron
Saluran pembayaran - kontrak pintar yang memungkinkan dua pengguna untuk mengirim pembayaran di luar blockchain. Akibatnya, tidak hanya uang yang disimpan (tidak ada komisi), tetapi juga waktu (Anda tidak harus menunggu sampai blok berikutnya diproses). Pembayaran dapat kecil dan sewenang-wenang dan terjadi sesering yang diperlukan. Pada saat yang sama, para pihak tidak perlu saling mempercayai, karena keadilan penyelesaian akhir dijamin oleh kontrak yang cerdas.
Kami menemukan solusi yang cukup sederhana untuk masalah ini. Dua pihak dapat bertukar pesan yang ditandatangani, masing-masing berisi dua angka - jumlah total yang dibayarkan oleh masing-masing peserta. Dua angka ini bekerja seperti jam vektor dalam sistem terdistribusi tradisional dan mengatur urutan "terjadi sebelum" pada transaksi. Dengan menggunakan data ini, kontrak akan dapat menyelesaikan kemungkinan konflik.
Sebenarnya, untuk mengimplementasikan ide ini, satu angka sudah cukup, tetapi kami meninggalkan keduanya, karena kami dapat membuat antarmuka pengguna yang lebih nyaman. Selain itu, kami memutuskan untuk memasukkan jumlah pembayaran dalam setiap pesan. Tanpanya, jika pesan hilang karena beberapa alasan, maka meskipun semua jumlah dan perhitungan akhir akan benar, pengguna mungkin tidak melihat kehilangan.
Untuk menguji ide kami, kami mencari contoh penggunaan protokol saluran pembayaran yang sederhana dan ringkas. Yang mengejutkan, kami hanya menemukan dua:
- Deskripsi pendekatan yang serupa, hanya untuk saluran searah.
- Tutorial yang menjelaskan ide yang sama dengan kami, tetapi tanpa menjelaskan banyak detail penting, seperti kebenaran umum dan prosedur untuk menyelesaikan konflik.
Menjadi jelas bahwa masuk akal untuk menggambarkan protokol kami secara rinci, memberikan perhatian khusus pada kebenarannya. Setelah beberapa iterasi, spesifikasinya sudah siap, dan sekarang Anda juga dapat melihatnya.
Kami menerapkan kontrak untuk FunC, dan kami menulis utilitas baris perintah untuk berinteraksi dengan kontrak kami di Fift, sesuai rekomendasi panitia. Kami dapat memilih bahasa lain untuk CLI kami, tetapi menarik bagi kami untuk mencoba Fift untuk melihat bagaimana itu menunjukkan dirinya dalam tindakan.
Sejujurnya, setelah bekerja dengan Fift, kami melihat tidak ada alasan yang baik untuk memilih bahasa ini daripada bahasa yang populer dan digunakan secara aktif dengan alat dan perpustakaan yang dikembangkan. Pemrograman dalam bahasa stack agak tidak menyenangkan, karena Anda harus selalu mengingat apa yang ada di stack, dan kompiler tidak membantu.
Oleh karena itu, satu-satunya, menurut pendapat kami, pembenaran untuk keberadaan Fift adalah perannya sebagai bahasa utama untuk Fift Assembler. Tapi bukankah lebih baik menanamkan assembler TVM dalam beberapa bahasa yang ada, dan tidak membuat yang baru untuk ini, pada dasarnya satu-satunya tujuan?
TVM Haskell eDSL
Sekarang saatnya berbicara tentang kontrak pintar kedua kami. Kami memutuskan untuk mengembangkan dompet multi-tanda tangan, tetapi menulis kontrak pintar lain di FunC akan terlalu membosankan. Kami ingin menambahkan beberapa semangat, dan itu menjadi bahasa rakitan kami sendiri untuk TVM.
Seperti Fift Assembler, bahasa baru kami dapat disematkan, tetapi alih-alih Fift kami memilih Haskell sebagai tuan rumah, yang memungkinkan kami untuk sepenuhnya menggunakan sistem tipe canggihnya. Ketika bekerja dengan kontrak pintar, di mana harga kesalahan kecil sekalipun bisa sangat tinggi, pengetikan statis, menurut kami, adalah keuntungan besar.
Untuk menunjukkan seperti apa assembler TVM yang ada di Haskell, kami menerapkan dompet standar di atasnya. Berikut adalah beberapa hal yang harus diperhatikan:
- Kontrak ini terdiri dari satu fungsi, tetapi Anda dapat menggunakan sebanyak yang Anda suka. Ketika Anda mendefinisikan fungsi baru dalam bahasa host (yaitu, di Haskell), eDSL kami memungkinkan Anda untuk memilih apakah Anda ingin mengubahnya menjadi subprogram terpisah di TVM atau hanya dibangun di tempat panggilan.
- Seperti Haskell, fungsi memiliki tipe yang diperiksa pada waktu kompilasi. Dalam eDSL kami, tipe input fungsi adalah tipe stack yang diharapkan fungsi, dan tipe hasilnya adalah tipe stack yang akan diperoleh setelah panggilan.
- Kode ini memiliki anotasi
stacktype
yang menggambarkan tipe stack yang diharapkan pada rekan panggilan. Dalam kontrak dompet asli, ini hanya komentar, tetapi dalam eDSL kami, mereka sebenarnya adalah bagian dari kode dan diperiksa pada waktu kompilasi. Mereka dapat berfungsi sebagai dokumentasi atau pernyataan yang membantu pengembang menemukan masalah jika tipe tumpukan berubah seiring perubahan kode. Tentu saja, anotasi semacam itu tidak memengaruhi kinerja runtime, karena tidak ada kode TVM yang dihasilkan untuknya. - Ini masih merupakan prototipe yang ditulis dalam dua minggu, jadi masih banyak pekerjaan yang harus dilakukan pada proyek. Misalnya, semua instance kelas yang Anda lihat dalam kode di bawah ini harus dihasilkan secara otomatis.
Inilah yang terlihat seperti implementasi dompet multisig di eDSL kami:
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]
Kode sumber lengkap dari eDSL kami dan kontrak dompet multi-tanda tangan dapat ditemukan di repositori ini. Dan secara lebih rinci kolega kami George Agapov berbicara tentang bahasa bawaan.
Kesimpulan tentang kompetisi dan TON
Secara total, pekerjaan kami memakan waktu 380 jam (bersama dengan kenalan dengan dokumentasi, pertemuan, dan pengembangan itu sendiri). Lima pengembang ikut serta dalam kompetisi: STO, pemimpin tim, spesialis platform blockchain, dan pengembang perangkat lunak Haskell.
Kami menemukan sumber daya untuk berpartisipasi dalam kontes tanpa kesulitan, karena semangat hackathon, kerja tim yang erat, kebutuhan untuk perendaman cepat dalam aspek teknologi baru selalu menarik. Beberapa malam tanpa tidur untuk mencapai hasil maksimal dalam kondisi sumber daya terbatas dikompensasi oleh pengalaman berharga dan kenangan indah. Selain itu, mengerjakan tugas-tugas seperti itu selalu merupakan ujian yang baik untuk proses perusahaan, karena sangat sulit untuk mencapai hasil yang benar-benar layak tanpa interaksi internal yang sangat baik.
Terlepas dari lirik: kami terkesan dengan jumlah pekerjaan yang dilakukan oleh tim TON. Mereka berhasil membangun sistem kerja yang kompleks, indah, dan yang paling penting. TON terbukti sebagai platform dengan potensi besar. Namun, agar ekosistem ini berkembang, masih banyak yang harus dilakukan, baik dalam hal penggunaannya dalam proyek-proyek blockchain maupun dalam hal meningkatkan alat pengembangan. Kami bangga menjadi bagian dari proses ini sekarang.
Jika setelah membaca artikel ini Anda masih memiliki pertanyaan atau ide tentang cara menerapkan TON untuk menyelesaikan masalah Anda, kirimkan kepada kami - kami dengan senang hati akan berbagi pengalaman kami.