FlowCards: Deklaratywna struktura dla rozwoju dAppów Ergo

This page is machine-translated.
Alexander Slesarenko

29 kwietnia 2020

Dzięki Robertowi Kornackiemu za dopracowanie szkicu.

Wprowadzenie

ErgoScript to język smart kontraktów używany
przez blockchain Ergo. Choć ma zwięzłą składnię przyjętą z języków Scala/Kotlin, może
wydawać się na początku mylący, ponieważ koncepcyjnie ErgoScript jest dość inny w porównaniu do
konwencjonalnych języków, które wszyscy znamy i kochamy. Dzieje się tak, ponieważ Ergo jest blockchainem opartym na UTXO,
podczas gdy smart kontrakty są tradycyjnie kojarzone z systemami opartymi na kontach,
takimi jak Ethereum. Jednak model transakcji Ergo ma wiele zalet w porównaniu do modelu opartego na kontach,
a przy odpowiednim podejściu może być nawet znacznie łatwiejszy do rozwijania kontraktów Ergo
niż pisanie i debugowanie kodu Solidity.

Poniżej omówimy kluczowe aspekty modelu kontraktów Ergo, które czynią go innym:

Paradygmat

Model konta Ethereum jest imperatywny. Oznacza to, że typowe zadanie wysyłania monet z
Alicji do Boba wymaga zmiany sald w pamięci jako serii operacji. Z drugiej strony, model programowania oparty na UTXO
Ergo jest deklaratywny. Kontrakty ErgoScript określają warunki, które muszą być spełnione, aby
transakcja została zaakceptowana przez blockchain (a nie zmiany, które mają być dokonane w stanie pamięci
w wyniku wykonania kontraktu).

Skalowalność

W modelu konta Ethereum zarówno zmiany w pamięci, jak i sprawdzenia ważności są wykonywane
na łańcuchu podczas wykonywania kodu. W przeciwieństwie do tego, transakcje Ergo są tworzone
poza łańcuchem i tylko sprawdzenia walidacji są wykonywane na łańcuchu, co zmniejsza ilość
operacji wykonywanych przez każdy węzeł w sieci. Dodatkowo, dzięki niezmienności
grafu transakcji, możliwe są różne strategie optymalizacji, aby poprawić przepustowość
transakcji na sekundę w sieci. Możliwe są również lekkie węzły weryfikujące, co
jeszcze bardziej ułatwia skalowalność i dostępność sieci.

Wspólny stan

Model oparty na kontach polega na współdzielonym, zmiennym stanie, co prowadzi do
skomplikowanej semantyki (i subtelnych błędów wartym miliony dolarów) w kontekście obliczeń współbieżnych/
rozproszonych. Model Ergo oparty jest na niezmiennym grafie transakcji. To
podejście, odziedziczone po Bitcoinie, dobrze współpracuje z współbieżną i rozproszoną naturą
blockchainów i ułatwia działanie lekkich klientów bez zaufania.

Siła wyrazu

Ethereum promowało wykonanie języka turingowskiego na blockchainie. Teoretycznie obiecywało to nieograniczony potencjał, jednak w praktyce ujawniły się poważne
ograniczenia związane z nadmiernym rozrostem blockchaina, subtelnymi błędami wartymi miliony dolarów, kosztami gazu, które
ograniczają złożoność kontraktów, i innymi podobnymi problemami. Z drugiej strony, Ergo rozszerza UTXO, aby umożliwić
turingowość, ograniczając jednocześnie złożoność samego języka ErgoScript. Ta sama
siła wyrazu jest osiągana w inny i bardziej semantycznie poprawny sposób.

Biorąc pod uwagę wszystkie powyższe punkty, powinno być jasne, że model Ergo ma wiele zalet.
W reszcie tego artykułu wprowadzę Cię w koncepcję FlowCards - komponentu dla deweloperów dApp,
który pozwala na projektowanie złożonych kontraktów Ergo w sposób deklaratywny i wizualny.

Od imperatywnego do deklaratywnego

W imperatywnym modelu programowania Ethereum transakcja jest sekwencją operacji
wykonywanych przez maszynę wirtualną Ethereum. Poniższa funkcja Solidity
implementuje transfer tokenów z sender do receiver. Transakcja zaczyna się, gdy
sender wywołuje tę funkcję na instancji kontraktu i kończy, gdy funkcja
zwraca.

// Wysyła ilość istniejących monet od dowolnego wywołującego do adresu
function send(address receiver, uint amount) public {
    require(amount <= balances[msg.sender], "Niewystarczające saldo.");
    balances[msg.sender] -= amount;
    balances[receiver] += amount;
    emit Sent(msg.sender, receiver, amount);
}

