Verjetno ste slišali, da Telegram Morda pa ste spregledali novico, da je Telegram za izvedbo enega ali več pametnih pogodb za to platformo.
Ekipa Serokell z bogatimi izkušnjami pri razvoju velikih blockchain projektov ni mogla ostati pasivna. Na natečaj smo delegirali pet svojih sodelavcev, ki so že po dveh tednih zasedli prvo mesto pod (ne)skromnim naključnim vzdevkom Sexy Chameleon. V tem članku bom opisal, kako so to dosegli. Upamo, da boste v naslednjih desetih minutah prebrali zanimivo zgodbo, ali pa boste našli kaj koristnega, kar lahko uporabite v svojem delu.
Ampak začnimo z majhnim potopom v kontekst.
Natečaj in njegove pogoje
Torej, osnovne naloge udeležencev so bile izvedba ene ali več predlaganih pametnih pogodb ter predlogi za izboljšanje ekosistema TON. Natečaj je potekal od 24. septembra do 15. oktobra, rezultati pa so bili objavljeni šele 15. novembra. Kar precej časa, glede na to, da je Telegram v tem času uspešno izvedel in objavil rezultate natečajev za oblikovanje in razvoj aplikacij v C++ za testiranje in oceno kakovosti VoIP klicev v Telegramu.
Iz seznama, ki so ga predlagali organizatorji, smo izbrali dve pametni pogodbi. Za eno smo uporabili orodja, ki so na voljo skupaj s TON, drugo pa smo izvedli v novem jeziku, ki so ga razvili naši inženirji posebej za TON in je bil vgrajen v Haskell.
Izbor funkcionalnega programskega jezika ni naključen. V našem pogosto razlagamo, zakaj menimo, da je kompleksnost funkcionalnih jezikov močno prenapihnjena in zakaj na splošno dajemo prednost tem pred objektno usmerjenimi. Mimogrede, v njem je tudi .
Zakaj smo se sploh odločili sodelovati?
Na kratko, zato, ker je naša specializacija izvajanje nestandardnih in zahtevnih projektov, ki zahtevajo posebne veščine ter pogosto predstavljajo znanstveno vrednost za IT skupnost. Močno podpiramo open-source razvoj in se trudimo za njegovo popularizacijo ter sodelujemo z vodilnimi univerzami v Rusiji na področju računalništva in matematike.
Zanimivi izzivi natečaja in povezava z našim ljubim projektom Telegram so bili odlična motivacija, nagradni sklad pa dodatna spodbuda. 🙂
Raziskovanje blockchaina TON
Skrbno spremljamo nove razvojne trende v blockchainu, umetni inteligenci in strojno učenje ter se trudimo, da ne spustimo nobene pomembne izdaje na vsakem področju, s katerim se ukvarjamo. Tako je bila naša ekipa do trenutka začetka natečaja že seznanjena z idejami iz . Pred začetkom dela s TON pa nismo analizirali tehnične dokumentacije in dejanskega izvornega kode platforme, zato je bil prvi korak dovolj očiten — temeljita raziskava uradne dokumentacije na in v .
Ob začetku natečaja je bil koda že objavljena, zato smo za prihranek časa odločili, da poiščemo navodilo ali povzetek, ki ga je napisalo uporabniki. Na žalost to ni prineslo rezultatov — razen navodila za sestavo platforme na Ubuntu nismo našli drugih materialov.
Dokumentacija se je izkazala za skrbno obdelano, a branje le-te je bilo v nekaterih delih težavno. Pogosto smo se morali vračati k različnim točkam in prehajati z višjih opisov abstraktnih idej na nizke podrobnosti implementacije.
Bilo bi lažje, če v specifikaciji sploh ne bi bilo podrobnega opisa implementacije. Informacije o tem, kako virtualni stroj predstavlja svoj sklad, bolj odvračajo razvijalce, ki ustvarjajo pametne pogodbe za platformo TON, kot pa jim pomagajo.
Nix: sestavljamo projekt
V Serokell smo veliki oboževalci . Naše projekte gradimo in implementiramo z uporabo , vsi naši strežniki pa imajo nameščen . Tako so vsi naši gradnje reproducibilni in delujejo pod katerim koli operacijskim sistemom, ki podpira Nix.
Zato smo začeli s kreiranjem . S tem je sestavljanje TON kar enostavno:
$ cd ~/.config/nixpkgs/overlays && git clone https://github.com/serokell/ton.nix
$ cd /path/to/ton/repo && nix-shell
[nix-shell]$ cmakeConfigurePhase && makeUpoštevajte, da vam ni treba namestiti nobenih odvisnosti. Nix bo vse naredil namesto vas, ne glede na to, ali uporabljate NixOS, Ubuntu ali macOS.
Programiranje za TON
Кoda pametnih pogodbi u TON mreži izvršava se na TON virtuelnoj mašini (TVM). TVM je složenija od većine drugih virtuelnih mašina i ima veoma zanimljivih funkcionalnosti, na primer, može raditi sa nastavcima (continuations) in linkovima na podatke.
Štaviše, tim iz TON-a je stvorio čak tri nova programska jezika:
Fift — univerzalni stekovni programski jezik, koji podseća na . Njegova supermoć je mogućnost interakcije sa TVM.
FunC — programski jezik pametnih ugovora, koji je sličan i kompajlira se u još jedan jezik — Fift Assembler.
Fift Assembler — Fift biblioteka za generisanje binarnog izvršnog koda za TVM. Fift Assembler ne sadrži kompajler. To je .
Naši takmičarski radovi
Napokon, došlo je vreme da pogledamo rezultate naših napora.
Asinhroni platni kanal
Platni kanal (payment channel) — pametni ugovor koji omogućava dva korisnika da šalju uplate izvan blokčejna. Na taj način se štede ne samo novac (nema naknade), već i vreme (ne morate čekati da se obradi sledeća blokada). Uplate mogu biti koliko god male i dešavati se onoliko često koliko je potrebno. Pritom stranama nije potrebno da poveravaju jedna drugoj, jer je pravednost konačnog obračuna garantovana pametnim ugovorom.
Pronašli smo prilično jednostavno rešenje za problem. Dve strane mogu razmenjivati potpisane poruke, od kojih svaka sadrži dva broja — ukupnu sumu koju je platio svaki od učesnika. Ova dva broja funkcionišu kao u tradicionalnim distribuiranim sistemima i određuju redosled ‘desilo se pre’ na transakcijama. Koristeći te podatke, ugovor može rešiti svaki mogući konflikt.
U stvari, za implementaciju ove ideje dovoljno je i jedan broj, ali smo ostavili oba, jer smo tako mogli napraviti praktičniji korisnički interfejs. Pored toga, odlučili smo da uključimo u svaku poruku veličinu uplate. Bez nje, ako poruka iz nekog razloga izgubi, iako su sve sume i konačni obračun ispravni, korisnik može ne primetiti gubitak.
Da bi preizkusili našo idejo, smo poiskali primere uporabe takega enostavnega in jedrnatega protokola plačilnega kanala. Na naše presenečenje smo našli le dva:
- podobnega pristopa, le za enosmerni kanal.
- , v katerih je opisana ista ideja kot pri nas, vendar brez razlage mnogih pomembnih podrobnosti, kot sta splošna pravilnost in postopek reševanja konfliktov.
Postalo je jasno, da je smiselno podrobno opisati naš protokol, pri čemer je treba posebno pozornost nameniti njegovi pravilnosti. Po več iteracijah je bila specifikacija pripravljena, zdaj pa jo lahko .
Uresničili smo pogodbo v FunC, orodje ukazne vrstice za interakcijo z našo pogodbo pa smo povsem napisali v Fift, kot so priporočili organizatorji. Izbrati bi lahko kateri koli drug jezik za naš CLI, vendar nas je zanimalo, kako se bo Fift obnesel v praksi.
Iskreno povedano, ko smo delali s Fift, nismo videli tehtnih razlogov, da bi raje izbrali ta jezik pred priljubljenimi in pogosto uporabljenimi jeziki z razvitimi orodji in knjižnicami. Programiranje v jezikih na steklu je precej neprijetno, saj je treba nenehno slediti, kaj in kje je v skladu, kar kompilator ne olajša.
Zato je edini, po našem mnenju, opravičljiv razlog za obstoj Fift njegova vloga kot jezik za Fift Assembler. Ali ne bi bilo bolje vgraditi assembler TVM v že obstoječ jezik, namesto da bi izumili novega za to, v bistvu edino, namen?
TVM Haskell eDSL
Zdaj je čas, da govorimo o našem drugem pametnem pogodbi. Odločili smo se razviti denarnico z več podpisom, vendar bi bilo pisati še eno pametno pogodbo v FunC preveč dolgočasno. Želeli smo dodati neki pečat, in ta pečat je postal naš lasten jezik assemblerja za TVM.
Kot Fift Assembler je naš novi jezik vgrajen, le da smo kot gostitelja namesto Fift izbrali Haskell, kar nam je omogočilo, da v celoti izkoristimo njegov napreden sistem tipov. Pri delu s pametnimi pogodbami, kjer je cena vsake majhne napake lahko zelo visoka, se nam zdi, da je statična tipizacija velika prednost.
Da bi pokazali kako izgleda TVM asembler ugrađen u Haskell, implementirali smo standardni novčanik. Evo nekoliko stvari na koje treba obratiti pažnju:
- Ova kontrakt se sastoji od jedne funkcije, ali možete koristiti koliko god želite. Kada definišete novu funkciju na jeziku domaćina (tj. Haskellu), naš eDSL vam omogućava da odlučite želite li da postane posebna podprogram u TVM-u ili da bude jednostavno ugrađena na mesto poziva.
- Kao i u Haskellu, funkcije imaju tipove koji se proveravaju tokom kompajliranja. U našem eDSL, tip ulaza funkcije to je tip steka koji funkcija očekuje, a tip rezultata to je tip steka koji će se dobiti nakon poziva.
- Kod ima anotacije
stacktype, koje opisuju očekivani tip steka na mestu poziva. U originalnom novčaniku, to su bili samo komentari, ali u našem eDSL su zapravo deo koda i proveravaju se tokom kompajliranja. Mogu poslužiti kao dokumentacija ili izjave koje pomažu programeru da otkrije problem u slučaju da se tip steka promeni prilikom izmene koda. Naravno, takve anotacije ne utiču na performanse tokom izvršavanja, pošto se nikakvo TVM kod za njih ne generiše. - Ovo je još uvek prototip napisan za dve nedelje, tako da još mnogo posla predstoji. Na primer, svi primeri klasa koje vidite u donjem kodu trebaju biti automatski generisani.
Evo kako izgleda implementacija multisig novčanika u našem 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 @Word32Celoten izvorna koda našega eDSL in pogodbe denarnice z več podpisi lahko najdete v Podrobneje Zaključki o natečaju in TON
V skupnem je naše delo trajalo 380 ur (vključno z seznanjanjem z dokumentacijo, sestanki in samo razvijanjem). V natečajnem projektu je sodelovalo pet razvijalcev: CTO, timski vodja, strokovnjaki za blockchain platforme in razvijalci programske opreme v Haskellu.
V skupnem je naše delo trajalo 380 ur (vključno z spoznavanjem dokumentacije, sestanki in samo razvojem). V projektnem natečaju je sodelovalo pet razvijalcev: CTO, vodja ekipe, strokovnjaki za blockchain platforme in razvijalci programske opreme v Haskellu.
Zasoby do udziału w konkursie znaleźliśmy bez trudu, ponieważ duch hackathonu, bliska praca zespołowa oraz potrzeba szybkiego zanurzenia się w aspekty nowych technologii – to zawsze fascynujące. Kilka bezsennych nocy w celu osiągnięcia maksymalnych wyników w warunkach ograniczonych zasobów rekompensuje bezcenne doświadczenie i doskonałe wspomnienia. Ponadto praca nad takimi zadaniami – to zawsze doskonały sprawdzian procesów w firmie, ponieważ osiągnięcie naprawdę satysfakcjonujących wyników bez doskonale zorganizowanej wewnętrznej współpracy jest niezwykle trudne.
Oprócz liryki: byliśmy pod wrażeniem zakresu pracy wykonanego przez zespół TON. Udało im się zbudować skomplikowany, piękny i co najważniejsze, działający system. TON ujawnił się jako platforma o dużym potencjale. Jednak aby ten ekosystem się rozwijał, trzeba zrobić jeszcze bardzo dużo, zarówno w zakresie jego wykorzystania w projektach blockchain, jak i w doskonaleniu narzędzi deweloperskich. Jesteśmy dumni, że teraz jesteśmy częścią tego procesu.
Jeśli po przeczytaniu tego artykułu pozostały Państwu jakieś pytania lub pojawiły się pomysły na to, jak zastosować TON w rozwiązaniu swoich problemów, — z przyjemnością podzielimy się doświadczeniem.
Izvor: habr.com
