Bi Haskell re FunC veguherînin FunCtional: Çawa Serokell Pêşbaziya Blockchain ya Telegram qezenc kir

Dibe ku we ew Telegram bihîstiye nêzîkê destpêkirina platforma bloka Ton e. Lê dibe ku we nûçeyên ku ne demek berê Telegram ji bîr kiribe pêşbirk ragihand ji bo pêkanîna yek an çend peymanên jîr ji bo vê platformê.

Tîma Serokell, xwedan ezmûnek pirfireh di pêşxistina projeyên mezin ên blokê de, nekarî li aliyekî bisekine. Me pênc karmend şand pêşbaziyê, û du hefte şûnda wan di bin navê paşnavê rasthatî yê (bê) nerm de cîhê yekem girt. Di vê gotarê de ez ê bipeyivim ka wan çawa kir. Em hêvî dikin ku di deh deqeyên pêş de hûn ê bi kêmanî çîrokek balkêş bixwînin, û herî zêde hûn ê tê de tiştek kêrhatî bibînin ku hûn dikarin di xebata xwe de bicîh bînin.

Lê em bi çarçoveyek piçûk dest pê bikin.

Pêşbazî û mercên wê

Ji ber vê yekê, peywirên sereke yên beşdaran pêkanîna yek an çend peymanên biaqil ên pêşniyarkirî, û her weha çêkirina pêşniyaran ji bo baştirkirina ekosîstema TON bû. Pêşbirk ji 24ê Îlonê heta 15ê Cotmehê berdewam kir û encam tenê di 15ê Mijdarê de hatin eşkerekirin. Demek dirêj e, ji ber ku di vê demê de Telegram karî encamên pêşbirkên li ser sêwirandin û pêşkeftina serîlêdanên di C++ de ji bo ceribandin û nirxandina qalîteya bangên VoIP di Telegram de li dar bixe û ragihîne.

Me ji navnîşa ku ji hêla organîzatoran ve hatî pêşniyar kirin du peymanên jîr hilbijart. Ji bo yek ji wan, me amûrên ku bi TON-ê re hatine belavkirin bikar anîn, û ya duyemîn bi zimanek nû ku ji hêla endezyarên me ve bi taybetî ji bo TON-ê hatî pêşve xistin û li Haskell hatî çêkirin hate bicîh kirin.

Hilbijartina zimanek bernamesaziya fonksiyonel ne tesadufî ye. Di me de bloga pargîdanî Em bi gelemperî li ser vê yekê diaxivin ka çima em difikirin ku tevliheviya zimanên fonksiyonel mezinbûnek mezin e û çima em bi gelemperî wan ji yên objekt-oriented tercîh dikin. Bi awayê, ew jî dihewîne orjînala vê gotarê.

Çima me jî biryar da ku em beşdar bibin?

Bi kurtasî, ji ber ku pisporiya me projeyên ne-standard û tevlihev in ku jêhatîyên taybetî hewce dikin û bi gelemperî ji civata IT-ê re nirxek zanistî ne. Em bi xurtî piştgirî didin pêşkeftina çavkaniya vekirî û bi populerkirina wê re mijûl in, û di warê zanistiya computer û matematîkê de bi zanîngehên pêşeng ên rûsî re jî hevkariyê dikin.

Karên balkêş ên pêşbaziyê û tevlêbûna projeya meya delal Telegram bi serê xwe motîvasyonek hêja bûn, lê fona xelatê bû teşwîqek zêde. 🙂

TON lêkolîn blockchain

Em ji nêz ve pêşkeftinên nû yên di zincîra blok, îstîxbarata sûnî û fêrbûna makîneyê de dişopînin û hewl didin ku di her deverên ku em lê dixebitin de yek serbestberdana girîng ji dest nedin. Ji ber vê yekê, dema ku pêşbaziyê dest pê kir, tîmê me jixwe bi ramanên ji nas bû TON kaxeza spî. Lêbelê, berî ku em dest bi xebata bi TON-ê re bikin, me belgeyên teknîkî û koda çavkaniya rastîn a platformê analîz nekir, ji ber vê yekê gava yekem pir eşkere bû - lêkolînek bêkêmasî ya belgeyên fermî yên li ser malperê û di depoyên projeyê.