Funkcja najpierw sprawdza warunki wstępne, następnie aktualizuje pamięć (tj. salda) i
na koniec publikuje warunek końcowy jako zdarzenie Sent. Gaz, który jest konsumowany przez
transakcję, jest wysyłany do górnika jako nagroda za wykonanie tej transakcji.

W przeciwieństwie do Ethereum, transakcja w Ergo jest strukturą danych zawierającą listę wejściowych monet,
które wydaje, oraz listę monet wyjściowych, które tworzy, zachowując całkowite salda
ERGs i tokenów (w czym Ergo jest podobne do Bitcoina).

Wracając do powyższego przykładu, ponieważ Ergo natywnie wspiera tokeny, w związku z tym dla tego
konkretnego przykładu wysyłania tokenów nie musimy pisać żadnego kodu w ErgoScript. Zamiast tego
musimy stworzyć transakcję 'send' pokazaną na poniższej ilustracji, która opisuje
ten sam transfer tokenów, ale w sposób deklaratywny.

Send

Obrazek wizualnie opisuje następujące kroki, które użytkownik sieci musi
wykonać:

  1. Wybierz niezużyte pudełka nadawcy, zawierające łącznie tB >= amount tokenów i B >= txFee + minErg ERGs.
  2. Utwórz wyjściowe pudełko target, które jest chronione przez publiczny klucz receiver z minErg
    ERGs i amount tokenów T.
  3. Utwórz jedno wyjście fee chronione przez kontrakt minerFee z txFee ERGs.
  4. Utwórz jedno wyjście change chronione przez publiczny klucz sender, zawierające
    B - minErg - txFee ERGs i tB - amount tokenów T.
  5. Utwórz nową transakcję, podpisz ją używając tajnego klucza nadawcy i wyślij do sieci Ergo.

Co ważne, należy zrozumieć, że wszystkie te kroki są wykonywane poza łańcuchem (na przykład używając
Appkit Transaction API) przez aplikację
użytkownika. Węzły sieci Ergo nie muszą powtarzać tego procesu tworzenia transakcji,
muszą jedynie zweryfikować już utworzoną transakcję. Kontrakty ErgoScript są przechowywane w
wejściach transakcji i sprawdzają warunki wydania. Węzeł wykonuje
kontrakty na łańcuchu, gdy transakcja jest weryfikowana. Transakcja jest ważna, jeśli wszystkie
warunki są spełnione.

Zatem w Ethereum, gdy "wysyłamy kwotę od nadawcy do odbiorcy", dosłownie
edytujemy salda i aktualizujemy pamięć za pomocą konkretnego zestawu poleceń. To się dzieje
na łańcuchu i w związku z tym nowa transakcja jest również tworzona na łańcuchu w wyniku tego procesu.

W Ergo (jak w Bitcoinie) transakcje są tworzone poza łańcuchem i węzły sieci jedynie
je weryfikują. Efekty transakcji na stanie blockchaina polegają na tym, że wejściowe monety
(lub pudełka w terminologii Ergo) są usuwane, a wyjściowe pudełka są dodawane do
UTXO set.

W powyższym przykładzie nie używamy kontraktu ErgoScript, ale zakładamy, że sprawdzanie podpisu jest
używane jako warunek wstępny wydania. Jednak w bardziej złożonych scenariuszach aplikacyjnych musimy oczywiście
użyć ErgoScript, co będziemy omawiać w następnej części.

Od zmiany stanu do sprawdzania kontekstu

W przykładzie funkcji send najpierw sprawdziliśmy warunek wstępny (require(amount <= balances[msg.sender],...)) a następnie zmieniliśmy stan (tj. aktualizujemy salda
balances[msg.sender] -= amount). To jest typowe w transakcjach Ethereum. Zanim
zmienimy cokolwiek, musimy sprawdzić, czy jest to ważne.

W Ergo, jak wcześniej omówiliśmy, stan (tj. zestaw UTXO pudełek) zmienia się niejawnie, gdy
ważna transakcja jest dołączana do bloku. Dlatego musimy jedynie sprawdzić warunki wstępne, zanim
transakcja może zostać dodana do bloku. To jest to, co robią kontrakty ErgoScript.

Nie jest możliwe "zmienienie stanu" w ErgoScript, ponieważ jest to język do sprawdzania
warunków wstępnych dla wydania monet. ErgoScript jest czysto funkcjonalnym językiem bez efektów ubocznych, który działa na niezmiennych wartościach danych. Oznacza to, że wszystkie wejścia, wyjścia i
inne parametry transakcji dostępne w skrypcie są niezmienne. To, między innymi,
czyni ErgoScript bardzo prostym językiem, który jest łatwy do nauczenia i bezpieczny w użyciu. Podobnie jak
w Bitcoinie, każde wejściowe pudełko zawiera skrypt, który powinien zwrócić wartość true, aby 1) umożliwić wydanie pudełka (tj. usunięcie z zestawu UTXO) i 2) dodać
transakcję do bloku.

