Ju sigurisht keni dëgjuar se Telegram . Por mund të keni humbur lajmin se së fundmi Telegram për realizimin e një ose më shumë kontratave smart për këtë platformë.
Ekipi i Serokell me përvojë të pasur në zhvillimin e projekteve të mëdha blockchain nuk mund të qëndronte indiferent. Ne deleguam pesë punonjës në konkurs, dhe vetëm pas dy javësh ata zënë vendin e parë nën (jo)modestin pseudonim Sexy Chameleon. Në këtë artikull do të flas për mënyrën se si ia dolën. Shpresojmë që gjatë dhjetë minutave të ardhshme të lexoni një histori interesante dhe ndoshta të gjeni diçka të dobishme, që mund ta aplikoni në punën tuaj.
Por le të fillojmë me një përmbledhje të shkurtër të kontekstit.
Konkursi dhe kushtet e tij
Pra, detyrat kryesore të pjesëmarrësve ishin realizimi i një ose më shumë nga kontratat smart të propozuara, si dhe ofrimi i sugjerimeve për përmirësimin e ekosistemit TON. Konkursi u zhvillua nga 24 Shtatori deri më 15 Tetor, dhe rezultatet u shpallën vetëm më 15 Nëntor. Mjaft vonë, duke marrë parasysh se në këtë kohë Telegram kishte kryer dhe shpallur rezultatet e konkurseve për dizajn dhe për zhvillimin e aplikacioneve në C++ për testimin dhe vlerësimin e cilësisë së thirrjeve VoIP në Telegram.
Ne zgjodhëm nga lista e propozuar nga organizatorët dy kontrata smart. Për njërën prej tyre përdorëm mjetet që shpërndahen me TON, ndërsa tjetrën e realizuam në një gjuhë të re, të zhvilluar nga inxhinierët tanë specifikisht për TON dhe të integruar në Haskell.
Zgjedhja e një gjuhe programimi funksionale nuk është rastësi. Në blogun tonë ne flasim shpesh përse e konsiderojmë kompleksitetin e gjuhëve funksionale si një teprim të madh dhe përse në përgjithësi i preferojmë ato të orientuara në objekt. Për më tepër, aty është edhe .
Pse vendosëm të merrnim pjesë
Në përmbledhje, sepse specializimi ynë është në projekte jo standarde dhe të ndërlikuara që kërkojnë aftësi të veçanta dhe shpesh paraqesin vlerë shkencore për komunitetin IT. Ne mbështesim me zjarr zhvillimin open-source dhe angazhohemi për popullarizimin e tij, si dhe bashkëpunojmë me universitetet kryesore të Rusisë në fushën e shkencave kompjuterike dhe matematikës.
Detyrat interesante tĂ« konkursit dhe pĂ«rfshirja nĂ« njĂ« projekt qĂ« e duam ka qenĂ« njĂ« motivim i shkĂ«lqyer, ndĂ«rsa fondi i çmimeve ishte njĂ« stimul shtesĂ«. đ
Kërkimi i blockchain-it TON
Ne ndjekim me vijimĂ«si zhvillimet e reja nĂ« blockchain, inteligjencĂ«n artificiale dhe mĂ«simin e makinerive dhe pĂ«rpiqemi tĂ« mos humbasim asnjĂ« lançim tĂ« rĂ«ndĂ«sishĂ«m nĂ« çdo fushĂ« ku punojmĂ«. Prandaj, nĂ« momentin e fillimit tĂ« konkursit ekipi ynĂ« ishte tashmĂ« i njohur me idetĂ« nga . MegjithatĂ«, pĂ«rpara fillimit tĂ« punĂ«s me TON nuk kishim analizuar dokumentacionin teknik dhe kodin origjinal tĂ« platformĂ«s, kĂ«shtu qĂ« hapi i parĂ« ishte mjaft i qartĂ« â njĂ« kĂ«rkim i kujdesshĂ«m i dokumentacionit zyrtar nĂ« dhe nĂ« .
NĂ« fillim tĂ« konkursit kodi ishte tashmĂ« i publikuar, kĂ«shtu qĂ«, pĂ«r tĂ« kursyer kohĂ«, ne vendosĂ«m tĂ« kĂ«rkojmĂ« njĂ« udhĂ«zues ose njĂ« pĂ«rmbledhje tĂ« shkruar nga pĂ«rdoruesit. FatkeqĂ«sisht, kjo nuk dha rezultate â pĂ«rveç udhĂ«zimeve pĂ«r ndĂ«rtimin e platformĂ«s nĂ« Ubuntu, nuk gjetĂ«m materiale tĂ« tjera.
Dokumentacioni i vetë ka qenë i punuar me kujdes, por leximi i tij në disa momente ishte i vështirë. Shpesh na duhej të ktheheshim në pika të caktuara dhe të kalonim nga përshkrimet e nivelit të lartë të ideve abstrakte në detaje të nivelit të ulët të realizimit.
Do të ishte më e lehtë nëse në specifikim nuk do të kishte përshkrime të detajuara të realizimit. Informacioni se si makina virtuale paraqet stekimin e saj, më shumë e shpërqendron zhvilluesit që krijojnë kontrata smart për platformën TON, sesa e ndihmon ata.
Nix: ndërtimi i projektit
Në Serokell ne jemi adhurues të mëdhenj . Ne e ndërtuam projektet tona dhe i implementojmë me ndihmën e , dhe të gjithë serverët tanë kanë të instaluar . Falë kësaj, të gjitha ndërtimet tona janë të riprodhueshme dhe funksionojnë nën çdo sistem operativ mbi të cilin mund të instaloni Nix.
Prandaj, ne filluam me krijimin e . Me ndihmën e tij, të kompilosh TON është maksimalisht e thjeshtë:
$ cd ~/.config/nixpkgs/overlays && git clone https://github.com/serokell/ton.nix
$ cd /path/to/ton/repo && nix-shell
[nix-shell]$ cmakeConfigurePhase && makeVini re, nuk keni nevojë të instaloni asnjë varësi. Nix e bën mrekullinë për ju pavarësisht nëse po përdorni NixOS, Ubuntu apo macOS.
Programimi për TON
Kodi i kontraktit të mençur në TON Network ekzekutohet në TON Virtual Machine (TVM). TVM është më komplekse se shumica e makinave të tjera virtuale dhe ka shumë funksionalitete interesante, për shembull, ajo mund të punojë me vazhdimet (continuations) dhe lidhjet me të dhëna.
Më tepër, ekipi i TON krijoi tre gjuhë të reja programimi:
Fift â njĂ« gjuhĂ« programimi universale e tipit stack, e cila ngjan me . Superfuqia e saj Ă«shtĂ« mundĂ«sia pĂ«r tĂ« interaguar me TVM.
FunC â njĂ« gjuhĂ« programimi pĂ«r kontraktet e mençura, e cila Ă«shtĂ« e ngjashme me dhe kompilon nĂ« njĂ« gjuhĂ« tjetĂ«r â Fift Assembler.
Fift Assembler â njĂ« bibliotekĂ« Fift pĂ«r gjenerimin e kodit ekzekutiv binar pĂ«r TVM. Fift Assembler nuk ka kompjilator. Ky Ă«shtĂ« .
Këto janë punët tona konkurruese
Më në fund, është koha për të parë rezultatet e përpjekjeve tona.
Kanal pagesash i asinkronizuar
Kanal pagesash (payment channel) â Ă«shtĂ« njĂ« kontrakt inteligjent qĂ« lejon dy pĂ«rdorues tĂ« dĂ«rgojnĂ« pagesa jashtĂ« blockchain. Si rezultat, jo vetĂ«m qĂ« kursehen para (nuk ka komision), por edhe koha (nuk Ă«shtĂ« e nevojshme tĂ« presĂ«sh pĂ«r pĂ«rpunimin e bllokut tĂ« ardhshĂ«m). Pagesat mund tĂ« jenĂ« sa mĂ« tĂ« vogla dhe tĂ« ndodhin sa herĂ« qĂ« Ă«shtĂ« e nevojshme. NĂ« tĂ« njĂ«jtĂ«n kohĂ«, palĂ«t nuk duhet tĂ« besojnĂ« njĂ«ra-tjetrĂ«n, pasi drejtĂ«sia e llogaritjes pĂ«rfundimtare garanton nga kontrakti inteligjent.
Ne gjetĂ«m njĂ« zgjidhje mjaft tĂ« thjeshtĂ« pĂ«r problematikĂ«n. TĂ« dy palĂ«t mund tĂ« ndajnĂ« mesazhe tĂ« nĂ«nshkruara, secila prej tĂ« cilave pĂ«rmban dy numra â shumĂ«n totale tĂ« paguar nga secili nga pjesĂ«marrĂ«sit. KĂ«ta dy numra veprojnĂ« si nĂ« sistemet tradicionale tĂ« shpĂ«rndara dhe pĂ«rcaktojnĂ« rendin "ka ndodhur para" nĂ« transaksione. Duke pĂ«rdorur kĂ«to tĂ« dhĂ«na, kontrakti mund tĂ« zgjidhĂ« çdo konflikt tĂ« mundshĂ«m.
Në të vërtetë, për realizimin e kësaj ideje mjafton një numër, por ne e lanë të dy, sepse kështu arritëm të krijojmë një ndërfaqe përdoruesi më të përshtatshme. Përveç kësaj, vendosëm të përfshimë në çdo mesazh madhësinë e pagesës. Pa të, nëse mesazhi humbet për ndonjë arsye, atëherë megjithëse të gjitha shumat dhe llogaritja përfundimtare do të ishin të sakta, përdoruesi mund të mos e vërë re humbjen.
Për të testuar idenë tonë, kërkuam shembuj të përdorimit të një protokolli të tillë të thjeshtë dhe të qartë të kanalit të pagesave. Për t'u befasuar, gjetëm vetëm dy:
- një qasje të ngjashme, vetëm për një kanal njëdrejtimor.
- , i cili përshkruan të njëjtën ide si ne, vetëm pa shpjegimin e shumë detajeve të rëndësishme, si saktësia e përgjithshme dhe procedura e zgjidhjes së konflikteve.
U bë e qartë se kishte kuptim të përshkruanim protokollin tonë në detaje, duke i kushtuar vëmendje të veçantë saktësisë së tij. Pas disa iteracioneve, specifikimi ishte gati, dhe tani edhe ju mund të .
Ne implementuam kontratën në FunC, dhe utilitarin e komandës për të ndërvepruar me kontratën tonë e shkruam plotësisht në Fift, ashtu siç rekomandonin organizatorët. Mund të kishim zgjedhur çdo gjuhë tjetër për CLI-së tonë, por ishte interesante të provonim pikërisht Fift, për të parë se si do të sillte në praktikë.
Me sinqeritet, pasi punuam me Fift, nuk pamë arsye të forta për të preferuar këtë gjuhë ndaj gjuhëve të popullarizuara dhe aktivisht të përdorura me instrumente dhe biblioteka të zhvilluar. Të programosh në një gjuhë të tipit stack është mjaft e pakëndshme, pasi duhet të mbash mend vazhdimisht se çfarë është ku në stack, dhe kompajleri nuk ndihmon në këtë.
Prandaj, justifikimi i vetëm, sipas mendimit tonë, për ekzistencën e Fift është roli i tij si gjuhë host për Fift Assembler. Por a nuk do të ishte më mirë të integrohej asambleja e TVM në ndonjë gjuhë ekzistuese, sesa të krijohej një e re për këtë, në esencë, qëllim të vetëm?
TVM Haskell eDSL
Tani ka ardhur koha për t'i treguar rreth kontraktit tonë të dytë të mençur. Ndezëm të zhvillonim një portofol me shumë nënshkresa, por të shkruajmë një kontrakt të ri të mençur në FunC do të ishte tepër e mërzitshme. Donim të shtonim ndonjë pikë të veçantë, dhe ajo ishte gjuha jonë e vetme e asamblesë për TVM.
Si dhe Fift Assembler, gjuha jonë e re është e integruar, vetëm se si host zgjodhëm Haskell, duke na lejuar të shfrytëzojmë sistemin e tij të avancuar të llojeve. Gjatë punës me kontraktet e mençura, ku çmimi i një gabimi të vogël mund të jetë shumë i lartë, tipizimi statik, sipas mendimit tonë, është një avantazh i madh.
Për të demonstruar se si duket asambleja e TVM e integruar në Haskell, ne implementuam një portofol standard në të. Ja disa gjëra që meritojnë vëmendje:
- Ky questo kontrakt është i përbërë nga një funksion, por ju mund të përdorni aq shumë sa të dëshironi. Kur përcaktoni një funksion të ri në gjuhën pritëse (dmth, në Haskell), eDSL ynë ju lejon të zgjidhni nëse dëshironi që ai të kthehet në një nënprogram të veçantë në TVM apo thjesht të përfshihet në vendin e thirrjes.
- Si në Haskell, funksionet kanë tipe që verifikohen gjatë kompilimit. Në eDSL tonë tipi i hyrjes së funksionit është tipi i grumbullit që funksioni pret, dhe tipi i rezultatit është tipi i grumbullit që do të del pas thirrjes.
- Ka anotacione në kod
stacktype, që përshkruajnë tipin e pritur të grumbullit në pikën e thirrjes. Në kontraktin origjinal të portofolit, ato ishin thjesht komente, por në eDSL tonë ato janë në fakt pjesë e kodit dhe kontrollohen gjatë kompilimit. Ato mund të shërbejnë si dokumentacion ose deklarata që ndihmojnë zhvilluesin të gjejë një problem në rast se tipi i grumbullit ndryshon gjatë ndryshimit të kodit. Natyrisht, këto anotacione nuk ndikojnë në performancën gjatë ekzekutimit, pasi për to nuk gjenerohet ndonjë kod TVM. - Ky është ende një prototip, shkruar brenda dy javëve, prandaj projekti ka ende shumë punë për t'u bërë. Për shembull, të gjitha instancat e klasave që shihni në kodin e mëposhtëm duhet të krijohen automatikisht.
Ja si duket implementimi i portofolit multisig në eDSL tonë:
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 @Word32Kodin e plotë burimor të eDSL tonë dhe kontraktin e portofolit multisig mund ta gjeni në Ndërsa më rreth gjuhëve të integruara kolegu ynë Georgiy Agapov.
Përfundimet mbi garën dhe TON
Në total, puna jonë zuri 380 orë (përfshirë njohjen me dokumentacionin, takimet dhe zhvillimin në vetvete). Në projektin konkurues morën pjesë pesë zhvillues: CTO, lideri i ekipit, specialistë të platformave blockchain dhe zhvillues të software-it në Haskell.
Burimet pĂ«r tĂ« marrĂ« pjesĂ« nĂ« konkurs i gjetĂ«m pa vĂ«shtirĂ«si, sepse fryma e hackathon-it, puna e ngushtĂ« nĂ« ekip, nevoja pĂ«r njĂ« zhytje tĂ« shpejtĂ« nĂ« aspektet e teknologjive tĂ« reja â Ă«shtĂ« gjithmonĂ« erĂ« dhe interesante. Disa natĂ« pa gjumĂ« pĂ«r tĂ« arritur rezultate maksimale nĂ« kushte tĂ« kufizuara burimesh kompensohen me pĂ«rvojĂ« tĂ« çmuar dhe kujtime tĂ« shkĂ«lqyera. PĂ«r mĂ« tepĂ«r, puna nĂ« kĂ«tĂ« lloj detyrash Ă«shtĂ« gjithmonĂ« njĂ« test i mirĂ« pĂ«r proceset e kompanisĂ«, pasi tĂ« arrihen rezultate me vlerĂ« pa njĂ« bashkĂ«punim tĂ« shkĂ«lqyer tĂ« brendshĂ«m Ă«shtĂ« jashtĂ«zakonisht e vĂ«shtirĂ«.
Përveç lirizmit: ne ishim të impresionuar nga volumi i punës të bërë nga ekipi TON. Ata arritën të ndërtuan një sistem të ndërlikuar, të bukur, dhe më e rëndësishmja, funksional. TON u tregua si një platformë me potencial të madh. Megjithatë, për të siguruar që kjo ekosistem të zhvillohet, ka ende shumë punë për t'u bërë, si në aspektin e përdorimit të saj në projektet blockchain, ashtu edhe në aspektin e përmirësimit të mjeteve të zhvillimit. Ne jemi të krenarë që tani jemi pjesë e këtij procesi.
NĂ«se pas leximit tĂ« kĂ«tij artikulli ju mbetĂ«n pyetje ose keni ide se si tĂ« aplikoni TON pĂ«r zgjidhjen e detyrave tuaja, â ne me kĂ«naqĂ«si do tĂ« ndajmĂ« pĂ«rvojĂ«n tonĂ«.
Burimi: habr.com