Wexta ku pêşbirk dest pê kir, kod berê hatibû weşandin, ji ber vê yekê ji bo ku dem xilas bikin, me biryar da ku em li rêberek an kurteyek ku ji hêla hatî nivîsandin ve bigerin. ji hêla bikarhêneran ve. Mixabin, vê yekê tu encam neda - ji bilî rêwerzên ji bo berhevkirina platformê li ser Ubuntu, me tu materyalên din nedît.

Belge bi xwe baş lêkolîn bû, lê di hin waran de xwendina dijwar bû. Pir caran neçar mabû ku em vegerin ser hin xalan û ji danasînên asta bilind ên ramanên razber berbi hûrguliyên pêkanîna asta nizm ve biçin.

Dê hêsantir be heke diyarde bi tevahî ravekek berfireh a pêkanînê negire. Agahdariya li ser ka makîneyek virtual çawa stûyê xwe temsîl dike, bêtir dibe ku bala pêşdebiran biafirîne ku ji bo platforma TON peymanên biaqil diafirînin ne ku alîkariya wan bike.

Nix: proje li hev kirin

Li Serokell em heyranên mezin in nix. Em bi wê projeyên xwe berhev dikin û bi kar tînin NixOps, û li ser hemî serverên me hatî saz kirin Nix OS. Bi saya vê yekê, hemî avahiyên me têne dubare kirin û li ser her pergala xebitandinê ya ku Nix dikare li ser were saz kirin dixebitin.

Ji ber vê yekê me dest bi afirandinê kir Ji bo kombûna TON-ê bi vegotina Nix-ê ve girêdayî ye. Bi alîkariya wê, berhevkirina TON bi qasî ku pêkan hêsan e:

$ cd ~/.config/nixpkgs/overlays && git clone https://github.com/serokell/ton.nix
$ cd /path/to/ton/repo && nix-shell
[nix-shell]$ cmakeConfigurePhase && make

Bala xwe bidinê ku hûn ne hewce ne ku pêwendiyan saz bikin. Nix dê bi sêrbazî her tiştî ji bo we bike, gelo hûn NixOS, Ubuntu, an macOS bikar tînin.

Bernamekirin ji bo TON

Koda peymana hişmend a di Tora TON de li ser Makîneya Virtualê TON (TVM) dimeşe. TVM ji piraniya makîneyên din ên virtual tevlihevtir e, û xwedan fonksiyonek pir balkêş e, mînakî, ew dikare pê re bixebite berdewam dike и girêdanên daneyan.

Wekî din, xortên ji TON sê zimanên bernamesaziyê yên nû afirandin:

Fift zimanek bernamesaziya stackê ya gerdûnî ye ku dişibihe Orthare. Kapasîteya wî ya super jêhatîbûna bi TVM-ê re ye.

FunC zimanek bernamesaziya peymana zîrek e ku dişibihe C û bi zimanekî din - Fift Assembler - hatiye berhev kirin.

Meclîsê pêncemîn - Pirtûkxaneya pêncan ji bo afirandina koda binaryê ya ji bo TVM. Pêncemîn Assembler berhevkarek nîne. Ev Zimanek Taybetî ya Domainê ya Bicîbûyî (eDSL).

Pêşbirka me dixebite

Di dawiyê de, dem hatiye ku em li encamên hewldanên xwe binêrin.

Kanala peredana Asynchronous

Kanala dravdanê peymanek jîr e ku dihêle du bikarhêner li derveyî zincîra blokê drav bişînin. Wekî encamek, hûn ne tenê drav (komîsyonek tune), lê di heman demê de dem jî (hûn ne hewce ne ku li bendê bin ku bloka din were hilanîn). Tezmînat dikare bi qasî ku tê xwestin piçûk be û bi qasî ku tê xwestin. Di vê rewşê de, alî ne hewce ne ku ji hev bawer bikin, ji ber ku dadperweriya lihevhatina dawîn bi peymana zîrek tê garantî kirin.

