Zanurz się w Move — języku programowania blockchain Libra firmy Facebook

Następnie szczegółowo rozważymy główne cechy języka Move i jakie są jego kluczowe różnice w stosunku do innego, już popularnego języka inteligentnych kontraktów - Solidity (na platformie Ethereum). Materiał jest oparty na badaniu dostępnego online, 26-stronicowego whitepaper.

Wprowadzenie

Move to wykonywalny język kodu bajtowego używany do wykonywania transakcji użytkowników i inteligentnych kontraktów. Proszę zwrócić uwagę na dwie kwestie:

  1. Podczas gdy Move jest językiem kodu bajtowego, który może być wykonywany bezpośrednio na maszynie wirtualnej Move, Solidity (język kontraktu inteligentnego Ethereum) jest językiem wyższego poziomu, który jest najpierw kompilowany do kodu bajtowego przed wykonaniem na EVM (Ethereum Virtual Machine ).
  2. Move może być używany nie tylko do implementacji inteligentnych kontraktów, ale także do niestandardowych transakcji (więcej o tym później), podczas gdy Solidity jest językiem tylko dla inteligentnych kontraktów.


Tłumaczenie wykonał zespół projektowy INDEX Protocol. Już przetłumaczyliśmy obszerny materiał opisujący projekt Libra, teraz czas przyjrzeć się językowi Move bardziej szczegółowo. Tłumaczenie zostało wykonane wspólnie z firmą Habrauser super

Kluczową cechą Move jest możliwość definiowania niestandardowych typów zasobów z semantyką opartą na logice liniowej: zasobu nie można nigdy kopiować ani niejawnie usuwać, a jedynie przenosić. Funkcjonalnie jest to podobne do możliwości języka Rust. Wartości w Rust można przypisać tylko do jednej nazwy na raz. Przypisanie wartości do innej nazwy powoduje, że jest ona niedostępna pod poprzednią nazwą.

Zanurz się w Move — języku programowania blockchain Libra firmy Facebook

Na przykład następujący fragment kodu zwróci błąd: Użycie przeniesionej wartości „x”. Dzieje się tak, ponieważ w Rust nie ma wyrzucania śmieci. Gdy zmienne wyjdą poza zakres, pamięć, do której się odnoszą, również zostanie zwolniona. Mówiąc najprościej, może być tylko jeden „właściciel” danych. W tym przykładzie x jest pierwotnym właścicielem, a następnie y staje się nowym właścicielem. Przeczytaj więcej o tym zachowaniu tutaj.

Reprezentacja zasobów cyfrowych w systemach otwartych

Istnieją dwie właściwości zasobów fizycznych, które trudno przedstawić cyfrowo:

  • Rzadkość (Niedobór, pierwotnie niedobór). Należy kontrolować liczbę aktywów (emisji) w systemie. Należy zabronić powielania istniejących zasobów, a tworzenie nowych jest operacją uprzywilejowaną.
  • Kontrola dostępu... Uczestnik systemu musi być w stanie chronić zasoby za pomocą zasad kontroli dostępu.

Te dwie cechy, które są naturalne dla aktywów fizycznych, muszą zostać zaimplementowane dla obiektów cyfrowych, jeśli chcemy uznać je za aktywa. Na przykład rzadki metal ma naturalny niedobór i tylko ty masz do niego dostęp (na przykład trzymasz go w rękach) i możesz go sprzedać lub wydać.

Aby zilustrować, jak dotarliśmy do tych dwóch właściwości, zacznijmy od następujących zdań:

Sugestia nr 1: Najprostsza zasada bez niedoboru i kontroli dostępu

Zanurz się w Move — języku programowania blockchain Libra firmy Facebook

  • G [K]: = n oznacza aktualizację numeru dostępnego za pomocą klawisza К w globalnym stanie blockchain, w nowym znaczeniu n.
  • transakcja ⟨Alicja, 100⟩ oznacza ustawienie salda konta Alicji na 100.