Jeśli jesteśmy pedantyczni, to zatem niepoprawne (mówiąc ściśle) jest myślenie o ErgoScript jako języku
kontraktów Ergo, ponieważ jest to język propozycji (predykatów logicznych, formuł,
etc.), które chronią pudełka przed "nielegalnym" wydaniem. W przeciwieństwie do Bitcoina, w Ergo cały
proces transakcji i część aktualnego kontekstu blockchaina jest dostępna dla każdego skryptu. Dlatego
każdy skrypt może sprawdzić, które wyjścia są tworzone przez transakcję, ich ilości ERG i tokenów
(użyjemy tej możliwości w naszych przykładowych kontraktach DEX), aktualny numer bloku
itd.

W ErgoScript definiujesz warunki, czy zmiany (tj. wydanie monet) są dozwolone
w danym kontekście. To w przeciwieństwie do programowania zmian
imperatywnie w kodzie kontraktu.

Podczas gdy model transakcji Ergo odblokowuje cały szereg aplikacji, takich jak (DEX, DeFi
Apps, LETS, itd.), projektowanie kontraktów jako warunków wstępnych dla wydania monet (lub skryptów ochronnych)
bezpośrednio nie jest intuicyjne. W następnych sekcjach rozważymy użyteczną notację graficzną
do projektowania kontraktów deklaratywnie za pomocą Diagramów FlowCard, które są wizualną
reprezentacją komponentów wykonawczych (FlowCards).

FlowCards mają na celu radykalne uproszczenie rozwoju dApp na platformie Ergo, oferując
wysokopoziomowy deklaratywny język, środowisko wykonawcze, format przechowywania i
graficzną notację
.

Zaczniemy od wysokiego poziomu diagramów i przejdziemy do specyfikacji FlowCard.

Diagramy FlowCard

Pomysł stojący za diagramami FlowCard opiera się na następujących obserwacjach: 1) Pudełko Ergo
jest niezmienne i może być wydane tylko w transakcji, która używa go jako wejścia. 2) Dlatego
możemy narysować przepływ pudełek przez transakcje, tak aby pudełka wpływające do
transakcji były wydawane, a te wypływające były tworzone i dodawane do UTXO. 3) Z tej perspektywy,
transakcja jest po prostu przetwornikiem starych pudełek na nowe, zachowując salda ERGs i tokenów zaangażowanych.

Poniższa ilustracja pokazuje główne elementy transakcji Ergo, które już wcześniej widzieliśmy
(pod teraz nazwą Diagram FlowCard).

Anatomy

Za każdym elementem diagramu kryje się ściśle zdefiniowane znaczenie (semantyka),
aby diagram był wizualną reprezentacją (lub widokiem) podstawowego komponentu wykonawczego
(zwanego FlowCard).

FlowCard może być używany jako komponent wielokrotnego użytku dApp Ergo do tworzenia i inicjowania
transakcji na blockchainie Ergo. Omówimy to w nadchodzących sekcjach.

Teraz przyjrzyjmy się poszczególnym elementom diagramu FlowCard jeden po drugim.

1. Nazwa i parametry

Każda karta przepływu ma nadaną nazwę i listę typowanych parametrów. Jest to podobne do
templatu z parametrami. Na powyższej ilustracji widzimy kartę przepływu Send, która ma pięć parametrów.
Parametry są używane w specyfikacji.

2. Portfel kontraktowy

To kluczowy element karty przepływu. Każde pudełko ma skrypt ochronny. Często jest to
skrypt, który sprawdza podpis w stosunku do klucza publicznego. Ten skrypt jest trywialny w ErgoScript
i jest definiowany jak szablon def pk(pubkey: Address) = { pubkey }, gdzie pubkey jest
parametrem typu Address. Na ilustracji szablon skryptu jest stosowany do
parametru pk(sender), a zatem uzyskuje się konkretny kontrakt portfelowy. Dlatego
pk(sender) i pk(receiver) dają różne skrypty i reprezentują różne portfele
na diagramie, mimo że używają tego samego szablonu.

Portfel kontraktowy zawiera zestaw wszystkich pudełek UTXO, które mają dany skrypt pochodzący z
danego szablonu skryptu przy użyciu parametrów karty przepływu. Na przykład, na ilustracji,
szablon to pk, a parametr pubkey jest zastępowany parametrem karty przepływu sender.

