Jy het waarskynlik daardie Telegram gehoor . Maar jy het dalk die nuus gemis dat Telegram nie lank gelede nie vir die implementering van een of meer slim kontrakte vir hierdie platform.
Die Serokell-span, met uitgebreide ervaring in die ontwikkeling van groot blokkettingprojekte, kon nie opsy staan nie. Ons het vyf werknemers na die kompetisie afgevaardig, en twee weke later het hulle die eerste plek daarin behaal onder die (on)beskeie ewekansige bynaam Sexy Chameleon. In hierdie artikel sal ek praat oor hoe hulle dit gedoen het. Ons hoop dat jy in die volgende tien minute ten minste 'n interessante storie sal lees, en hoogstens iets nuttigs daarin sal vind wat jy in jou werk kan toepas.
Maar kom ons begin met 'n bietjie konteks.
Mededinging en sy voorwaardes
Dus, die hooftake van die deelnemers was die implementering van een of meer van die voorgestelde slim kontrakte, asook die maak van voorstelle om die TON-ekosisteem te verbeter. Die kompetisie het van 24 September tot 15 Oktober gestrek, en die uitslae is eers op 15 November aangekondig. Nogal lank, as in ag geneem word dat Telegram gedurende hierdie tyd daarin geslaag het om die resultate van kompetisies oor die ontwerp en ontwikkeling van toepassings in C++ te hou en aan te kondig vir die toets en assessering van die kwaliteit van VoIP-oproepe in Telegram.
Ons het twee slim kontrakte gekies uit die lys wat deur die organiseerders voorgestel is. Vir een van hulle het ons gereedskap gebruik wat met TON versprei is, en die tweede is geïmplementeer in 'n nuwe taal wat deur ons ingenieurs spesifiek vir TON ontwikkel is en in Haskell ingebou is.
Die keuse van 'n funksionele programmeertaal is nie toevallig nie. In ons Ons praat dikwels oor hoekom ons dink die kompleksiteit van funksionele tale is 'n groot oordrywing en hoekom ons dit oor die algemeen verkies bo objekgeoriënteerde tale. Terloops, dit bevat ook .
Hoekom het ons selfs besluit om deel te neem?
Kortom, want ons spesialisasie is nie-standaard en komplekse projekte wat spesiale vaardighede vereis en dikwels van wetenskaplike waarde vir die IT-gemeenskap is. Ons ondersteun oopbronontwikkeling sterk en is betrokke by die popularisering daarvan, en werk ook saam met vooraanstaande Russiese universiteite op die gebied van rekenaarwetenskap en wiskunde.
Die interessante take van die kompetisie en betrokkenheid by ons geliefde Telegram-projek was op sigself 'n uitstekende motivering, maar die prysfonds het 'n bykomende aansporing geword. 🙂
TON blockchain navorsing
Ons monitor nuwe ontwikkelings in blokketting, kunsmatige intelligensie en masjienleer noukeurig en probeer om nie 'n enkele beduidende vrystelling te mis in elk van die gebiede waarin ons werk nie. Daarom, toe die kompetisie begin het, was ons span reeds vertroud met idees van . Voordat ons egter met TON begin werk het, het ons nie die tegniese dokumentasie en die werklike bronkode van die platform ontleed nie, so die eerste stap was redelik voor die hand liggend - 'n deeglike studie van die amptelike dokumentasie oor en .
Teen die tyd dat die kompetisie begin het, was die kode reeds gepubliseer, so om tyd te bespaar, het ons besluit om 'n gids of opsomming te soek wat geskryf is deur deur gebruikers. Ongelukkig het dit geen resultate opgelewer nie - behalwe instruksies vir die samestelling van die platform op Ubuntu, het ons geen ander materiaal gevind nie.
Die dokumentasie self was goed nagevors, maar was moeilik om te lees in sommige gebiede. Ons moes gereeld na sekere punte terugkeer en van hoëvlakbeskrywings van abstrakte idees na laevlakimplementeringsbesonderhede oorskakel.
Dit sal makliker wees as die spesifikasie glad nie 'n gedetailleerde beskrywing van die implementering insluit nie. Inligting oor hoe 'n virtuele masjien sy stapel verteenwoordig, is meer geneig om ontwikkelaars se aandag af te lei wat slim kontrakte vir die TON-platform skep as om hulle te help.
Nix: om die projek saam te stel
By Serokell is ons groot aanhangers . Ons versamel ons projekte daarmee en ontplooi dit met behulp van , en op al ons bedieners geïnstalleer . Danksy dit is al ons bouwerk reproduseerbaar en werk dit op enige bedryfstelsel waarop Nix geïnstalleer kan word.
So ons het begin deur te skep . Met sy hulp is die samestelling van TON so eenvoudig as moontlik:
$ cd ~/.config/nixpkgs/overlays && git clone https://github.com/serokell/ton.nix
$ cd /path/to/ton/repo && nix-shell
[nix-shell]$ cmakeConfigurePhase && makeLet daarop dat jy nie enige afhanklikhede hoef te installeer nie. Nix sal op magiese wyse alles vir jou doen, of jy nou NixOS, Ubuntu of macOS gebruik.
Programmering vir TON
Die slimkontrakkode in die TON-netwerk loop op die TON-virtuele masjien (TVM). TVM is meer kompleks as die meeste ander virtuele masjiene, en het baie interessante funksionaliteit, byvoorbeeld, dit kan werk voortsettings и skakels na data.
Boonop het die ouens van TON drie nuwe programmeertale geskep:
Vyf is 'n universele stapel programmeertaal wat lyk soos . Sy super vermoë is die vermoë om met TVM te kommunikeer.
FunC is 'n slim kontrak programmeertaal wat soortgelyk is aan en is saamgestel in 'n ander taal - Fift Assembler.
Vyfde samesteller - Fift-biblioteek vir die generering van binêre uitvoerbare kode vir TVM. Fifth Assembler het nie 'n samesteller nie. Hierdie .
Ons kompetisie werk
Uiteindelik is dit tyd om te kyk na die resultate van ons pogings.
Asynchrone betaalkanaal
Betalingskanaal is 'n slim kontrak wat twee gebruikers toelaat om betalings buite die blokketting te stuur. As gevolg hiervan spaar jy nie net geld nie (daar is geen kommissie nie), maar ook tyd (jy hoef nie te wag vir die volgende blok om verwerk te word nie). Betalings kan so klein wees as wat verlang word en so gereeld as wat nodig is. In hierdie geval hoef die partye mekaar nie te vertrou nie, aangesien die billikheid van die finale skikking deur die slim kontrak gewaarborg word.
Ons het 'n redelik eenvoudige oplossing vir die probleem gevind. Twee partye kan getekende boodskappe uitruil, wat elk twee nommers bevat—die volle bedrag wat deur elke party betaal word. Hierdie twee nommers werk soos in tradisionele verspreide stelsels en stel die "gebeur voor"-bevel op transaksies. Deur hierdie data te gebruik, sal die kontrak enige moontlike konflik kan oplos.
Trouens, een nommer is genoeg om hierdie idee te implementeer, maar ons het albei verlaat omdat ons op hierdie manier 'n geriefliker gebruikerskoppelvlak kon maak. Daarbenewens het ons besluit om die betalingsbedrag in elke boodskap in te sluit. Daarsonder, as die boodskap om een of ander rede verlore gaan, sal die gebruiker dalk nie die verlies opmerk nie, alhoewel al die bedrae en die finale berekening korrek sal wees.
Om ons idee te toets, het ons gesoek na voorbeelde van die gebruik van so 'n eenvoudige en bondige betaalkanaalprotokol. Verbasend genoeg het ons net twee gevind:
- 'n soortgelyke benadering, slegs vir die geval van 'n eenrigtingkanaal.
- , wat dieselfde idee as ons s'n beskryf, maar sonder om baie belangrike besonderhede te verduidelik, soos algemene korrektheid en konflikoplossingsprosedures.
Dit het duidelik geword dat dit sin maak om ons protokol in detail te beskryf, met spesiale aandag aan die korrektheid daarvan. Na verskeie herhalings was die spesifikasie gereed, en nou kan jy ook. .
Ons het die kontrak in FunC geïmplementeer, en ons het die opdragreëlhulpmiddel vir interaksie met ons kontrak heeltemal in Fift geskryf, soos aanbeveel deur die organiseerders. Ons kon enige ander taal vir ons CLI gekies het, maar ons was geïnteresseerd om Fit te probeer om te sien hoe dit in die praktyk presteer.
Om eerlik te wees, nadat ons met Fift gewerk het, het ons geen dwingende redes gesien om hierdie taal te verkies bo gewilde en aktief gebruikte tale met ontwikkelde gereedskap en biblioteke nie. Programmering in 'n stapel-gebaseerde taal is nogal onaangenaam, aangesien jy voortdurend in jou kop moet hou wat op die stapel is, en die samesteller help nie hiermee nie.
Daarom, na ons mening, is die enigste regverdiging vir die bestaan van Fift sy rol as gasheertaal vir Fift Assembler. Maar sou dit nie beter wees om die TVM-samesteller in een of ander bestaande taal in te sluit, eerder as om 'n nuwe een uit te vind vir hierdie in wese uitsluitlike doel nie?
TVM Haskell eDSL
Nou is dit tyd om oor ons tweede slim kontrak te praat. Ons het besluit om 'n multi-handtekening-beursie te ontwikkel, maar om nog 'n slim kontrak in FunC te skryf, sou te vervelig wees. Ons wou 'n bietjie smaak byvoeg, en dit was ons eie samestellingstaal vir TVM.
Soos Fift Assembler, is ons nuwe taal ingebed, maar ons het Haskell as die gasheer gekies in plaas van Fift, wat ons in staat stel om sy gevorderde tipe stelsel ten volle te benut. Wanneer daar met slim kontrakte gewerk word, waar die koste van selfs 'n klein fout baie hoog kan wees, is statiese tik na ons mening 'n groot voordeel.
Om te demonstreer hoe TVM-samesteller lyk ingebed in Haskell, het ons 'n standaard-beursie daarop geïmplementeer. Hier is 'n paar dinge om op te let:
- Hierdie kontrak bestaan uit een funksie, maar jy kan soveel gebruik as wat jy wil. Wanneer jy 'n nuwe funksie in die gasheertaal (d.w.s. Haskell) definieer, laat ons eDSL jou toe om te kies of jy wil hê dit moet 'n aparte roetine in TVM word of bloot inlyn by die oproeppunt.
- Soos Haskell, het funksies tipes wat tydens samestelling gekontroleer word. In ons eDSL is die invoertipe van 'n funksie die tipe stapel wat die funksie verwag, en die resultaattipe is die tipe stapel wat na die oproep geproduseer sal word.
- Die kode het aantekeninge
stacktype, wat die verwagte stapeltipe by die oproeppunt beskryf. In die oorspronklike beursiekontrak was dit net opmerkings, maar in ons eDSL is dit eintlik deel van die kode en word gekontroleer tydens samestelling. Dit kan dien as dokumentasie of stellings wat die ontwikkelaar help om die probleem te vind as die kode verander en die stapeltipe verander. Natuurlik beïnvloed sulke aantekeninge nie looptydprestasie nie, aangesien geen TVM-kode daarvoor gegenereer word nie. - Hierdie is steeds 'n prototipe wat in twee weke geskryf is, so daar is nog baie werk om aan die projek te doen. Byvoorbeeld, alle gevalle van die klasse wat jy in die kode hieronder sien, moet outomaties gegenereer word.
Dit is hoe die implementering van 'n multisig-beursie op ons eDSL lyk:
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 @Word32Die volledige bronkode van ons eDSL en multi-handtekening beursie kontrak kan gevind word by En meer oor ingeboude tale, ons kollega Georgy Agapov.
Gevolgtrekkings oor die kompetisie en TON
In totaal het ons werk 380 uur geneem (insluitend vertroudmaking met dokumentasie, vergaderings en werklike ontwikkeling). Vyf ontwikkelaars het aan die kompetisieprojek deelgeneem: CTO, spanleier, blokkettingplatformspesialiste en Haskell-sagteware-ontwikkelaars.
Ons het hulpbronne gevind om sonder moeite aan die kompetisie deel te neem, aangesien die gees van 'n hackathon, hegte spanwerk en die behoefte om ons vinnig in aspekte van nuwe tegnologieë te verdiep altyd opwindend is. Verskeie slapelose nagte om maksimum resultate te behaal in toestande van beperkte hulpbronne word vergoed deur onskatbare ervaring en uitstekende herinneringe. Daarbenewens is die werk aan sulke take altyd 'n goeie toets van die maatskappy se prosesse, aangesien dit uiters moeilik is om werklik ordentlike resultate te behaal sonder goed funksionerende interne kommunikasie.
Lirieke ter syde: ons was beïndruk deur die hoeveelheid werk wat deur die TON-span ingesit is. Hulle het daarin geslaag om 'n komplekse, pragtige, en die belangrikste, werkende stelsel te bou. TON het homself bewys as 'n platform met groot potensiaal. Om hierdie ekosisteem egter te ontwikkel, moet baie meer gedoen word, beide in terme van die gebruik daarvan in blokkettingprojekte en in terme van die verbetering van ontwikkelingsinstrumente. Ons is trots om nou deel te wees van hierdie proses.
As jy na die lees van hierdie artikel nog enige vrae het of idees het oor hoe om TON te gebruik om jou probleme op te los, — ons sal met graagte ons ervaring deel.
Bron: will.com