Powyższe rozwiązanie ma kilka głównych problemów:

  • Alicja może otrzymać nieograniczoną liczbę monet, po prostu wysyłając transakcja ⟨Alice, 100⟩.
  • Monety, które Alicja wysyła do Boba, są bezużyteczne, ponieważ Bob może wysłać sobie nieograniczoną liczbę monet przy użyciu tej samej techniki.

Sugestia nr 2: Uwzględnienie deficytu

Zanurz się w Move — języku programowania blockchain Libra firmy Facebook

Teraz monitorujemy sytuację, aby liczba monet Ka był co najmniej równy n przed transakcją przelewu. Jednak o ile rozwiązuje to problem niedoboru, nie ma informacji o tym, kto może wysłać monety Alicji (na razie każdy może to zrobić, najważniejsze jest, aby nie naruszać zasady ograniczenia ilości).

Oferta nr 3: Połączenie niedoboru i kontroli dostępu

Zanurz się w Move — języku programowania blockchain Libra firmy Facebook

Rozwiązujemy ten problem za pomocą mechanizmu podpisu cyfrowego weryfikacja_sygnatury przed sprawdzeniem salda, co oznacza, że ​​Alicja używa swojego klucza prywatnego do podpisania transakcji i potwierdzenia, że ​​jest właścicielem swoich monet.

Języki programowania Blockchain

Istniejące języki blockchain borykają się z następującymi problemami (wszystkie zostały rozwiązane w Move (uwaga: niestety autor artykułu odwołuje się tylko do Ethereum w swoich porównaniach, więc warto je brać tylko w tym kontekście. Na przykład większość poniższych problemów jest również rozwiązana w EOS.)):

Pośrednia reprezentacja aktywów. Zasób jest kodowany przy użyciu liczby całkowitej, ale liczba całkowita nie jest tym samym, co zasób. W rzeczywistości nie ma typu ani wartości reprezentującej Bitcoin/Ether/<Any Coin>! To sprawia, że ​​pisanie programów korzystających z zasobów jest trudne i podatne na błędy. Wzorce takie jak przekazywanie zasobów do/z procedur lub przechowywanie zasobów w strukturach wymagają specjalnego wsparcia ze strony języka.

Deficyt nie jest rozszerzalny... Język stanowi tylko jeden rzadki zasób. Ponadto środki zaradcze przeciwko niedostatkowi są bezpośrednio wpisane w semantykę samego języka. Deweloper, jeśli chce stworzyć niestandardowy zasób, musi sam dokładnie kontrolować wszystkie aspekty zasobu. To są właśnie problemy inteligentnych kontraktów Ethereum.

Użytkownicy emitują swoje aktywa, tokeny ERC-20, używając liczb całkowitych do określenia zarówno wartości, jak i całkowitej podaży. Za każdym razem, gdy tworzone są nowe tokeny, kod inteligentnej umowy musi niezależnie weryfikować zgodność z regułami emisji. Ponadto pośrednia prezentacja aktywów prowadzi w niektórych przypadkach do poważnych błędów - powielania, dwukrotnego wydatkowania lub nawet całkowitej utraty aktywów.

Brak elastycznej kontroli dostępu... Jedyną obecnie używaną polityką kontroli dostępu jest schemat podpisu wykorzystujący kryptografię asymetryczną. Podobnie jak ochrona niedoboru, zasady kontroli dostępu są głęboko zakorzenione w semantyce języka. Ale jak rozszerzyć język, aby umożliwić programistom definiowanie własnych zasad kontroli dostępu, jest często bardzo trudnym zadaniem.

Dotyczy to również Ethereum, gdzie inteligentne kontrakty nie obsługują natywnej obsługi kryptografii w celu kontroli dostępu. Programiści muszą ręcznie ustawić kontrolę dostępu, na przykład za pomocą modyfikatora onlyOwner.

Mimo że jestem wielkim fanem Ethereum, uważam, że ze względów bezpieczeństwa właściwości aktywów powinny być natywnie obsługiwane przez ten język. W szczególności przeniesienie Etheru do inteligentnego kontraktu wiąże się z dynamiczną wysyłką, co wprowadziło nową klasę błędów znanych jako luki w zabezpieczeniach związane z ponownym wejściem. Dynamiczne wysyłanie oznacza tutaj, że logika wykonania kodu zostanie określona w czasie wykonywania (dynamiczna), a nie w czasie kompilacji (statyczna).