Me ji pirsgirêkê re çareseriyek pir hêsan dît. Du partî dikarin peyamên îmzekirî biguhezînin, ku her yek du hejmar dihewîne - tevahî mîqdara ku ji hêla her partiyek ve hatî dayîn. Ev her du hejmar mîna kar dikin saeta vektor di pergalên belavkirî yên kevneşopî de û li ser danûstendinan fermana "berî qewimî" destnîşan dikin. Bi karanîna van daneyan, peyman dê bikaribe her nakokiyek gengaz çareser bike.

Bi rastî, yek hejmar ji bo pêkanîna vê ramanê bes e, lê me herdu jî hiştin ji ber ku bi vî rengî me dikaribû navgînek bikarhênerek hêsantir çêbikin. Wekî din, me biryar da ku di her peyamê de mîqdara dravdanê têxin nav xwe. Bêyî wê, heke peyam ji ber hin sedeman winda bibe, wê hingê, her çend hemî mîqdar û hesabê dawîn rast be jî, dibe ku bikarhêner windahiyê nas neke.

Ji bo ceribandina ramana xwe, me li nimûneyên karanîna protokolek kanala dravdanê ya wusa hêsan û kurt geriya. Ecêb e, me tenê du dîtin:

  1. description nêzîkatiyek wekhev, tenê ji bo doza kanalek yekalî.
  2. Tutorial, ku heman ramana me vedibêje, lê bêyî ravekirina gelek hûrguliyên girîng, mîna rastbûna gelemperî û prosedurên çareserkirina nakokiyan.

Eşkere bû ku ew watedar e ku meriv protokola me bi hûrgulî rave bike, bi taybetî bala xwe bide rastbûna wê. Piştî çend dubareyan, taybetmendî amade bû, û naha hûn jî dikarin. li wê binêre.

Me peyman di FunC de bicîh kir, û me wekî ku ji hêla organîzatoran ve hatî pêşniyar kirin, amûra rêzika fermanê ji bo ku bi peymana xwe re bi tevahî di Fift de têkilî daynin nivîsî. Me dikaribû ji bo CLI-ya xwe zimanek din hilbijêrin, lê me eleqedar bû ku Fit biceribînin da ku bibînin ka ew di pratîkê de çawa dike.

Rast be, piştî ku bi Fift re xebitî, me ti sedemên berbiçav nedît ku em vî zimanî ji zimanên populer û çalak ên ku bi amûr û pirtûkxaneyên pêşkeftî têne bikar anîn tercîh bikin. Bernamesazkirina bi zimanek-based stack-ê pir ne xweş e, ji ber ku hûn neçar in ku bi domdarî tiştê ku li ser stakê ye di serê xwe de bihêlin, û berhevkar bi vê yekê re nabe alîkar.

Ji ber vê yekê, li gorî me, yekane hincet ji bo hebûna Fift rola wê ya wekî zimanê mêvandar ji bo Fift Assembler e. Lê ma ne çêtir e ku meriv sazkerê TVM-ê di hin zimanê heyî de bihêle, ne ku yek nû ji bo vê armanca bingehîn a bingehîn îcad bike?

TVM Haskell eDSL

Naha ew dem e ku em li ser peymana xweya duyemîn a jîr biaxivin. Me biryar da ku em berîka pir-îmzeyê pêş bixin, lê nivîsandina peymanek din a jîr li FunC dê pir bêzar be. Me dixwest ku hinekî çêjekê lê zêde bikin, û ew zimanê me yê meclîsê ji bo TVM bû.

Mîna Fift Assembler, zimanê me yê nû bicîbûyî ye, lê me Haskell wekî mêvandar li şûna Fift hilbijart, ku rê dide me ku em bi tevahî ji pergala wê ya pêşkeftî sûd werbigirin. Dema ku bi peymanên biaqil re dixebitin, li ku derê lêçûna xeletiyek piçûk jî pir zêde be, bi dîtina me nivîsandina statîk avantajek mezin e.

