Move se zrodil v raných fázích projektu Libra v roce 2018 - dva zakladatelé Mysten (Evan a já) byli také zakládajícím týmem Libra. Než jsme se rozhodli vytvořit nový jazyk, první tým Libra intenzivně studoval existující případy použití a jazyky chytrých smluv, aby pochopil, co chtějí vývojáři dělat a kde stávající jazyky nedosahují. Klíčovým problémem, který jsme objevili, je, že inteligentní smlouvy jsou o aktivech a řízení přístupu, ale rané jazyky inteligentních smluv postrádaly reprezentaci typu/hodnoty pro oba. Naší hypotézou je, že pokud poskytneme prvotřídní abstrakce pro tyto klíčové koncepty, můžeme výrazně zlepšit zabezpečení inteligentních smluv a produktivitu programátorů inteligentních smluv – mít správný slovník pro daný úkol může znamenat velký rozdíl. V průběhu let se mnoho lidí podílelo na návrhu a implementaci Move, protože se jazyk vyvinul z klíčové myšlenky v jazyk inteligentních smluv bez ohledu na platformu s odvážným cílem stát se „JavaScriptem webu3“.
Dnes s radostí oznamujeme milník v integraci Move a Sui. Funkce Sui Move je kompletní, podporovaná pokročilými nástroji a má rozsáhlou dokumentaci a příklady, včetně následujících částí:
Série výukových programů pro programování pomocí objektů Sui Move Vývojový dokument o základních znalostech, návrhových vzorech a vzorech Sui Move Plug-in pro vylepšení VSCode vyvinutý týmem Mysten Move, který podporuje analýzu kódu a diagnostiku chyb. konstrukce, testování a správa balíčků Move, generování dokumentace a validátor Move integrovaný s sui CLI
Čím je Move jedinečný
Move je multiplatformní vestavěný jazyk. Samotná syntaxe jádra je velmi jednoduchá: má běžné koncepty, jako jsou struktury, celá čísla a adresy, ale nemá koncepty specifické pro blockchain, jako jsou účty a transakce, čas, kryptografie atd. Tyto funkce musí poskytovat blockchainová platforma integrovaná s Move. Důležité je, že tyto blockchainy nevyžadují vlastní moduly Move – každá platforma používá stejný virtuální stroj Move, validátor bajtového kódu, kompilátor, validátor, správce balíčků a CLI, ale tím, že staví na kódu nad těmito základními komponentami a přidává funkce specifické pro blockchain. . Diem byl prvním blockchainem, který vložil Move, a následné blockchainy založené na Move (včetně 0L, StarCoin a Aptos) většinou přijaly přístup ve stylu Diem. I když má Move ve stylu Diem některé skvělé vlastnosti, jak povolená povaha Diem, tak určité detaily implementace Diem blockchainu (zejména model úložiště) ztěžují implementaci některých základních případů použití chytrých smluv. Zejména původní návrhy Move and Diem předcházejí explozi popularity NFT a mají několik zvláštností, díky nimž je implementace případů použití souvisejících s NFT obzvláště složitá. V tomto příspěvku si ukážeme problémy s originálním vkládáním Move ve stylu Diem na třech takových příkladech a popíšeme, jak jsme tento problém vyřešili v Sui Move. Předpokládáme určitou základní znalost Move, ale doufejme, že tyto klíčové body budou srozumitelné každému, kdo má programátorské znalosti.
Hedvábné zkušenosti při vytváření aktiv ve velkém měřítku
Schopnost hromadně vytvářet a distribuovat aktiva je zásadní jak pro přihlášení, tak pro zapojení uživatelů webu3. Možná chce streamer na Twitchi distribuovat pamětní NFT, tvůrce chce poslat vstupenky na speciální událost nebo herní vývojář chce všem hráčům vyslat nové předměty. Zde je (neúspěšný) pokus napsat kód pro hromadnou ražbu aktiv ve stylu Diem Move. Tento kód vezme jako vstup vektor adres příjemců, vygeneruje aktivum pro každého příjemce a pokusí se aktivum převést.
Při přesunu ve stylu Diem je globální úložiště zadáno pomocí párů (adresa, název typu) - to znamená, že každá adresa může uložit maximálně jeden majetek určitého typu. Move_to(receiverient, CoolAsset { ...} se proto pokusí přesunout CoolAsset tak, že jej uloží na adresu příjemce. Tento kód se však nepodaří zkompilovat na řádku move_to(receiverient, ...). Klíčová otázka je , v přesun ve stylu Diem, nemůžete poslat hodnotu typu CoolAsset na adresu A, pokud není transakce odeslána z jiné adresy než A a vlastník účtu vytvořeného v A neodešle transakci a výslovně se nerozhodne přijmout CoolAsset. typ objektu Jedná se o dvě transakce, jen pro získání aktiva Rozhodnutí udělat to má smysl pro Diem, což je povolený systém, který musí pečlivě omezit vytváření účtů a zabránit tomu, aby byly účty omezeny systémem úložiště. Spíše než držení příliš mnoha aktiv pro otevřený systém, který chce používat alokaci aktiv jako mechanismus pro onboarding, nebo jen obecně umožnit aktivům volný tok mezi uživateli, jako je tomu na Ethereu a podobných blockchainech, je to velmi omezené .
Kód pro implementaci stejné funkce v Sui Move je následující:
Globální úložiště Sui Move je klíčováno ID objektu. Každá struktura s páry klíč–hodnota je „objekt Sui“, který musí mít globálně jedinečné pole id. Sui Move zavádí primitivum pro přenos, které lze použít na libovolném objektu Sui namísto použití omezující struktury move_to. Toto primitivum pod kapotou mapuje id na CoolAsset v globálním úložišti a přidává metadata, která označují, že hodnotu vlastní příjemce. Zajímavou vlastností Sui verze mass_mint je, že je prohozena se všemi ostatními transakcemi (včetně dalších transakcí, které volají mass_mint!). Runtime Sui si toho všimne a odešle transakce volající tuto funkci prostřednictvím „rychlé cesty“ vysílání byzantského konsensu, která nevyžaduje konsensus. Takové transakce mohou být buď potvrzeny nebo provedeny paralelně. To nevyžaduje žádné úsilí ze strany programátora (jen napíší výše uvedený kód a běhové prostředí se postará o zbytek.) Možná nenápadně, toto není případ Diem varianty tohoto kódu – i když výše uvedený kód funguje, existuje a volání guid::create vytvoří sporné body s jinými transakcemi, které generují GUID nebo se dotýkají zdrojů účtu. V některých případech je možné přepsat kód přesunu ve stylu Diem, abyste se vyhnuli argumentu, ale mnoho konvenčních způsobů psaní přesunu ve stylu Diem přináší malé překážky, které brání paralelnímu provádění.
Místní vlastnictví aktiv a převody
Pojďme rozšířit kód přesunu ve stylu Diem o řešení, které se skutečně zkompiluje a spustí. Obvyklý způsob, jak toho dosáhnout, je „vzor obalu“: protože Bob nemůže přesunout CoolAsset přímo na Alicinu adresu, požádáme Alici, aby se „přihlásila“ k odběru CoolAsset, přičemž nejprve zveřejníme obal typu CoolAssetStore, který obsahuje typ Collection (stůl). Alice to může udělat voláním funkce opt_in. Poté přidáme kód, který Bobovi umožní přesunout CoolAsset z jeho CoolAssetStore do Alice's CoolAssetStore. V tomto kódu přidáme další vrásku: převody CoolAssets povolíme pouze v případě, že byly vytvořeny alespoň před 30 dny. Tento druh politiky je důležitý pro tvůrce, kteří (například) chtějí zastavit spekulanty v nákupu/propagaci vstupenek na akce, aby bylo pro skutečné fanoušky snazší tyto vstupenky získat za rozumnou cenu.
Tento kód je platný. Ale to je poměrně komplikovaný způsob, jak splnit úkol převodu majetku z Alice na Boba! Pojďme se podívat na další implementaci Sui Move
Tento kód je mnohem kratší. Klíčová věc, kterou je třeba poznamenat, je, že cool_transfer je vstupní funkce (což znamená, že ji může volat přímo runtime Sui prostřednictvím transakce), má však jako vstup parametr typu CoolAsset. V tom je opět kouzlo Sui Runtime Transakce obsahuje sadu ID objektů, se kterými chce pracovat, a když Sui Runtime:
Zanalyzujte ID na hodnotu objektu (nepotřebujete části loan_global_mut a table_remove v kódu ve stylu Diem výše). Zkontroluje, zda je objekt ve vlastnictví odesílatele transakce (eliminuje potřebu sekce signer::address_of a souvisejícího kódu výše). Tato část je obzvláště zajímavá a brzy si ji vysvětlíme: V Sui je součástí runtime kontrola typu hodnoty objektu podle typu parametru volané funkce cool_transfer k parametrům cool_transfer a zavolejte funkci
To umožnilo programátorům Sui Move přeskočit šablonu pro část logiky „Stažení“ a přejít přímo k zábavnější části: zkontrolovat 30denní politiku vypršení platnosti. Podobně je také značně zjednodušena část „vklad“ s převodní strukturou Sui Move vysvětlenou výše. Konečně není třeba představovat typ wrapperu s interní kolekcí, jako je CoolAssetStore – globální úložiště Sui indexované id umožňuje na jednu adresu uložit libovolný počet hodnot daného typu. Dalším rozdílem, na který je třeba upozornit, je to, že cool_transfer ve stylu Diem má 5 způsobů, jak přerušit (tj. selže a naúčtuje uživateli plyn, aniž by dokončil převod), zatímco Sui Move cool_transfer má pouze 1 způsob, jak přerušit: při porušení 30denní zásady. Přesunutí kontrol vlastnictví objektů do běhového prostředí je velkou výhrou nejen z hlediska ergonomie, ale také z hlediska bezpečnosti. Implementace bezpečnosti na úrovni běhu zabrání chybám při implementaci těchto kontrol na konstrukci (nebo na ně úplně zapomene!). Nakonec si všimněte, že podpis funkce vstupního bodu Sui Move cool_transfer( asset: CoolAsset, ...) nám poskytuje mnoho informací o tom, co bude tato funkce dělat (je neprůhlednější než podpisy funkcí ve stylu Diem). Můžeme si myslet, že tato funkce požaduje povolení k přenosu CoolAsset, zatímco jiná funkce f(aktiva: &mut CoolAsset, ...) požaduje povolení k zápisu (ale nikoli přenosu) CoolAsset, a g(aktiva: &CoolAsset, ..) pouze žádá o povolení ke čtení.
Protože jsou tyto informace dostupné přímo v podpisu funkce (nevyžaduje se provádění ani statická analýza!), mohou je přímo používat peněženky a další klientské nástroje. V Sui Wallet pracujeme na žádostech o podpis čitelný pro člověka a využíváme tyto podpisy strukturovaných funkcí k poskytování výzev k povolení ve stylu iOS/Android uživatelům. Peněženka může říkat něco jako: „Tato transakce vyžaduje povolení ke čtení vašeho CoolAsset, zápisu do vaší AssetCollection a převodu vašeho ConcertTicketu. Pokračovat?“.
Lidsky čitelné požadavky na podpis řeší rozsáhlý útočný vektor přítomný na mnoha existujících platformách, včetně těch, které používají Move ve stylu Diem!, kde uživatelé peněženek musí slepě podepisovat transakce, aniž by chápali dopad, který mohou mít. Věříme, že snížení rizikovosti peněženky je kritickým krokem v podpoře běžného přijetí kryptoměnových peněženek a navrhli jsme Sui Move, aby tento cíl podpořila tím, že umožní funkce, jako jsou požadavky na podpis čitelný člověkem.
Spojte různá aktiva
Nakonec se podívejme na příklad sdružování různých typů aktiv. Toto je poměrně běžný případ použití: programátoři mohou chtít zabalit různé typy NFT do kolekce, sbalit položky dohromady a prodat je na trhu nebo přidat přílohy ke stávajícím položkám. Předpokládejme, že máme následující situaci:
Alice definuje objekt postavy pro použití ve hře Alice chce podporovat zdobení své postavy různými typy doplňků třetích stran, které jsou později vytvořeny. Každý by měl být schopen vytvořit doplněk, ale majitel postavy by se měl rozhodnout, zda doplněk přidá. Přenesení postavy by mělo automaticky přenést veškeré její příslušenství.
Tentokrát začneme kódem pro Sui Move. Využijeme dalšího aspektu funkce vlastnictví objektů zabudované do runtime Sui: jeden objekt může být vlastněn jiným objektem. Každý objekt má jedinečného vlastníka, ale nadřazený objekt může mít libovolný počet podřízených objektů. Vztah nadřazený/podřízený objekt je vytvořen pomocí funkce transfer_to_object, která je přidruženým objektem výše uvedené přenosové funkce.
V tomto kódu modul role obsahuje funkci accessorize, která umožňuje vlastníkovi role přidat doplňkový objekt libovolného typu jako podřízený objekt. To umožňuje Bobovi a Clarisse vytvářet vlastní typy ozdob s různými vlastnostmi a funkcemi, které Alice nemá, ale staví na tom, co Alice již udělala. Například Bobova košile může být vybavena pouze v případě, že má oblíbenou barvu postavy, a Clarissin meč lze ovládat pouze tehdy, je-li postava dostatečně silná. Následuje praktická ukázka přesunu ve stylu Diem, ale žádný z nich nebyl úspěšný, to znamená, že přesun ve stylu Diem nemůže dosáhnout výše uvedeného scénáře.
Je vidět, že problémy v Diem-style Move jsou následující
Podporovány jsou pouze kolekce stejného typu (jak ukázal první test), ale doplňky nejsou v zásadě typem objektu kolekce objektů, které lze zabalit, musí být předdefinována (jako ve druhém pokusu) nebo dočasně přidána a další kompozice objektů není podporována (jako ve třetím testu).
Shrnout
Sui je první platformou, která se výrazně odchýlila od původního návrhu Diem ve způsobu použití Move. Navrhnout kombinaci, která plně využívá výhod Move a jedinečných schopností platformy, je umění i věda, která vyžaduje hluboké porozumění jazyku Move a možnostem základního blockchainu. Jsme velmi nadšeni z pokroku, který Sui Move dosahuje, a z nových případů použití, které umožní! ". [1] Dalším argumentem ve prospěch zásady přesunu ve stylu Diem je, že "před přijetím konkrétního typu aktiv se musíte přihlásit." Toto je dobrý mechanismus, jak zabránit spamu. Myslíme však na prevenci spamu Vzhledem k tomu, že patří k aplikační vrstvě, namísto toho, aby uživatelé museli posílat transakce, které stojí skutečné peníze za přihlášení k přijímání aktiv, lze spam snadno řešit (například) na úrovni peněženky pomocí bohatých uživatelsky definovaných zásad a automatických filtrů nevyžádané pošty. .