Zatem w Solidity, gdy kontrakt A wywołuje funkcję w kontrakcie B, kontrakt B może uruchomić kod, który nie był zamierzony przez twórcę kontraktu A, co może skutkować luki w zabezpieczeniach związane z ponownym wejściem (umowa A przypadkowo działa jak umowa B dotycząca wypłaty pieniędzy, zanim saldo konta zostanie faktycznie odjęte).

Przenieś podstawy projektowania języka

Zasoby pierwszego rzędu

Na wysokim poziomie interakcja pomiędzy modułami/zasobami/procedurami w języku Move jest bardzo podobna do relacji pomiędzy klasami/obiektami i metodami w językach OOP.
Moduły Move są podobne do inteligentnych kontraktów w innych blockchainach. Moduł deklaruje typy zasobów i procedury definiujące zasady tworzenia, niszczenia i aktualizowania zadeklarowanych zasobów. Ale to wszystko to tylko konwencje („żargon") Przenieść. Zilustrujemy ten punkt nieco później.

Гибкость

Move zwiększa elastyczność Libry poprzez skrypty. Każda transakcja w Librze zawiera skrypt, który jest w istocie podstawową procedurą transakcji. Skrypt może wykonać albo jedną określoną akcję, np. dokonać płatności do określonej listy odbiorców, albo ponownie wykorzystać inne zasoby – np. wywołując procedurę, w której określona jest ogólna logika. Dlatego skrypty transakcyjne Move oferują większą elastyczność. Skrypt może wykorzystywać zarówno zachowania jednorazowe, jak i powtarzalne, podczas gdy Ethereum może wykonywać tylko powtarzalne skrypty (wywołując jedną metodę w przypadku metody inteligentnego kontraktu). Powodem, dla którego nazywa się go „wielokrotnym użytku”, jest to, że funkcje inteligentnego kontraktu mogą być wykonywane wielokrotnie. (notatka: Sprawa jest tutaj bardzo subtelna. Z jednej strony w Bitcoinie istnieją również skrypty transakcyjne w postaci pseudokodu bajtowego. Z drugiej strony, jak rozumiem, Move faktycznie rozwija ten język do poziomu pełnoprawnego języka inteligentnych kontraktów).

bezpieczeństwo

Format pliku wykonywalnego Move to kod bajtowy, który z jednej strony jest językiem wyższego poziomu niż język asemblera, ale niższego poziomu niż kod źródłowy. Kod bajtowy jest sprawdzany w czasie wykonywania (w łańcuchu) pod kątem zasobów, typów i bezpieczeństwa pamięci przy użyciu weryfikatora kodu bajtowego, a następnie wykonywany przez interpreter. Takie podejście pozwala Move zapewnić bezpieczeństwo kodu źródłowego, ale bez procesu kompilacji i konieczności dodawania kompilatora do systemu. Przekształcenie Move w język kodu bajtowego to naprawdę dobre rozwiązanie. Nie trzeba go kompilować ze źródeł, jak ma to miejsce w przypadku Solidity, i nie trzeba się martwić możliwymi awariami lub atakami na infrastrukturę kompilatora.

Sprawdzalność

Naszym celem jest możliwie najłatwiejsze przeprowadzanie kontroli, ponieważ wszystko to odbywa się w łańcuchu (uwaga: online, podczas realizacji każdej transakcji, więc każde opóźnienie prowadzi do spowolnienia całej sieci), jednak początkowo projekt języka jest gotowy do użycia narzędzi do weryfikacji statycznej poza łańcuchem. Chociaż jest to bardziej preferowane, na razie rozwój narzędzi weryfikacyjnych (jako osobnego zestawu narzędzi) został odłożony na przyszłość i obecnie obsługiwana jest tylko weryfikacja dynamiczna w czasie wykonywania (w łańcuchu).

Modułowość

Moduły przenoszenia zapewniają abstrakcję danych i lokalizują krytyczne operacje na zasobach. Enkapsulacja zapewniona przez moduł w połączeniu z ochroną zapewnianą przez system typów Move zapewnia, że ​​właściwości ustawione w typach modułu nie mogą zostać naruszone przez kod spoza modułu. Jest to dość przemyślany projekt abstrakcji, co oznacza, że ​​dane wewnątrz umowy mogą się zmieniać tylko w ramach umowy, a nie poza nią.

Zanurz się w Move — języku programowania blockchain Libra firmy Facebook

Przenieś przegląd

Przykładowy skrypt transakcyjny pokazuje, że złośliwe lub nieostrożne działania programisty poza modułem nie mogą zagrozić bezpieczeństwu zasobów modułu. Następnie przyjrzymy się przykładom wykorzystania modułów, zasobów i procedur do programowania łańcucha bloków Libra.

Płatności peer-to-peer

Zanurz się w Move — języku programowania blockchain Libra firmy Facebook

Liczba monet określona w kwocie zostanie przelana z salda nadawcy do odbiorcy.
Jest tu kilka nowości (zaznaczonych na czerwono):

  • 0x0: adres konta, na którym przechowywany jest moduł
  • Waluta: Nazwa modułu
  • Moneta: typ zasobu
  • Wartość monety zwrócona przez procedurę to wartość zasobu typu 0x0.Currency.Coin
  • ruszaj się (): wartość nie może być użyta ponownie
  • Kopiuj (): wartość może być użyta później

Przeanalizuj kod: w pierwszym kroku nadawca wywołuje procedurę o nazwie wycofać_z_nadawcy z modułu przechowywanego w 0x0.Waluta. W drugim kroku nadawca przekazuje środki odbiorcy, przenosząc wartość zasobu monety do procedury wpłaty modułu 0x0.Waluta.

Oto trzy przykłady błędów w kodzie, które zostaną odrzucone podczas kontroli:
Zduplikuj środki, zmieniając wezwanie ruch (moneta) na kopia (moneta). Zasoby można jedynie przenosić. Próba zduplikowania ilości zasobu (na przykład przez wywołanie kopia (moneta) w powyższym przykładzie) spowoduje błąd podczas sprawdzania kodu bajtowego.

Ponowne wykorzystanie środków poprzez określenie ruch (moneta) dwa razy . Dodanie linii 0x0.Currency.deposit (skopiuj (some_other_payee), przesuń (moneta)) na przykład powyższe umożliwi nadawcy „wydanie” monet dwukrotnie – za pierwszym razem z odbiorcą, a drugi z jakiś_inny_odbiorca. Jest to niepożądane zachowanie, które nie jest możliwe w przypadku zasobu fizycznego. Na szczęście Move odrzuci ten program.

Utrata środków w wyniku odmowy ruch (moneta). Jeśli nie przeniesiesz zasobu (na przykład usuwając linię zawierającą ruch (moneta)), zostanie zgłoszony błąd weryfikacji kodu bajtowego. Chroni to programistów Move przed przypadkową lub umyślną utratą środków.

Moduł walutowy

Zanurz się w Move — języku programowania blockchain Libra firmy Facebook

Każde konto może zawierać 0 lub więcej modułów (pokazanych jako prostokąty) i jedną lub więcej wartości zasobów (pokazanych jako cylindry). Na przykład konto w 0x0 zawiera moduł 0x0.Waluta oraz wartość typu zasobu 0x0.Waluta.Moneta. Konto pod adresem 0x1 ma dwa zasoby i jeden moduł; Konto pod adresem 0x2 ma dwa moduły i jedną wartość zasobu.

Niektóre momenty:

  • Skrypt transakcji jest atomowy - albo jest wykonywany w całości, albo wcale.
  • Moduł to trwały fragment kodu, który jest dostępny na całym świecie.
  • Stan globalny ma strukturę tablicy mieszającej, gdzie kluczem jest adres konta
  • Konta mogą zawierać nie więcej niż jedną wartość zasobu danego typu i nie więcej niż jeden moduł o podanej nazwie (konto pod adresem 0x0 nie może zawierać dodatkowego zasobu 0x0.Waluta.Moneta lub inny moduł o nazwie Waluta)
  • Adres zadeklarowanego modułu jest częścią typu (0x0.Waluta.Moneta и 0x1.Waluta.Moneta są odrębnymi typami, których nie można używać zamiennie)
  • Programiści mogą przechowywać wiele wystąpień tego typu zasobu na koncie, definiując swój niestandardowy zasób - (zasób TwoCoins {c1: 0x0.Currency.Coin, c2: 0x0.Currency.Coin})
  • Możesz odwoływać się do zasobu po jego nazwie bez konfliktów, na przykład możesz odwoływać się do dwóch zasobów za pomocą Dwie monety.c1 и Dwie monety.c2.

Deklaracja zasobów monet

Zanurz się w Move — języku programowania blockchain Libra firmy Facebook
Moduł nazwany Waluta i typ zasobu o nazwie Moneta

Niektóre momenty:

  • Moneta jest strukturą z jednym polem typu u64 (64-bitowa liczba całkowita bez znaku)
  • Tylko procedury modułu Waluta może tworzyć lub niszczyć wartości typu Moneta.
  • Inne moduły i skrypty mogą zapisywać pola wartości lub odwoływać się do nich jedynie za pośrednictwem publicznych procedur dostarczonych przez moduł.

Sprzedaż depozytu

Zanurz się w Move — języku programowania blockchain Libra firmy Facebook

Ta procedura akceptuje zasób Moneta jako dane wejściowe i łączy je z zasobem Monetazapisane na koncie odbiorcy:

  1. Niszczenie zasobu wejściowego Moneta i rejestrowanie jej wartości.
  2. Otrzymanie linku do unikalnego zasobu Coin przechowywanego na koncie odbiorcy.
  3. Zmiana wartości liczby Monet o wartość przekazaną w parametrze podczas wywoływania procedury.

Niektóre momenty:

  • Rozpakuj, wypożycz globalnie - wbudowane procedury
  • Rozpakować Jest to jedyny sposób na usunięcie zasobu typu T. Procedura przyjmuje zasób jako dane wejściowe, niszczy go i zwraca wartość powiązaną z polami zasobu.
  • Pożycz globalnie przyjmuje adres jako dane wejściowe i zwraca referencję do unikalnej instancji T opublikowanej (będącej własnością) tego adresu
  • &mut Moneta to jest link do zasobu Moneta

Implementacja wycofania od nadawcy

Zanurz się w Move — języku programowania blockchain Libra firmy Facebook

Tej procedury:

  1. Pobiera łącze do unikalnego zasobu Moneta, powiązany z kontem nadawcy
  2. Zmniejsza wartość zasobu Moneta poprzez link na określoną kwotę
  3. Tworzy i zwraca nowy zasób Moneta ze zaktualizowanym saldem.

Niektóre momenty:

  • Depozyt może być spowodowane przez każdego, ale wycofać_z_nadawcy ma dostęp jedynie do monet konta wywołującego
  • Uzyskaj adres TxnSender podobny do nadawca wiadomości w Solidności
  • Odrzuć Chyba, że podobny do wymagać w Solidności. Jeśli ta kontrola zakończy się niepowodzeniem, transakcja zostanie zatrzymana, a wszystkie zmiany zostaną wycofane.
  • Pakiet jest to także wbudowana procedura, która tworzy nowy zasób typu T.
  • Jak również Rozpakować, Pakiet można wywołać tylko wewnątrz modułu, w którym opisano zasób T

wniosek

Przeanalizowaliśmy główne cechy języka Move, porównaliśmy go z Ethereum, a także zapoznaliśmy się z podstawową składnią skryptów. Na koniec gorąco polecam sprawdzić oryginalny biały papier. Zawiera wiele szczegółów dotyczących zasad projektowania języków programowania, a także wiele przydatnych linków.

Źródło: www.habr.com

Dodaj komentarz