Tilakonesuunnittelumallin vankka toteutus

Älykkäiden sopimusten kirjoittaminen on pelottavaa. He käsittelevät oikeita rahaa, ja unohtamalla lisätä yksi avainsana tai väärää väärin 2 näennäisesti vaihdettavaa koodiriviä voi johtaa miljoonien dollarien menetykseen. Kyllä, voit kirjoittaa testejä ja saada ammattilaiset tarkistamaan koodisi, mutta jos sopimusten rakenne ja toiminnallisuus alkavat monimutkaistua, on silti hyvä mahdollisuus, että he menettävät jotain. Et voi olla 100% varma, että koodisi on turvallinen.

Onneksi on olemassa lukuisia parhaita käytäntöjä, tunnettuja turvallisuusvirheitä ja suunnittelumalleja, jotka voivat auttaa minimoimaan riskit. Token Foundryssa yksi tapa, jolla autamme turvaamaan tokenimyyntimme, on käyttämällä ”State Machine” -malliin kutsuttua ohjelmointisuunnittelumallia.

Jos olet jo ohjelmoinut jonkin aikaa, saatat jo tietää tämän mallin. Tämän artikkelin tarkoituksena on selittää:

  • Mikä on State Machine -malli ja milloin sitä tulisi käyttää
  • Jakelu valtion koneelle, jonka olemme kehittäneet Token Foundryssä, kuinka sitä käytetään itse ja miten se todella toimii
  • Kuinka tämä malli voi auttaa takaamaan sopimustesi turvallisuuden
  • Kuinka haluamme kehittää edelleen valtion koneemme tulevaisuudessa

Mikä on State Machine Design Pattern?

State Machine -malli jakaa ohjelman toiminnallisuuden useisiin erilaisiin “tiloihin”. Missä tahansa vaiheessa ohjelma on yhdessä ja yhdessä tilassa, jonka aikana vain tilakohtaiset toiminnot ovat mahdollisia. Ohjelma voi siirtyä näiden tilojen välillä ennalta määritellyllä tavalla. Ohjelma voi esimerkiksi vaatia siirtymien käynnistämistä manuaalisesti tai voi siirtyä automaattisesti tilojen välillä. Token Foundry -yrityksessä määrittelemme nämä automaattiset siirtymät tilankäynnistysolosuhteiden avulla, joihin voi sisältyä (mutta ei niihin rajoittuen):

  • Muuttuja ottaa nyt halutun arvon
  • Tietty aika on saavutettu
  • Vaadittu tapahtuma- tai toimintopuhelu on tapahtunut

Uuteen tilaan siirtyessä voi tapahtua muuttuvien arvojen muutoksia tai tietyt toiminnot voidaan suorittaa automaattisesti. Toiminnot, jotka on suoritettava uuteen tilaan siirtyessään, ovat takaisinsoitto-toimintoja.

Milloin mallia tulisi käyttää?

State Machine -suunnittelumalli ei sovellu käytettäväksi kaikissa ohjelmissa tai älykkäissä sopimuksissa. Järjestelmät, jotka sopivat hyvin malliin, tulisi helposti jakaa erillisiin vaiheisiin, joissa tapahtuu erilainen käyttäytyminen tai eri toiminnot ovat sallittuja. Järjestelmän näitä vaiheita edustavat tilat koneessa, ja niiden tulisi tapahtua seuraavan jälkeen tietyn ajanjakson ajan.

Esimerkiksi, kun paljastetaan tietoa ketjussa, kaikkien osapuolten on tavallista, että he sitoutuvat tietoihinsä ennen kuin kaikki paljastavat todelliset arvot. Yksi esimerkki tästä on äänestys - sopimuksessa voidaan tarvita seuraavaa:

  • Rekisteröinti - äänestäjät voivat ilmoittautua sopimukseen myöhemmin äänestääkseen
  • Äänestysten sitoutuminen - äänestäjien valitsemien vaihtoehtojen tiivistelmä sitoutuu
  • Äänten paljastaminen - äänestäjät paljastavat nyt äänensä (joka vastaa heidän hajautustaan)
  • Äänestys on ohitettu - äänestäjät eivät enää saa antaa tietoja

Näiden valtioiden lähtöolosuhteet voivat laukaista siirtymävaiheen, kun tietty määrä äänestäjiä on rekisteröitynyt tai kun tietty aika on kulunut.

Jakelu Token Foundry: n valtion koneeseen ja miten sitä voidaan käyttää itse

Token Foundryssä olemme luoneet joitain älykkäitä sopimuksia, joiden avulla kehittäjät voivat helposti toteuttaa lineaarisen (toistaiseksi) tilakoneen mallin. StateMachine-sopimuksemme ja testimme ovat avoimen lähdekoodin tuotteita, ja ne löytyvät Token Foundry GitHubista kenelle tahansa lukemista, testaamista ja käyttöä varten.

Toteutuksemme mahdollistaa mielivaltaisen määrän tilojen määrittämisen, samoin kuin mielivaltaisen määrän käynnistysolosuhteita ja kunkin tilan takaisinsoitto-toimintoja.

Tarjoamme kaksi sopimusta: StateMachine.sol ja TimedStateMachine.sol. Ensimmäinen näistä on kantakuvion toteutus ja toinen on laajennus, joka mahdollistaa aikaleimapohjaiset aloitusolosuhteet tiloille.

Perusajatus tilakoneesi perustamiseen voidaan jakaa muutamiin yksinkertaisiin vaiheisiin:

  1. Tunnista koneesi korkean tason tilat.

Ne määritetään vakiona arvoina sopimuksessa. Esimerkiksi yksinkertaisella merkkimyynnillä sinulla voisi olla:

tavut32 vakio FREEZE = "freeze";
tavut32 vakio IN_PROGRESS = "inProgress";
tavun32 vakio LOPPU = "päättynyt"

Nämä tilat on välitettävä funktiolle setStates (tavut32 [] -tilat) tilakoneen asettamiseksi. Tämä tulisi yleensä tehdä sopimuksen rakentajana.

2. Määritä, mitkä toiminnot ovat sallittuja kussakin tilassa.

Tämä on myös suositeltavaa suorittaa sopimuksen rakentajassa, jotta kaikki kielletyt toiminnot asetetaan sellaisiksi alusta alkaen. Esimerkiksi jatkamalla yllä olevaa esimerkkiä, haluaisimme vain, että avustaja voi ostaa rahakkeita IN_PROGRESS-tilan aikana.

Rakentajaan laitamme:
allowFunction (IN_PROGRESS, tämä.osto.valitsin);

Tämä asettaa funktion ostamisen sallituksi vain IN_PROGRESS-alueella - jos tilakone on PYSYTYS- tai LOPETTU-tilassa, ostamista ei voida suorittaa. Lisätietoja siitä, miten tämä toimii myöhemmin.

3. Määritä minkä tahansa valtion lähtöolosuhteet ja takaisinsoitto-toiminnot

Käynnistys- ja takaisinsoitto-ominaisuudet on määriteltävä älykkäässä sopimuksessa, ja ne on lisättävä asiaankuuluviin tiloihin, kun rakennat tilakonetta.

Aloitusolosuhteiden on oltava seuraavassa muodossa, missä tavut32 on tilatunnus (esim. Vakio FREEZE):
toimintoesimerkkiStartCondition (tavut32) sisäiset palautukset (bool) {...}
Tilaan saapuessa automaattisesti suoritetut takaisinsoitot ovat eri muodossa:
toimintoesimerkkiTausta () sisäinen {...}

Ne asetetaan sitten asianomaisille tiloille seuraavasti:

addStartCondition (LOPETTU, hasSaleSoldOut);
addCallback (LOPETTU, transferMoneyToTeam);

Jotta aikaleiman aiheuttamat siirrot olisivat yksinkertaisempia, määrittelimme myös TimedStateMachine. Tällä sopimuksella on ennalta määritetty aikaleiman käynnistämä aloitusehto, ja se käyttää seuraavaa toimintoa näiden siirtymien lisäämiseksi helposti tilakoneeseen:
toiminto setStateStartTime (bytes32 stateId, uint256 timestamp) sisäinen

Joten miten tämä kaikki toimii?

StateMachine-sopimuksessamme on muuntaja nimeltä checkAllowed. Mikä on määritelty seuraavasti:

modifikaattori checkAllowed {
    conditionalTransitions ();
    vaativat (valtiot [currentStateId] .allowedFunctions [msg.sig]);
    _;
}

Kun funktio määritetään käyttämällä checkAllowed -muokkainta, toiminto conditionalTransitions () suoritetaan ensin. conditionalTransitions () tarkistaa jokaisen seuraavan tilan aloitusolosuhteet, ja jos jokin näistä on tosi siirtymiä mainittuun tilaan. Tämä prosessi toistuu, kunnes tilakone on oikeassa nykyisessä tilassa. Seuraava rivi vaatii sitten, että toiminnon sallitaan suorittaa nykyisessä tilassa.

Oletetaan esimerkiksi, että meillä on tilakone tilassa A, ja tilan B käynnistymisolosuhteet ovat aika = = 22:00. Jos funktiota onlyStateA merkitty checkAllowed kutsutaan kello 10.05pm, conditionalTransitions näkee, että (aika> = 22:00) == totta, ja siirtää koneen tilaan B automaattisesti - kutsuu tarvittavat takaisinsoitot tällä hetkellä. Sitten se näkee, että kone on tosiasiassa tilassa B eikä suorita vainInStateA: ta.

Kuinka valtion koneemme auttaa parantamaan kooditurvallisuutta, perusteluja ja hallittavuutta

Suunnittelumallien käyttö ohjelmoinnissa - mukaan lukien tilakonemalli - hajottaa monimutkaiset ideat yksinkertaisemmin ymmärrettäviksi konstrukteiksi. Tilakoneeksi suunnitellun järjestelmän avulla tilat voidaan testata ja perustella erikseen vaarantamatta muiden tilojen aiheuttamaa häiriötä ja niiden käyttäytymistä.

State Machine -rakenteet mahdollistavat myös järjestelmän virtauksen selkeyden lisääntymisen. Tällainen yksinkertaisuus ja selkeys älykkäissä sopimuksissa on avainasemassa, varsinkin kun ne käsittelevät mahdollisesti suuria rahasummia.

Rajoitukset ja tulevaisuuden suunnitelmat

Tällä hetkellä toteutus sallii vain lineaariset tilakoneet (jokaisessa tilassa voi olla vain yksi lähtevä siirtymä). Tämä sopii hyvin myyntisopimuksille, joilla on yksinkertainen kulku ja joiden on tarkoitus elää vain lyhyen ajan. Jos järjestelmäsi vaatii kuitenkin monimutkaisempia ominaisuuksia, tämä toteutus ei ehkä riitä. Esimerkkejä sellaisista ominaisuuksista ovat siirtymän peruuttaminen, haaroittumisvirtaukset tai syklien omaaminen.

Pyrimme parhaillaan uudistamaan tätä hanketta tukeaksemme epälineaarisia konerakenteita ja -syklejä (toivottavasti) aivan liian kaukaisessa tulevaisuudessa.

Arvostamme kaikkia kirjoittamaamme koodia koskevia kysymyksiä, kyselyjä ja palautetta, joten ota rohkeasti yhteyttä.

Alice Henshaw
Solidity Engineer @ Token Foundry
www.tokenfoundry.com