3. Kontrakt

Chociaż kontrakt jest właściwością pudełka, na diagramie grupujemy pudełka według ich
kontraktów, dlatego wygląda to tak, jakby pudełka należały do kontraktów, a nie kontrakty do
pudełek. W przykładzie mamy trzy zainstancjonowane kontrakty pk(sender), pk(receiver) i minerFee. Zauważ, że pk(sender) jest instancjonowaniem
szablonu pk z konkretnym parametrem sender, a minerFee jest instancjonowaniem
zdefiniowanego kontraktu, który chroni pudełka nagrody górnika.

4. Nazwa pudełka

Na diagramie możemy nadać każdemu pudełku nazwę. Oprócz czytelności diagramu, używamy również
nazwy jako synonimu bardziej złożonego dostępu indeksowanego do pudełka w kontrakcie. Na
przykład, change to nazwa pudełka, która może być również używana w warunkach ErgoScript
zamiast OUTPUTS(2). Używamy również nazw pudełek, aby powiązać warunki wydania
z pudełkami.

5. Pudełka w portfelu

Na diagramie pokazujemy pudełka (ciemniejsze prostokąty) jako należące do portfeli kontraktowych
(jaśniejsze prostokąty). Każdy taki prostokąt pudełka jest połączony z szarym prostokątem
transakcji
za pomocą pomarańczowych lub zielonych strzałek
lub obu. Pudełko wyjściowe (z przychodzącą zieloną strzałką) może zawierać wiele linii tekstu, gdzie każda
linia określa warunek, który powinien być sprawdzony jako część transakcji. Pierwsza
linia określa warunek dotyczący ilości ERG, która powinna być umieszczona w pudełku. Inne
linie mogą przyjąć jedną z następujących form:

  1. amount: TOKEN - pudełko powinno zawierać daną amount danego TOKEN
  2. R == value - pudełko powinno zawierać daną value danego rejestru R
  3. boxName ? condition - pudełko o nazwie boxName powinno sprawdzić condition w swoim skrypcie.

Omówimy te warunki w poniższych sekcjach.

6. Ilość ERGs w pudełku

Każde pudełko powinno przechowywać minimalną ilość ERGs. To jest sprawdzane, gdy tworzona transakcja jest
walidowana. Na diagramie ilość ERGs jest zawsze pokazywana jako pierwsza linia (np. B: ERG lub B - minErg - txFee). Typ wartości jako asocjacja B: ERG jest opcjonalny i może
być używany dla czytelności. Gdy wartość jest podana jako formuła, to ta formuła powinna być
przestrzegana przez transakcję, która tworzy pudełko.

Ważne jest, aby zrozumieć, że zmienne takie jak amount i txFee nie są nazwanymi
właściwościami pudełek. Są to parametry całego diagramu i reprezentują pewne
ilości. Innymi słowy, są to wspólne parametry między transakcjami (np. Zlecenie sprzedaży i transakcje Swap z przykładu DEX poniżej dzielą parametr tAmt). Tak więc
taka sama nazwa jest związana z tą samą wartością w całym diagramie (to jest miejsce, gdzie
tworzenie narzędzi bardzo by pomogło). Jednak gdy chodzi o walidację na łańcuchu tych wartości,
tylko jawne warunki, które są oznaczone ?, są przekształcane na ErgoScript. W tym samym czasie wszystkie inne warunki są zapewniane poza łańcuchem podczas budowania transakcji (na przykład w aplikacji używającej API Appkit) i walidacji transakcji, gdy jest dodawana do
blockchaina.

7. Ilość tokenu T

Pudełko może przechowywać wartości wielu tokenów. Tokeny na diagramie są nazwane, a zmienna value
może być powiązana z tokenem T za pomocą wyrażenia value: T. Wartość value
może być podana przez formułę. Jeśli formuła jest poprzedzona nazwą pudełka, jak boxName ? formula,
to również powinna być sprawdzana w skrypcie ochronnym pudełka boxName. Ta
dodatkowa specyfikacja jest bardzo wygodna, ponieważ 1) pozwala na automatyczną walidację wizualnego
designu, a 2) warunki określone w pudełkach diagramu są wystarczające do syntezowania niezbędnych skryptów ochronnych. (więcej na ten temat
poniżej w "Od diagramów do kontraktów ErgoScript")

8. Wejścia Tx