Ji bo ku em destnîşan bikin ka berhevkarê TVM-ê di Haskell-ê de bi çi rengî xuya dike, me berîka standard li ser wê bicîh kir. Li vir çend tişt hene ku hûn bala xwe bidin wan:

  • Ev peyman ji yek fonksiyonê pêk tê, lê hûn dikarin bi qasî ku hûn dixwazin bikar bînin. Gava ku hûn di zimanê mêvandar de fonksiyonek nû diyar dikin (ango Haskell), eDSL-ya me dihêle hûn hilbijêrin ka hûn dixwazin ew di TVM-ê de bibe rûtînek cûda an jî bi tenê di xala bangê de were xêz kirin.
  • Mîna Haskell, fonksiyonan celeb hene ku di dema berhevkirinê de têne kontrol kirin. Di eDSL-a me de, celebê têketina fonksiyonê celebê stûna ku fonksiyonê hêvî dike ye, û celebê encamê celebê stikê ye ku dê piştî bangê were hilberandin.
  • Di kodê de şîrove hene stacktype, di xala bangê de celebê stackê ya hêvîdar diyar dike. Di peymana berîka orjînal de ev tenê şîrove bûn, lê di eDSL-ya me de ew bi rastî beşek kodê ne û di dema berhevkirinê de têne kontrol kirin. Ew dikarin wekî belgekirin an daxuyaniyên ku ji pêşdebir re dibe alîkar ku heke kod biguhezîne û celebê stikê biguheze pirsgirêkê bibîne. Bê guman, şîroveyên weha bandorê li performansa dema xebitandinê nakin, ji ber ku kodek TVM ji wan re nayê çêkirin.
  • Ev hîn jî prototîpek e ku di nav du hefteyan de hatî nivîsandin, ji ber vê yekê hîn gelek kar heye ku li ser projeyê were kirin. Mînakî, hemî mînakên dersên ku hûn di koda jêrîn de dibînin divê bixweber bêne çêkirin.

Ev e ku bicîhkirina walletek multisig li ser eDSL-ya me dixuye:

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 @Word32

Koda çavkaniyê ya tevahî ya peymana berîka me ya eDSL û pir-îmza dikare li vir were dîtin vê depoyê. Û hîn bi berfirehî got li ser zimanên çêkirî, hevkarê me Georgy Agapov.

Encamên li ser pêşbirkê û TON

Bi tevahî, xebata me 380 demjimêran kişand (di nav de naskirina belge, civîn û pêşkeftina rastîn). Pênc pêşdebir beşdarî projeya pêşbaziyê bûn: CTO, serokê tîmê, pisporên platforma blokê û pêşdebirên nermalava Haskell.

Me çavkanî dît ku bêyî dijwarî beşdarî pêşbirkê bibin, ji ber ku ruhê hackathon, xebata tîmê ya nêzîk, û hewcedariya ku em zû xwe di warên teknolojiyên nû de bihelînin her gav balkêş e. Çend şevên bê xew ji bo bidestxistina encamên herî zêde di şert û mercên çavkaniyên tixûb de bi ezmûnek bêhempa û bîranînên hêja têne berdêl kirin. Digel vê yekê, xebata li ser van peywiran her gav ceribandinek baş a pêvajoyên pargîdaniyê ye, ji ber ku gihandina encamên bi rastî hêja bêyî danûstendina navxweyî ya baş-karker pir dijwar e.

Gotin li hêlekê: em ji mêjera xebata ku ji hêla tîmê TON ve hatî danîn bandor kirin. Wan karî pergalek tevlihev, xweşik û ya herî girîng a xebatê ava bikin. TON xwe îsbat kiriye ku platformek bi potansiyelek mezin e. Lêbelê, ji bo ku ev ekosîstem pêş bikeve, hem di warê karanîna wê di projeyên blokê de hem jî di warê başkirina amûrên pêşkeftinê de, pêdivî ye ku pir zêde were kirin. Em şanaz in ku niha bûne beşek ji vê pêvajoyê.

Ger piştî xwendina vê gotarê hîn jî pirsên we hebin an jî ramanên we hene ka meriv çawa TON-ê bikar tîne da ku pirsgirêkên xwe çareser bike, ji me re binivîse - em ê kêfxweş bibin ku ezmûna xwe parve bikin.

Source: www.habr.com

Add a comment