Olete tõenäoliselt kuulnud, et Telegram Kuid võisite jääda ilma uudisest, et hiljuti kuulutas Telegram ühe või mitme nutika lepingu rakendamiseks selle platvormi jaoks.
Serokelli meeskond, kellel on rohkelt kogemusi suurte plokiahela projektide arendamisel, ei saanud kõrvale jääda. Me delegeerisime konkursile viis töötajat, ja juba kahe nädala pärast saavutasid nad seal esimese koha (mitte)alatu suvalise hüüdnimega Sexy Chameleon. Selles artiklis räägin, kuidas nad selle saavutasid. Loodame, et järgmise kümne minuti jooksul loete vähemalt huvitavat lugu ja maksimumi ulatuses leiate sealt midagi kasulikku, mida saate oma töös rakendada.
Aga alustame väikese sissejuhatusega konteksti.
Konkurs ja selle tingimused
Nii et osalejate peamised ülesanded olid ühe või enama pakutud nutika lepingu rakendamine ning ettepanekute esitamine TON-i ökosüsteemi parandamiseks. Konkurs toimus 24. septembrist kuni 15. oktoobrini, tulemused kuulutati välja alles 15. novembril. See on päris kaua, arvestades, et selle aja jooksul jõudis Telegram korraldada ja kuulutada välja disaini- ja C++ rakenduste arendamise konkursid, et testida ja hinnata VoIP-kõnede kvaliteeti Telegramis.
Valisime korraldajate pakutud nimekirjast kaks nutikat lepingut. Ühe jaoks kasutasime TON-iga koos levitatavaid tööriistu, teise realiseerisime uuel keelel, mille meie insenerid spetsiaalselt TON-i jaoks lõid ja Haskelli sisse ehitasid.
Funktsionaalse programmeerimiskeele valik ei ole juhuslik. Meie räägime sageli, miks peame funktsionaalsete keelte keerukust suureks liialduseks ja miks eelistaime neid üldiselt objekt-orienteeritud keeledele. Muide, seal on ka .
Miks me üldse otsustasime osaleda
Lühidalt, kuna meie spetsialiseerumine on mittestandardsetele ja keerukatele projektidele, mis nõuavad erilisi oskusi ja toovad sageli teaduslikku väärtust IT-kogukonnale. Me toetame innukalt avatud lähtekoodiga arendust ja tegeleme selle populariseerimisega, tehes koostööd Venemaa juhtivate ülikoolidega arvutiteaduse ja matemaatika vallas.
Konkursi huvitavad ülesanded ja osalemine meie armastatud projektis Telegram on iseenesest olnud suurepärane motivatsioon, kuid auhinnafond oli lisaks stiimuliks. 🙂
TON-i plokiahela uurimine
Me jälgime tähelepanelikult uusi arenguid plokiahelas, tehisintellektis ja masinõppes ning püüame mitte jätta tähelepanuta ühtki olulist väljaannet igas valdkonnas, millega tegeleme. Seetõttu, kui konkurss algas, oli meie meeskond juba tuttav ideedega, mis olid . Siiski, enne TON-iga töötamise alustamist ei analüüsinud me tehnilist dokumentatsiooni ja tegelikku lähtekoodi, seega oli esimene samm piisavalt ilmne — ametliku dokumentatsiooni põhjalik uurimine. ja .
Konkursi alguses oli kood juba avaldatud, seega, et aega säästa, otsustasime otsida juhendit või kokkuvõtet, mille on kirjutanud kasutajad. Kahjuks ei toonud see tulemusi – peale platvormi ehitamise juhendi Ubuntu puhul, ei leidnud me mingeid muid materjale.
Dokumentatsioon osutus hoolikalt välja töötatuks, kuid mõnes kohas oli seda keeruline lugeda. Saime sageli tagasi pöörduda teatud punktide juurde ja vahetada kõrgtasemelisi abstraktsete ideede kirjeldusi madalama taseme teostuse detailide vastu.
Oleks lihtsam, kui spetsifikatsioonis ei oleks üldse detailset teostuse kirjeldust. Informatsioon selle kohta, kuidas virtuaalmasin oma steke esindab, pigem segab TON platvormi jaoks nutilepingute loomise arendajaid, kui aitab neid.
Nix: kogume projekti
Serokellis oleme suured fännid . Kogume oma projekte ja viime need ellu kasutades , ja kõigil meie serveritel on see paigaldatud. . Tänu sellele on kõik meie ehitused kordumatud ja töötavad igas operatsioonisüsteemis, kuhu Nixi saab paigaldada.
Seega alustasime selle loomisega . Selle abil saab TONi maksimaalselt lihtsalt kokku panna:
$ cd ~/.config/nixpkgs/overlays && git clone https://github.com/serokell/ton.nix
$ cd /tee/ton/repo && nix-shell
[nix-shell]$ cmakeConfigurePhase && makePange tähele, et teil ei ole vaja installida mingeid sõltuvusi. Nix teeb kõik teie eest maagiliselt, sõltumata sellest, kas kasutate NixOS-i, Ubuntu-d või macOS-i.
Programmeerimine TONi jaoks
TON Networki nutikad lepingud täidetakse TON virtuaalses masinas (TVM). TVM on keerulisem kui enamik teisi virtuaalseid masinaid ja omab väga huvitavat funktsionaalsust, näiteks oskab ta töötada jatkudega (continuations) ja andmesse viidete.
Veelgi enam, TONi meeskond on loonud koguni kolm uut programmeerimiskeelt:
Fift — universaalne virnastamise programmeerimiskeel, mis meenutab . Selle ülim võime on suhelda TVM-iga.
FunC — nutilepingute programmeerimiskeel, mis sarnaneb ja kompileeritakse veel üheks keeleks — Fift assembleri.
Fift assembler — Fift raamatukogu TVM-i kahepanuse genereerimiseks. Fift assembleril puudub kompilaator. See on .
Meie konkursitööd
Lõpuks on aeg vaadata meie pingutuste tulemusi.
Asünkroonne makseteenus
Makseteenus (payment channel) on nutileping, mis võimaldab kahe kasutaja saata makseid väljaspool plokiahelat. Selle tulemusena säästetakse mitte ainult raha (komisjoni pole), vaid ka aega (te ei pea ootama, kuni järgmine plokk töödeldakse). Makseid saab teha lõputult väikeseks ja nii tihti, kui vajalik. Samuti ei pea osalised üksteisele usaldama, kuna lõpparve õiglus on garanteeritud nutilepinguga.
Oleme leidnud üsna lihtsa lahenduse probleemile. Kaks osalust saavad vahetada allkirjastatud sõnumeid, millest igaühes on kaks numbrit — iga osalise poolt tasutud kogusumma. Need kaks numbrit toimivad nagu traditsioonilistes jaotatud süsteemides ja määravad „toimu kui“ järjekorra tehingutele. Kasutades neid andmeid, suudab leping lahendada mis tahes võimaliku konflikti.
Tõepoolest, selle idee elluviimiseks piisab ühest numbrist, kuid me jätsime mõlemad, et pakkuda mugavamat kasutajaliidest. Lisaks otsustasime igas sõnumis esitada makse summa. Ilma selleta, kui sõnum mingil põhjusel kaob, võib kasutaja kaotust mitte märgata, kuigi kõik summad ja lõplik arvestus on õiged.
Kuna meie ideed testida, otsisime näiteid sellise lihtsa ja lakoonilise maksekanali protokolli kasutamisest. Üllatuseks leidsime vaid kaks:
- sarnast lähenemist, kuid ühe suunalise kanali juhtumile.
- , kus on kirjeldatud sama ideed kui meil, aga ilma paljude oluliste detailide, nagu üldine õigsus ja konfliktide lahendamise protseduur, selgituseta.
Saime aru, et on mõistlik põhjalikult kirjeldada meie protokolli, pöörates erilist tähelepanu selle õigsusele. Pärast mitmeid iteratsioone oli spetsifikatsioon valmis, ja nüüd saate ka .
Me oleme ellu viinud lepingu FunCiga, ning meie CLI-tööriist, mis suhtleb meie lepinguga, on täielikult kirjutatud Fiftis, nagu soovitasid korraldajad. Me oleksime võinud valida mistahes muu keele meie CLI jaoks, kuid meid huvitas Fifti proovimine, et näha, kuidas see praktikas tulemuseks osutub.
Ausalt öeldes, olles töötanud Fiftiga, ei leidnud me olulisi põhjuseid, miks eelistada seda keelt populaarsetele ja aktiivselt kasutatavatele keelemudelitele, millel on arenenud tööriistade ja raamatukogude kogum. Steekkeelt kasutada on üsna ebamugav, kuna tuleb pidevalt meeles pidada, mis kus asub steedis, ning kompilaator selles osas ei aita.
Seega on meie arvates Fifti ainus õigustus eksisteerimiseks tema roll Fift Assembleri host-keelena. Kas ei oleks olnud parem integreerida TVM assembler mõne olemasolevasse keelde, mitte leiutada uut vaid selle ühekordse eesmärgi jaoks?
TVM Haskell eDSL
Nüüd on aeg rääkida meie teisest nutilepingust. Otsustasime arendada mitme allkirjaga rahakoti, kuid kirjutada veel üks nutileping FunC'is oleks liiga igav. Soovisime lisada midagi põnevat, ning selleks sai meie enda assembleri keel TVM jaoks.
Nagu Fift Assembler, on meie uus keel sisseehitatud, kuid Fikti asemel valisime hostiks Haskelli, mis võimaldas meil täielikult ära kasutada selle arenenud tüüpsüsteemi. Nutilepingute juures, kus isegi väikse vea hind võib olla ülimalt kõrge, on staatiline tüüpimine meie arvates suur eelis.
Kuna demonstreerida, kuidas näeb välja TVM assembler, mis on Haskelli sisse ehitatud, oleme selle põhjal rakendanud standardse rahakoti. Siin on mõned asjad, millele tasub tähelepanu pöörata:
- See leping koosneb ühest funktsioonist, kuid võite kasutada nii palju kui soovite. Kui määratlete uue funktsiooni hostikeeles (st Haskellis), võimaldab meie eDSL valida, kas soovite, et see muutuks eraldi alaprogrammiks TVM-is või oleks lihtsalt hõlmatud kutsumise kohtadesse.
- Nagu Haskellis, on funktsioonidel tüübid, mida kontrollitakse kompileerimise ajal. Meie eDSL-is on funktsiooni sisendi tüüp see, millist steki tüüpi funktsioon ootab, ja tulemuse tüüp on see, milline steki tüüp tekib pärast väljakutset.
- Koodis on annotatsioone
stacktype, mis kirjeldavad oodatavat steki tüüpi väljakutse kohas. Originaalses rahakoti lepingus olid need lihtsalt kommentaarid, kuid meie eDSL-is on need tegelikult osa koodist ja kontrollitakse kompileerimise ajal. Need võivad toimida dokumentatsioonina või kinnitustena, mis aitavad arendajal leida probleemi, kui koodi muutmise korral steki tüüp muutub. Muidugi ei mõjuta sellised annotatsioonid täitmise ajal jõudlust, kuna nende jaoks ei genereerita mingit TVM koodi. - See on endiselt prototüüp, mis on kirjutatud kahe nädala jooksul, seega on projekti kallal veel palju tööd. Näiteks kõik klasside eksemplarid, mida näete allpool toodud koodis, peaksid genereerima automaatselt.
Nii näeb välja multisig rahakoti rakendus meie eDSL-is:
peamine :: IO ()
peamine = putText $ pretty $ declProgram protseduurid meetodid
kus
protseduurid =
[ ("recv_external", decl recvExternal)
, ("recv_internal", decl recvInternal)
]
meetodid =
[ ("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 "Tundmatu 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 @Word32Meie eDSL-i ja mitme allkirjaga rahakoti lepingute täielikku lähtekoodi leiate Ja lisaks meie kolleeg Georgi Agapov sisseehitatud keeltest.
Kokkuvõtted konkursist ja TON
Kokku kulus meie tööle 380 tundi (koos dokumentatsiooniga tutvumise, koosolekute ja tegeliku arendusega). Konkursi projektis osales viis arendajat: CTO, meeskonnajuht, plokiahela platvormide spetsialistid ja Haskell-i tarkvaraarendajad.
Ressursse konkursis osalemiseks leidisime vaevata, kuna hackathoni vaim, tihe meeskonnatöö, vajadus uute tehnoloogiate aspektidesse kiiresti süveneda — see on alati haarav. Mõned unetud ööd maksimaalse tulemuse nimel piiratud ressursside tingimustes kompenseeritakse hindamatu kogemuse ja toredate mälestustega. Lisaks on selliste ülesannete täitmine alati hea kontroll ettevõtte protsesside üle, kuna tõeliselt väärtuslike tulemuste saavutamine ilma suurepäraselt sujuva sisese koostööta on äärmiselt keeruline.
Lisaks luulele: olime muljet avaldanud TONi meeskonna töö mahu üle. Neil on õnnestunud ehitada keeruline, ilus ja mis kõige tähtsam, töötav süsteem. TON on end tõestanud kui platvorm, millel on suur potentsiaal. Kuid selleks, et see ökosüsteem areneks, tuleb veel palju ära teha, nii plokiahelaprojektide kasutamise osas kui ka arendustööriistade täiustamise osas. Oleme uhked, et nüüd oleme osa sellest protsessist.
Kui pärast selle artikli lugemist on teil jäänud küsimusi või on teil ideid TONi rakendamiseks oma probleemide lahendamiseks, — jagame meelsasti kogemusi.
Allikas: habr.com