Wejścia są połączone z odpowiednią transakcją za pomocą pomarańczowych
strzałek. Strzałka wejścia może mieć etykietę w następujących formach:

  1. name@index - opcjonalna nazwa z indeksem, tj. fee@0 lub @2. To jest właściwość
    końcowego punktu strzałki. Nazwa jest używana w warunkach powiązanych pudełek,
    a index to pozycja odpowiadającego pudełka w kolekcji INPUTS transakcji.
  2. !action - jest to właściwość źródła strzałki i nadaje nazwę alternatywnej
    ścieżce wydania pudełka (zobaczymy to w przykładzie DEX)

Z powodu alternatywnych ścieżek wydania, pudełko może mieć wiele wychodzących pomarańczowych strzałek, w takim przypadku powinny być one oznaczone różnymi
akcjami.

9. Transakcja

Transakcja wydaje wejściowe pudełka i tworzy wyjściowe pudełka. Wejściowe pudełka są podane przez
pomarańczowe strzałki, a etykiety są oczekiwane, aby umieścić wejścia w
odpowiednich indeksach w kolekcji INPUTS. Wyjściowe pudełka są podane przez zielone strzałki. Każda transakcja powinna zachować ścisłą równowagę wartości ERG
(suma wejść == suma wyjść) i dla każdego tokenu suma wejść >= suma
wyjść. Diagram projektowy wymaga jawnej specyfikacji wartości ERG i tokenów dla wszystkich wyjściowych pudełek, aby uniknąć błędów niejawnych i zapewnić lepszą czytelność.

10. Wyjścia Tx

Wyjścia są połączone z odpowiednią transakcją za pomocą zielonych
strzałek. Strzałka wyjścia może mieć etykietę w następującej formie name@index, gdzie opcjonalna nazwa jest towarzyszona indeksem, tj. fee@0 lub @2. To jest właściwość
końcowego punktu strzałki. Nazwa jest używana w warunkach powiązanych pudełek, a index to pozycja odpowiadającego pudełka w kolekcji OUTPUTS transakcji.

Przykład: Zdecentralizowana giełda (DEX)

Teraz użyjmy powyżej opisanej notacji, aby zaprojektować FlowCard dla dApp DEX. Jest to wystarczająco proste,
ale także ilustruje wszystkie kluczowe cechy diagramów FlowCard,
które wprowadziliśmy w poprzedniej sekcji.

Scenariusz dApp jest pokazany na poniższej ilustracji:
Są trzy uczestników (kupujący,
sprzedawca i DEX) dApp DEX i pięć różnych typów transakcji, które są tworzone przez
uczestników. Kupujący chce wymienić ergAmt ERGs na tAmt tokenów TID (lub odwrotnie, sprzedawca chce sprzedać TID tokeny za ERGs, kto pierwszy wyśle zamówienie, nie ma znaczenia). Zarówno kupujący, jak i sprzedawca mogą w każdej chwili anulować swoje zamówienia. Usługa dopasowywania DEX poza łańcuchem może znaleźć pasujące zamówienia i stworzyć transakcję Swap, aby
zakończyć wymianę.

Poniższy diagram w pełni (i formalnie) określa wszystkie pięć transakcji, które muszą
być tworzone poza łańcuchem przez dApp DEX. Określa również wszystkie warunki wydania, które
powinny być weryfikowane na łańcuchu.

DEX

Omówmy diagram FlowCard i logikę każdej transakcji w szczegółach:

Transakcja zamówienia kupna

Kupujący tworzy transakcję Buy Order. Transakcja wydaje E ilość ERGs
(którą zapiszemy jako E: ERG) z jednego lub więcej pudełek w portfelu pk(buyer). Transakcja tworzy pudełko bid z ergAmt: ERG chronione przez skrypt buyOrder. Skrypt buyOrder jest syntetyzowany z specyfikacji (zobacz
poniżej w "Od diagramów do kontraktów ErgoScript") ręcznie lub automatycznie przez
narzędzie. Chociaż nie musimy definiować skryptu buyOrder jawnie podczas
projektowania, w czasie wykonania pudełko bid powinno zawierać skrypt buyOrder jako
propozycję ochronną (która sprawdza warunki wydania pudełka), w przeciwnym razie warunki
określone na diagramie nie będą sprawdzane.

Pudełko change jest tworzone, aby zrównoważyć sumy wejściowe i wyjściowe transakcji.
Pudełko opłaty transakcyjnej jest pomijane, ponieważ może być dodane automatycznie przez narzędzia. W
praktyce jednak projektant może dodać pudełko opłaty jawnie do diagramu. Pokrywa to
przypadki bardziej złożonych transakcji (jak Swap), gdzie istnieje wiele sposobów na opłacenie
opłaty transakcyjnej.

Anulowanie zamówienia kupna, anulowanie zamówienia sprzedaży

W każdej chwili kupujący może anulować zamówienie, wysyłając transakcję CancelBuy. Transakcja
musi spełniać kontrakt ochronny buyOrder, który chroni pudełko bid.
Jak widać na diagramie, zarówno transakcje Cancel, jak i Swap mogą wydawać
pudełko bid. Gdy pudełko ma alternatywy wydania (lub ścieżki wydania), każda
alternatywa jest identyfikowana przez unikalną nazwę poprzedzoną ! (!cancel i !swap
dla pudełka bid). Każda alternatywna ścieżka ma specyficzne warunki wydania. W naszym przykładzie,
gdy transakcja Cancel Buy wydaje pudełko bid, warunek ?buyer powinien być
spełniony, co odczytujemy jako "podpis dla adresu buyer powinien być przedstawiony w transakcji". Dlatego tylko kupujący może anulować zamówienie kupna. Ten warunek "podpisu" jest wymagany tylko dla alternatywnej ścieżki wydania !cancel i nie jest wymagany dla !swap.

Transakcja zamówienia sprzedaży

Transakcja Sell Order jest podobna do BuyOrder, ponieważ dotyczy tokenów oprócz ERGs. Transakcja wydaje E: ERG i T: TID tokeny z portfela sprzedawcy
(zdefiniowanego jako kontrakt pk(seller)). Dwa wyjścia to ask i change. Zmiana
jest standardowym pudełkiem do zrównoważenia transakcji. Pudełko ask przechowuje tAmt: TID tokenów do wymiany
oraz minErg: ERG - minimalną ilość ERGs wymaganą w każdym pudełku.

Transakcja Swap

To kluczowa transakcja w scenariuszu dApp DEX. Transakcja ma kilka warunków wydania
na wejściowych pudełkach, a te warunki są zawarte w skryptach buyOrder i
sellOrder (które są weryfikowane, gdy transakcja jest dodawana do
blockchaina). Jednak na diagramie te warunki nie są określone w pudełkach bid i
ask, są zamiast tego zdefiniowane w wyjściowych pudełkach transakcji.

To jest konwencja dla poprawy użyteczności, ponieważ większość warunków odnosi się do właściwości
wyjściowych pudełek. Moglibyśmy określić te właściwości w pudełku bid, ale wtedy musielibyśmy
użyć bardziej złożonych wyrażeń.

Rozważmy wyjście utworzone przez strzałkę oznaczoną buyerOut@0. Ta etykieta mówi
nam, że wyjście znajduje się na indeksie 0 w kolekcji OUTPUTS transakcji i
że na diagramie możemy odwołać się do tego pudełka za pomocą nazwy buyerOut. Tak więc możemy oznaczyć
zarówno samo pudełko, jak i strzałkę, aby nadać pudełku nazwę.

Warunki pokazane w pudełku buyerOut mają formę bid ? condition, co oznacza,
że powinny być weryfikowane na łańcuchu w celu wydania pudełka bid.
Warunki mają następujące znaczenie:

  • tAmt: TID wymaga, aby pudełko miało tAmt ilości tokenu TID
  • R4 == bid.id wymaga, aby rejestr R4 w pudełku był równy id pudełka bid.
  • script == buyer wymaga, aby pudełko buyerOut miało skrypt portfela, w którym się znajduje na diagramie, tj. pk(buyer)

Podobne właściwości są dodawane do pudełka sellerOut, które jest określone jako znajdujące się na indeksie 1
i nazwa jest nadawana mu za pomocą etykiety na samym pudełku, a nie na strzałce.

Transakcja Swap wydaje dwa pudełka bid i ask, używając ścieżki wydania !swap na obu,
jednak w przeciwieństwie do !cancel warunki na tej ścieżce nie są określone. To jest miejsce, gdzie
prefiksy bid ? i ask ? wchodzą w grę. Są one używane, aby warunki wymienione w pudełkach buyerOut i
sellerOut zostały przeniesione do ścieżki wydania !swap pudełek bid i ask
odpowiednio.

Jeśli spojrzysz na warunki wyjściowych pudełek, zobaczysz, że dokładnie określają
wymianę wartości między portfelami sprzedawcy i kupującego. Kupujący otrzymuje wymaganą ilość
tokenu TID, a sprzedawca otrzymuje odpowiadającą ilość ERGs. Transakcja Swap
jest tworzona, gdy istnieją dwa pasujące pudełka z kontraktami buyOrder i sellOrder.

Od diagramów do kontraktów ErgoScript

Interesujące w specyfikacjach FlowCard jest to, że możemy je wykorzystać do automatycznego
generowania niezbędnych skryptów ErgoTree.
Z odpowiednim wsparciem narzędziowym można to zrobić automatycznie, ale w przypadku braku
można to zrobić ręcznie. Tak więc, FlowCard pozwala nam uchwycić i wizualnie
reprezentować wszystkie wybory projektowe i szczegóły semantyczne dApp Ergo.

To, co zamierzamy zrobić następnie, to mechanicznie stworzyć kontrakt buyOrder z
informacji podanych w karcie przepływu DEX.

Przypomnijmy, że każdy skrypt jest propozycją (wyrażeniem o wartości boolowskiej), które powinno ocenić
się na true, aby umożliwić wydanie pudełka. Gdy mamy wiele warunków do spełnienia w tym samym
time, możemy je połączyć w formułę logiczną, używając operacji binarnej AND, a jeśli mamy
alternatywy (niekoniecznie wykluczające) możemy je umieścić w operacji OR.

Pudełko buyOrder ma alternatywne ścieżki wydania !cancel i !swap. Tak więc,
kod ErgoScript powinien mieć operację OR z dwoma argumentami - jednym dla każdej ścieżki wydania.

/** kontrakt buyOrder */
{
  val cancelCondition = {}
  val swapCondition = {}
  cancelCondition || swapCondition
}

Formuła dla wyrażenia cancelCondition jest podana w ścieżce wydania !cancel
pudełka buyOrder. Możemy bezpośrednio uwzględnić ją w skrypcie.

/** kontrakt buyOrder */
{
  val cancelCondition = { buyer }
  val swapCondition = {}
  cancelCondition || swapCondition
}

Dla ścieżki wydania !swap pudełka buyOrder warunki są określone w
wyjściowym pudełku buyerOut transakcji Swap. Jeśli po prostu uwzględnimy je w
swapCondition, otrzymamy składniowo niepoprawny skrypt.

/** kontrakt buyOrder */
{
  val cancelCondition = { buyer }
  val swapCondition = {
    tAmt: TID &&
    R4 == bid.id &&
    @contract
  }
  cancelCondition || swapCondition
}

Możemy jednak przetłumaczyć warunki z składni diagramu na wyrażenia ErgoScript,
stosując następujące proste zasady:

  1. buyerOut@0 ==> val buyerOut = OUTPUTS(0)
  2. tAmt: TID ==> tid._2 == tAmt, gdzie tid = buyerOut.tokens(TID)
  3. R4 == bid.id ==> R4 == SELF.id, gdzie R4 = buyerOut.R4[Coll[Byte]].get
  4. script == buyer ==> buyerOut.propositionBytes == buyer.propBytes

Zauważ, że na diagramie TID reprezentuje identyfikator tokenu, ale ErgoScript nie ma dostępu do
tokenów według identyfikatorów, więc nie możemy napisać tokens.getByKey(TID). Z tego powodu, gdy
diagram jest tłumaczony na ErgoScript, TID staje się nazwanym stałym indeksem w
kolekcji tokens pudełka. Konkretna wartość stałej jest przypisywana, gdy transakcja
BuyOrder z pudełkiem buyOrder jest tworzona. Zgodność i
spójność między rzeczywistym tokenId, stałą TID i rzeczywistymi tokenami pudełka
buyerOut jest zapewniana przez kod aplikacji poza łańcuchem, co jest całkowicie
możliwe, ponieważ wszystkie transakcje są tworzone przez aplikację przy użyciu FlowCard jako
guiding specification. To może brzmieć zbyt skomplikowanie, ale to jest część tłumaczenia
z specyfikacji diagramu na rzeczywisty kod aplikacji wykonawczy, z których większość można
zautomatyzować.

Po transformacji możemy uzyskać poprawny skrypt, który sprawdza wszystkie wymagane
warunki wstępne dla wydania pudełka buyOrder.

/** kontrakt buyOrder */
def DEX(buyer: Addrss, seller: Address, TID: Int, ergAmt: Long, tAmt: Long)
{
  val cancelCondition: SigmaProp = { buyer }      // weryfikacja podpisu kupującego (ProveDlog)
  val swapCondition = OUTPUTS.size > 0 && {       // zabezpieczenie dostępu do OUTPUTS
    val buyerOut = OUTPUTS(0)                     // z buyerOut@0
    buyerOut.tokens.size > TID && {               // zabezpieczenie dostępu do tokenów
      val tid = buyerOut.tokens(TID)
      val regR4 = buyerOut.R4[Coll[Byte]]
      regR4.isDefined && {                        // zabezpieczenie dostępu do R4
        val R4 = regR4.get
        tid._2 == tAmt &&                             // z tAmt: TID 
        R4 == SELF.id &&                              // z R4 == bid.id
        buyerOut.propositionBytes == buyer.propBytes  // z script == buyer
      }
    } 
  }
  cancelCondition || swapCondition
}

Podobny skrypt dla pudełka sellOrder można uzyskać, stosując te same zasady tłumaczenia.
Dzięki wsparciu narzędzi kod kontraktów można mechanicznie generować z
specyfikacji diagramu.

Wnioski

Deklaratywne modele programowania już wygrały bitwę z imperatywnym programowaniem
w wielu dziedzinach aplikacji, takich jak Big Data, Przetwarzanie strumieniowe, Głębokie uczenie, Bazy danych,
etc. Ergo jest pionierem deklaratywnego modelu rozwoju dApp jako lepszej i bezpieczniejszej
alternatywy dla obecnie popularnego imperatywnego modelu smart kontraktów.

Koncepcja FlowCard przesuwa fokus z pisania kontraktów ErgoScript na
ogólny przepływ wartości (stąd nazwa), w taki sposób, że ErgoScript zawsze
może być generowany z nich. Nigdy nie będziesz musiał patrzeć na kod ErgoScript, gdy narzędzia
będą gotowe.

Oto możliwe następne kroki dla przyszłej pracy:

  1. Format przechowywania dla specyfikacji FlowCard i odpowiadający ustandaryzowany format pliku EIP
    (Json/XML/Protobuf). To pozwoli różnym narzędziom (Edytor diagramów, Czas wykonania, dApps itd.)
    na tworzenie i używanie plików *.flowcard.

  2. Przeglądarka FlowCard, która może generować diagramy z plików *.flowcard.

  3. Czas wykonania FlowCard, który może uruchamiać pliki *.flowcard, tworzyć i wysyłać transakcje do sieci Ergo.

  4. Narzędzie projektanta FlowCard, które może uprościć rozwój złożonych diagramów. To
    uczyni projektowanie i walidację kontraktów Ergo przyjemnym doświadczeniem, bardziej przypominającym rysowanie
    niż kodowanie. Dodatkowo, poprawność całego scenariusza dApp może być
    weryfikowana i kontrolowana przez narzędzia.

Odniesienia

Share post

Ergo Infrastructure DAO: Decentralizacja Kręgosłupa Ekosystemu Ergo

Ergo Infrastructure DAO: Decentralizacja Kręgosłupa Ekosystemu Ergo

Misja Ergo zawsze była zakorzeniona w decentralizacji, nie tylko na warstwie konsensusu, ale w całym stosie.

Ergo Platform

13 sierpnia 2025

Mew Finance: Zabawne narzędzie DeFi dla ekosystemu Ergo

Mew Finance: Zabawne narzędzie DeFi dla ekosystemu Ergo

Mew Finance to zestaw aplikacji zdecentralizowanych na blockchainie Ergo.

Ergo Platform

12 sierpnia 2025

Lithos: Decentralizacja wydobycia z użyciem pul on-chain

Lithos: Decentralizacja wydobycia z użyciem pul on-chain

Lithos to nowy protokół zaprojektowany w celu przekształcenia sposobu działania pul wydobywczych poprzez przeniesienie ich na łańc.

Ergo Platform

24 lipca 2025

Sigma 6.0: Mądrzejszy, bardziej elastyczny Ergo

Sigma 6.0: Mądrzejszy, bardziej elastyczny Ergo

Sigma 6.0 to główna proponowana aktualizacja blockchaina Ergo.

Ergo Platform

23 lipca 2025

Kształtowanie przyszłości Rosen: Wezwanie społeczności w sprawie pięciu kluczowych propozycji skarbowych

Kształtowanie przyszłości Rosen: Wezwanie społeczności w sprawie pięciu kluczowych propozycji skarbowych

Współzałożyciel Rosen, Armeanio, złożył pięć nowych propozycji do Skarbu Rosen.

Ergo Platform

9 lipca 2025

Rozszerzony UTXO Ergo i Wzrost Sztucznej Inteligencji Ekonomicznej

Rozszerzony UTXO Ergo i Wzrost Sztucznej Inteligencji Ekonomicznej

Praktyczna Wizja dla Autonomicznych Agentów Ekonomicznych Autonomiczne agenty ekonomiczne na blockchainie Ergo wykonują użyteczną.

Ergo Platform

12 maja 2025

ErgoHACK X: Sztuczna Inteligencja na Blockchainie Ergo

ErgoHACK X: Sztuczna Inteligencja na Blockchainie Ergo

Świętowanie Dekady Zdecentralizowanej Innowacji Dołącz do 10.

Ergo Platform

10 kwietnia 2025