Переместить учебник
Переместить учебник

Автор этой статьи:MoveMoon[1]

добро пожаловать в Переместить учебник! В этом уроке мы разработаем Move Некоторые шаги кода включают в себя Move Проектирование, внедрение, модульное тестирование и формальная верификация модулей.

Всего существует девять шагов:

  • Шаг 0: Установка
  • Нет. 1 Шаг: Напишите мне из Нет.один Move модуль
  • Нет. 2 шаг: дляяиз Нет.один Move модуль Добавить модульные тесты
  • Нет. 3 Шаг: Создайте меня из BasicCoinмодуль
  • Нет. 4 шаг:выполнитьяиз BaseCoinмодуль
  • Нет. 5 шаг:существовать BasicCoinмодуль Добавитьи Используйте модульные тесты
  • Нет. 6 Шаг: Сделай меня из BasicCoinмодуль Стандартизация
  • Нет. 7 Шаг: Используйте Move валидатор(Move prover)
  • Нет. 8 шаг: для BasicCoinмодуль Напишите формальную спецификацию

каждыйшагшаг Всеодеялодизайнстановитьсясуществоватьсоответствующийизstep_xавтономный в папке。Например,Если вы хотите пропустить Нет. 1 к Нет. 4 шагизсодержание,Пожалуйста, не стесняйтесь прыгатьк Нет. 5 шаг,потому чтодляяихсуществовать Нет. 5 шаг Изнаписано раньшеизвсекод Всесуществоватьstep_5в папке。существовать Некоторыйшагшагизконец,яих还Сумкавключить больше Расширенные темыиз Дополнительный материал.

Код учебника: https://github.com/move-language/move/tree/main/language/documentation/tutorial.

Давайте начнем прямо сейчас!

Шаг 0: Установка

Если вы еще этого не сделали, откройте терминал и клонируйте Move. repository[2]

код Язык:javascript
копировать
git clone https://github.com/move-language/move.git

Входитьmoveкаталог и запуститеdev_setup.shСкрипт。

код Язык:javascript
копировать
cd move
./scripts/dev_setup.sh -ypt

Следуйте инструкциям сценария, чтобы установить все зависимости Move.

Должен Скрипт Определить переменные средыдобавить вприезжатьтыиз~/.profileв файле。Включите его, выполнив эту командусуществовать Внутри。

код Язык:javascript
копировать
source ~/.profile

Затем установите инструменты командной строки Move, выполнив следующую команду.

код Язык:javascript
копировать
cargo install --path language/tools/move-cli

Вы можете проверить, работает ли это, выполнив следующую команду.

код Язык:javascript
копировать
move --help

Вы должны увидеть что-то вроде этого, а также список и описание некоторых команд.

код Язык:javascript
копировать
move-package
Execute a package command. Executed in the current directory or the closest containing Move package

USAGE:
    move [OPTIONS] <SUBCOMMAND>

OPTIONS:
        --abi                          Generate ABIs for packages
...

еслитыдуматьпопытаться найтиприезжать Какие команды доступныизи ониизэффект,Беги с--helpлоготипиз Команда или подкоманда распечатает документ.。

существовать, прежде чем переходить к следующим шагам,cdприезжать Учебное пособие Оглавление。

код Язык:javascript
копировать
cd <path_to_move>/language/documentation/tutorial

Поддержка перемещения кода Visual Studio

Visual Studio Code имеет официальную поддержку Move. Сначала вам необходимо установить анализатор Move:

код Язык:javascript
копировать
cargo install --path language/move-analyzer

Теперь вы можете открыть VS Код, поиск в панели расширений move-analyzerустановить VS Расширять,и установить его。Подробнееиз Объясните, что это нормальносуществовать РасширятьизREADME[3] найден в

Шаг 1. Напишите свой первый модуль Move.

Изменять Оглавление Входить`step_1/BasicCoin`[4]Оглавление。тыотвечать Долженсмотретьприезжатьодинназывается sourcesиз Оглавление -- Это все, что есть в этом пакете Move код Местосуществоватьизместо。ты还отвечать ДолженсмотретьприезжатьодинMove.tomlдокумент。еслитыпривычный Rust и Cargo,Move.tomlдокументиCargo.tomlдокументсходство,sourcesОглавлениеиsrcОглавлениесходство。

Давайте посмотрим на некоторые Move код! существоватьтывыбиратьиз Открыть в редакторе`sources/FirstModule.move`[5]。тывстречасмотретьприезжатьизсодержание Сразудаэтот:

код Язык:javascript
копировать
// sources/FirstModule.move
module 0xCAFE::BasicCoin {
    ...
}

Это определяет Moveмодуль[6]。модульда Move Компонент кода, который определяется как конкретный адрес: Модуль можно опубликовать по адресу. существуют В этом примере,BasicCoinмодульможет толькосуществовать0xCAFEОпубликовать под。

Примечание переводчика: Модули публикуются под адресом издателя. Стандартная библиотека выпущена по адресу 0x1.

Сейчас существует, давайте посмотрим на этот файл из следующей части,яихопределениеодин Структура[7]выражатьодинс данным Valueиз Coin

код Язык:javascript
копировать
module 0xCAFE::BasicCoin {
    struct Coin has key {
        value: u64,
    }
    ...
}

Просматривая остальную часть файла, мы видим определение функции, которая создает CoinСтруктураихрани этосуществоватьодинна счету:

код Язык:javascript
копировать
module 0xCAFE::BasicCoin {
    struct Coin has key {
        value: u64,
    }

    public fun mint(account: signer, value: u64) {
        move_to(&account, Coin { value })
    }
}

Давайте посмотрим на эту функцию и ее содержимое:

  • занимаетодин`signer`[8] -- один Неподделываемые жетоны,Представляет собой контроль над конкретным адресом,а такжеодинvalueПриходите чеканить монеты。
  • он использует данныеизсоздание стоимостиодинCoin,и использоватьmove_toоператор сохраняет этосуществоватьaccountВниз。

Давайте убедимся, что его можно построить! Это можно сделать черезсуществоватьпрограммное обеспечение Сумкав папке(`step_1/BasicCoin`[9])Вниз,использоватьbuildкоманда для завершения。

код Язык:javascript
копировать
move build

Расширенные концепции

  • Вы можете создать пустое место с помощью команды Переместить Сумку:
код Язык:javascript
копировать
  move new <pkg_name>
  • Move Код также может быть размещен в некоторых других местах. о Move Система пакетов из Подробнее может существоватьMove книга[10]найден в。
  • оMove.tomlдокументиз Более подробная информация доступнасуществоватьMove книгаизчасть упаковки[11]найден в。
  • Move такжеподдерживатьжизньимяадрес[12]изидея,Именованные адреса — это способ параметризации источника перемещения.,такты Сразу МожетделатьиспользоватьдругойизNamedAddrзначение для компиляциимодуль,таким образом получитьприезжатьдругойизбайт-код,Вы можете выполнить развертывание на основе адреса, который вы контролируете. Если часто использовать,МожетсуществоватьMove.tomlв файлеиз[address]частично определить,Например:
код Язык:javascript
копировать
  [addresses]
  SomeNamedAddress = "0xC0FFEE"
  • Move серединаиз Структура[13]Можетодеяло赋予другойизспособность(abilities)[14],Эти возможности описывают, что можно сделать с этим типом. Есть четыре разные способности:
  • copy:разрешено иметь этоспособностьизтипиззначениекопировать。
  • drop:разрешено иметь этоспособностьизтипиззначениевыбросить(разрушать)。
  • store:разрешено иметь этоспособностьизтипиз Стоит сэкономитьсуществоватьв глобальном хранилищеиз Структурасередина。
  • key: Этому типу разрешено выполнять глобальные операции хранения и ключи.

Поэтому в BasicCoinмодульсередина,яих说 CoinСтруктура Можетделатьдляглобальное хранилищеизодинключ,Так как у него нет других возможностей,Его нельзя копировать, выбрасывать,Или, как для хранилища без ключа, существует хранилище. поэтому,тыне могукопировать Монету нельзя потерять случайно Coin

  • функция[15]по умолчаниюда частный(частныйиз),также Можетдаpublic(общественныйиз),`public(friend)`[16],илиpublic(script)。Чтосередина Последнее объяснениеэтотфункция Можетотторговля Скриптсерединанастраиватьиспользовать。public(script)функциятакже Можетодеяло Что他public(script)функциянастраиватьиспользовать。
  • move_toдапятьдругойизглобальное хранилище操делать符[17]№1。

Шаг 2. Добавьте модульные тесты для первого модуля Move.

Сейчас существуют мы посмотрели на наш из Нет.один Move модуль,Давайте проведем тест,чтобы обеспечитьпроходить Изменять Оглавлениеприезжать`step_2/BasicCoin`[18],делатьчеканка монетяих期望изспособ работы。Move Модульные тесты в Rust Юнит-тесты в схожи, если вы с ними знакомы -- тестиспользовать#[test]комментировать,И как обычный из Move Функции пишутся одинаково.

ты Можетиспользоватьpackage testкоманда для запуска тестов。

код Язык:javascript
копировать
move test

сейчассуществоватьпозволятьяихвзгляни`FirstModule.move`документ[19]изсодержание。ты Волясмотретьприезжатьэтот тест。

код Язык:javascript
копировать
module 0xCAFE::BasicCoin {
    ...
    // Declare a unit test. It takes a signer called `account` with an
    // address value of `0xC0FFEE`.
    #[test(account = @0xC0FFEE)]
    fun test_mint_10(account: signer) acquires Coin {
        let addr = 0x1::signer::address_of(&account);
        mint(account, 10);
        // Make sure there is a `Coin` resource under `addr` with a value of `10`.
        // We can access this resource and its value since we are in the
        // same module that defined the `Coin` resource.
        assert!(borrow_global<Coin>(addr).value == 10, 0);
    }
}

Это объявление файла с именем test_mint_10из Модульное тестирование,существовать accountВнизкастингодин valueдля 10из CoinСтруктура。Затем Проверить хранилищесерединаизмонетаданетиassert!настраиватьиспользоватьиз Ожидаемое значение соответствует。если утверждение не выполнено,Юнит-тест завершится неудачей.

Продвинутые концепции и упражнения

  • Существует множество аннотаций, связанных с тестированием, которые стоит изучить.,этоих Можетсуществоватьздесь[20]попытаться найтиприезжать。тывстречасуществоватьшагшаг 5 серединасмотретьприезжать Чтосерединаиз Некоторыйделатьиспользовать。
  • существования Перед запуском модульных тестов всегда нужно добавлять единицу к Move Стандартная библиотека зависимостей. Это можно сделать путем существования Move.tomlиз[dependencies]Частично добавленоодинзаписи для завершения,Например:
код Язык:javascript
копировать
  [dependencies]
  MoveStdlib = { local = `../../../../move-stdlib/`, addr_subst = { `std` = `0x1` } }

Уведомление,Возможно, вам придется изменить путь,указать на это<path_to_move>/languageВнизизmove-stdlibОглавление。тытакже Можетобозначение git иззависимость。ты Можетсуществоватьздесь[21]Читать далеео Move Содержимое зависимостей пакета.

упражняться
  • Измените утверждениедля11,Тест не пройдет。попытаться найтиприезжатьодин Можетперешел кmove testЗаказизпараметр,Он покажет глобальный статус, если тест не пройден. Это должно выглядеть так:
код Язык:javascript
копировать
  ┌── test_mint_10 ──────
  │ error[E11001]: test failure
  │    ┌─ ./sources/FirstModule.move:24:9
  │    │
  │ 18 │     fun test_mint_10(account: signer) acquires Coin {
  │    │         ------------ In this function in 0xcafe::BasicCoin
  │    ·
  │ 24 │         assert!(borrow_global<Coin>(addr).value == 11, 0);
  │    │         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Test was not expected to abort but it aborted with 0 here
  │
  │
  │ ────── Storage state at point of failure ──────
  │ 0xc0ffee:
  │       => key 0xcafe::BasicCoin::Coin {
  │           value: 10
  │       }
  │
  └──────────────────
  • попытаться найтиприезжатьодинпозволятьтысобиратьтест Покрытиеинформацияизпараметр,Затемделатьиспользоватьmove coverageЗаказ查смотреть Покрытиестатистикаиисточниккод Покрытие。

Нет. 3 шаг:дизайнBasicCoinмодуль

В этом разделе мы разработаем реализацию, которая по сути Coin и Баланс интерфейсизмодуль, Монета Можетсуществоватьдругойадрес Вниздержатьиз Балансмеждукастингипередача。

Сигнатура публичной функции Move выглядит следующим образом:

код Язык:javascript
копировать
/// Publish an empty balance resource under `account`'s address. This function must be called before
/// minting or transferring to the account.
public fun publish_balance(account: &signer) { ... }

/// кастинг `amount` tokens приезжать `mint_addr`. Нужен модульиз owner Авторизовать
public fun mint(module_owner: &signer, mint_addr: address, amount: u64) acquires Balance { ... }

/// возвращаться `owner` из Баланс
public fun balance_of(owner: address): u64 acquires Balance { ... }

/// Transfers `amount` of tokens from `from` to `to`.
public fun transfer(from: &signer, to: address, amount: u64) acquires Balance { ... }

Далее мы рассмотрим структуры данных, необходимые этому модулю.

один Move Модули не имеют собственного места для хранения. Напротив, двигаться из «Глобальное хранилище» (то, что мы называем нашим состоянием блокчейна) индексируется на основе адресов. Каждый адрес имеет Move модуль(код)и Move ресурс (ценность).

Глобальное хранилище в синтаксисе Rust выглядит примерно так.

код Язык:javascript
копировать
struct GlobalStorage {
    resources: Map<address, Map<ResourceType, ResourceValue>>
    modules: Map<address, Map<ModuleName, ModuleBytecode>>
}

Рядом с каждым адресом Move Капиталисточникхранилищедаодиноттипприезжатьценитьизкартографирование。(одинхорош в наблюденииизчитатели могут Уведомлениеприезжать,этот意味着каждыйадресможет толькоиметькаждыйтипизодинценить)。Это удобнодляяих提供Понятноодинкадресдляиндексизместныйкартографирование。существоватьяихиз BasicCoinмодульсередина,яихопределение Понятнок Вниз BalanceКапиталисточник,Представляет каждый адрес, владеющий количеством монет.

код Язык:javascript
копировать
/// Struct representing the balance of each address.
struct Balance has key {
    coin: Coin // same Coin from Step 1
}

Грубо говоря, двигайтесь Статус блокчейна должен быть таким:

Расширенные темы

public(script)функция

Только сpublic(script)видимостьизфункция Можетсуществоватьторговлясередина直接настраиватьиспользовать。потому чтоэтот,еслитыдуматьотторговлясередина直接настраиватьиспользоватьtransferметод,Вам необходимо изменить его подпись с из на для:

код Язык:javascript
копировать
public(script) fun transfer(from: signer, to: address, amount: u64) acquires Balance { ... }

существоватьздесь[22]Читать далеео Move Видимость функции из описания.

Сравнение с Ethereum/Solidity

На большинстве Ethereum ERC-20 договорсередина,каждыйадресиз Балансхранитсясуществоватьодинmapping(address => uint256)типизпеременные состояниясередина。Эта переменная состояния хранитсуществовать Конкретные смарт-контрактыизхранилищесередина。

Состояние блокчейна Ethereum может выглядеть так:

Нет. 4 шаг:выполнитьBaseCoinмодуль

яих已经существоватьstep_4в папкедлятысоздавать Понятноодин Move Сумка,имядляBasicCoinsourcesдокументпапка Сумка Содержит Понятно Сумкасерединавсе Move модульизисточниккод,СумкавключатьBasicCoin.move。существоватьэтот разделсередина,яих Воля仔细研究一Вниз`BasicCoin.move`[23]виз Реализация метода。

Скомпилируйте наш код

позволятьяихпервыйсуществовать`step_4/BasicCoin`[24]в папкебегатьк Вниз Заказ,пытатьсяделатьиспользовать Move Код сборки пакета.

код Язык:javascript
копировать
move build

Реализация метода

сейчассуществоватьпозволятьяих仔细взгляни`BasicCoin.move`[25]виз Реализация метода。

метод publish_balance.

этотметодвыпускатьодинBalanceКапиталисточникприезжатьодин Данныйизадрес。потому чтодляэтот Капиталисточник需要проходитьмонетаили Перевести деньгиперенимать Coin,Местокpublish_balanceметоддолжно бытьиспользоватьсемья(Сумкавключатьмодульвсе ВОЗ)существоватьперенимать coin звонил раньше.

этотметодделатьиспользоватьmove_to操делать Приходитьвыпускать Капиталисточник。

код Язык:javascript
копировать
let empty_coin = Coin { value: 0 };
move_to(account, Balance { coin:  empty_coin });

метод mint

mintметоддляодин Данныйиз Счеткастинг Coin。здесьяих要求mintДолжно бытьприезжатьмодульвсе ВОЗиз Авторизовать。яихделатьиспользовать assert заявление для обеспечения исполнения.

код Язык:javascript
копировать
assert!(signer::address_of(&module_owner) == MODULE_OWNER, errors::requires_address(ENOT_MODULE_OWNER));

Move серединаизутверждениезаявление Можеттакделатьиспользовать:assert! (<predicate>, <abort_code>);。Это означает, что если<predicate>для Фальшивый,那么Сразуиспользовать<abort_code>серединаконецторговля。здесьMODULE_OWNERиENOT_MODULE_OWNERВседасуществоватьмодульиз Начальное определениеизпостоянный。иerrorsмодульопределение Понятнояих Можетделатьиспользоватьиз Распространенные категории ошибок。ценитьпридется Уведомлениеизда,Move существование является транзакционным во время исполнения из -- Местокесливнесейчасabort[26],Не нужно сбрасывать статус,потому чтодля Транзакцияиз Изменения не сохраняютсяприезжатьна блокчейне。

Затемяих Воляодинценаценитьдляamountиз Coin Депозитmint_addrиз Баланс。

код Язык:javascript
копировать
deposit(mint_addr, Coin { value: amount });

**метод balance_of **

яихделатьиспользоватьborrow_global,Один из мировых операторов хранения,Чтение из глобального хранилища.

код Язык:javascript
копировать
borrow_global<Balance>(owner).coin.value
                 |       |       \    /
        resource type  address  field names

метод transfer

этотфункцияотfromиз Баланссерединаизвлекать Токени Воля Токен Депозитtoиз Баланссередина。яих仔细研究一ВнизwithdrawВспомогательныйфункция:

код Язык:javascript
копировать
fun withdraw(addr: address, amount: u64) : Coin acquires Balance {
    let balance = balance_of(addr);
    assert!(balance >= amount, EINSUFFICIENT_BALANCE);
    let balance_ref = &mut borrow_global_mut<Balance>(addr).coin.value;
    *balance_ref = balance - amount;
    Coin { value: amount }
}

существоватьметодизначинать,яихутверждение Вывод денегиз Счетиметь достаточноиз Баланс。Затемяихделатьиспользоватьborrow_global_mutполучитьглобальное хранилищеизпеременный индексиспользовать,&mutодеялоиспользовать Приходитьсоздаватьодин Структураизпеременный индексиспользовать[27]。Затемяихпроходитьэтотпеременный индексиспользовать Приходить修改余额,ивозвращатьсяодин С суммой выводаизновый Coin。

упражняться

В нашем измодуле есть два «TODO», которые мы оставляем читателям как «дурапражняться».

  • Заканчиватьвыполнитьpublish_balanceметод。
  • выполнить depositметод。

этотупражнятьсяизрешение Можетсуществовать`step_4_sol`[28]документпапканайден в。

наградаупражняться

  • Что произойдет, если мы внесем на баланс слишком много токенов?

Нет. 5 шаг:добавить виделатьиспользоватьBasicCoinмодульиз Модульное тестирование

существуют на этом этапе,Мы собираемся рассмотреть все различные модульные тесты, которые мы пишем.,Чтобы осветить наше существование Нет, напишите исходник в четыре шага. Мы также рассмотрим некоторые инструменты, которые можно использовать для написания тестов.

для работы,существовать`step_5/BasicCoin`[29]в папкебегатьpackage testЗаказ:

код Язык:javascript
копировать
move test

тыотвечать Долженсмотретьприезжатьчто-то вроде этогоизвещь:

код Язык:javascript
копировать
INCLUDING DEPENDENCY MoveStdlib
BUILDING BasicCoin
Running Move unit tests
[ PASS    ] 0xcafe::BasicCoin::can_withdraw_amount
[ PASS    ] 0xcafe::BasicCoin::init_check_balance
[ PASS    ] 0xcafe::BasicCoin::init_non_owner
[ PASS    ] 0xcafe::BasicCoin::publish_balance_already_exists
[ PASS    ] 0xcafe::BasicCoin::publish_balance_has_zero
[ PASS    ] 0xcafe::BasicCoin::withdraw_dne
[ PASS    ] 0xcafe::BasicCoin::withdraw_too_much
Test result: OK. Total tests: 7; passed: 7; failed: 0

взгляни`BasicCoin`модуль[30]серединаизтест,Мы стараемся, чтобы каждый модульный тест существовал как отдельный тест из строки.

упражняться

После прочтения теста,пытатьсясуществоватьBasicCoinмодульсередина Писатьодинимядляbalance_of_dneиз Модульное тестирование,тестсуществоватьbalance_ofодеялонастраиватьиспользоватьизадрес Вниз Не существуетсуществоватьBalanceКапиталисточникиз Состояние。Должно быть всего несколько строк!

этотупражнятьсяизрешение Можетсуществовать`step_5_sol`[31]попытаться найтиприезжать。

Нет. 6 шаг:делатьBasicCoinмодуль Стандартизация

существовать Move середина,Мы можем использовать дженерики для определения различных типов входных данных, функций и структур. Дженерики — хороший строительный блок библиотек. существуют В этом разделе,яих Воляделать ПростойизBasicCoinмодульстановитьсядля Дженерики,Таким образом, его можно использовать как модуль для одиночного модуля.,Модуль используется другими пользователями.

Сначала мы добавляем параметры типа в структуру данных:

код Язык:javascript
копировать
struct Coin<phantom CoinType> has store {
    value: u64
}

struct Balance<phantom CoinType> has key {
    coin: Coin<CoinType>
}

Аналогично добавьте параметры типа в метод. Например,withdrawИзменятьстановиться Понятно Внизлапшаизсодержание:

код Язык:javascript
копировать
fun withdraw<CoinType>(addr: address, amount: u64) : Coin<CoinType> acquires Balance {
    let balance = balance_of<CoinType>(addr);
    assert!(balance >= amount, EINSUFFICIENT_BALANCE);
    let balance_ref = &mut borrow_global_mut<Balance<CoinType>>(addr).coin.value;
    *balance_ref = balance - amount;
    Coin<CoinType> { value: amount }
}

взгляни`step_6/BasicCoin/sources/BasicCoin.move`[32]Приходитьвзглянивесьизвыполнить。

существовать В этот момент,Познакомьтесь с Эфириумомизчитатели могут Уведомлениеприезжать,этотмодульиERC20 Стандарт токена[33]изглазизсходство,Для существования смарт-контракта предусмотрен один интерфейс для выбора взаимозаменяемых токенов. Ключевым преимуществом использования дженериков является возможность повторного использования.,Поскольку модуль общей библиотеки уже предоставляет один стандартный выбор,Экземплярный модуль может обеспечивать настройку путем упаковки стандартной выборки.

яих提供Понятноодинимядля`MyOddCoin`[34]из Маленькиймодуль,он создает экземплярCoinтиписделанный на заказ Понятно Чтопередача Стратегия:может толькопередачанечетное числоиз Coin。яих还Сумкавключатьдватест[35]Приходитьтестэтот ХОРОШОдля。ты Можетделатьиспользоватьтысуществовать Нет. 2 шаги Нет. 5 шагизучатьприезжатьиз Заказ Приходитьбегатьэтот些тест。

Расширенные темы

phantomтиппараметр

существоватьCoinиBalanceизопределениесередина,яих声明типпараметрCoinTypeдаphantom ,потому чтодляCoinTypeсуществовать Структураопределениесередина Нетделатьиспользовать,или ВОЗ只делатьдляphantom Используются параметры типа.

здесь[36]Читать далееоphantomтиппараметризинформация。

Дополнительные шаги

существуют Прежде чем перейти к следующему шагу, давайте убедимся, что вы установили все зависимости извалидатора.

Попробуйте запуститьboogie /version。есливнесейчас command not found: boogieизошибкаинформация,Вам нужно будет запустить сценарий установки и применить файл конфигурации.

код Язык:javascript
копировать
# run the following in move repo root directory
./scripts/dev_setup.sh -yp
source ~/.profile

Нет. 7 Шаг: Используйте Move валидатор

Развертывание смарт-контрактов в блокчейне потенциально может манипулировать ценными активами. Метод, использующий строгую математику для описания поведения логических компьютерных систем и их правильности.,Формальная верификация уже используется в блокчейне,к防конец智能договорсерединаизошибка。The Move prover[37]даодин Постоянное развитиеиз Инструменты формальной проверки,использовать Виспользовать Move Язык для написания смарт-контрактов. Пользователи могут использовать Move Specification Language (MSL)[38]указать смарт-контрактыиз Функциональные атрибуты,Затем используйте валидатор, чтобы автоматически проверить их статически. для объясняет, как использовать валидатор,яихсуществоватьBasicCoin.move[39]серединаприсоединиться Понятнок Внизкодфрагмент。

код Язык:javascript
копировать
    spec balance_of {
        pragma aborts_if_is_strict;
    }

неофициально,кодкусокspec balance_of {...}Сумка Содержитметодbalance_ofиз Спецификация недвижимости。

позволятьяихпервыйсуществовать`BasicCoin`Оглавление[40]Внутриделатьиспользоватьк Вниз Заказбегатьвалидатор:

код Язык:javascript
копировать
move prove

Выводится следующее сообщение об ошибке:

код Язык:javascript
копировать
error: abort not covered by any of the `aborts_if` clauses
   ┌─ ./sources/BasicCoin.move:38:5
   │
35 │           borrow_global<Balance<CoinType>>(owner).coin.value
   │           ------------- abort happened here with execution failure
   ·
38 │ ╭     spec balance_of {
39 │ │         pragma aborts_if_is_strict;
40 │ │     }
   │ ╰─────^
   │
   =     at ./sources/BasicCoin.move:34: balance_of
   =         owner = 0x29
   =     at ./sources/BasicCoin.move:35: balance_of
   =         ABORTED

Error: exiting with verification errors

Валидатор в основном сообщает нам,яих需要明确обозначениефункцияbalance_ofВолясерединаконецизсостояние,этотдасуществоватьownerНетиметь КапиталисточникBalance<CoinType>часнастраиватьиспользоватьфункцияborrow_globalделатьстановитьсяиз。для Понятноудалитьэтотошибкаинформация,яихдобавить в Понятноодинaborts_ifсостояние,следующее:

код Язык:javascript
копировать
    spec balance_of {
        pragma aborts_if_is_strict;
        aborts_if !exists<Balance<CoinType>>(owner);
    }

После добавления этого условия,снова Попробуйте запуститьproveЗаказ,чтобы подтвердить отсутствие ошибок проверки.

код Язык:javascript
копировать
move prove

Помимо условия прерывания, мы также хотим определить функциональные свойства. существуют Нет. 8 На этом этапе мы определим BasicCoinмодульизметод Укажите атрибуты для соответствиявалидатор进ХОРОШОПодробнееизпредставлять。

Нет. 8 шаг: для BasicCoinмодуль Напишите формальную спецификацию

метод вывода

метод withdrawиззнакимясуществовать Внизлапша给вне:

код Язык:javascript
копировать
fun withdraw<CoinType>(addr: address, amount: u64) : Coin<CoinType> acquires Balance

Долженметодотадресaddrизвлекатьценаценитьдляamountиз Токен,ивозвращатьсяодинсоздаватьизценаценитьдляamountиз Монета. когда 1)addrНет КапиталисточникBalance<CoinType>или 2)addrсерединаиз Токенколичество Маленький Вamountчас,методwithdrawсерединаконец。яих Можеттакопределениесостояние。

код Язык:javascript
копировать
    spec withdraw {
        let balance = global<Balance<CoinType>>(addr).coin.value;
        aborts_if !exists<Balance<CoinType>>(addr);
        aborts_if balance < amount;
    }

какяихсуществоватьздесьсмотретьприезжатьиз,один блок спецификации может содержать привязки let,этодля Введение в выражениеимясказать。global<T>(address)。Tдаодин Внутринаборфункция,возвращаться addrвиз Капиталисточникценить。balanceдаaddrМестоиметьиз Токенизколичество.exists<T>(address): boolдаодин Внутринаборфункция,если Капиталисточник T существоватьадресвжитьсуществовать,новозвращаться true。дваaborts_ifПункт соответствует вышеуказанномуприезжатьиздвасостояние。Вообще говоря,еслиодинфункцияиметьодин Вот и всеизaborts_ifсостояние,Эти условия будут согласованы друг с другом. По умолчанию,Если пользователь хочет указать условия прерывания,Необходимо перечислить все возможные условия. в противном случае,валидатор выдаст одну ошибку проверки. Однако,еслиpragma aborts_if_is_partialсуществовать spec определяется в блоке, комбинация из условия прерывания (или-ed изодинокийсостояние)только означаетфункцияизсерединаконец。读ВОЗМожетссылкаMSL[41]документ Понятно Узнать большеинформация。

Следующим шагом является определение функциональных атрибутов, следующих двух: ensuresзаявлениесерединаописывать。первый,проходитьделатьиспользоватьlet postобязательность,balance_postУказывает после выполненияaddrиз Баланс,этоотвечать Долженравныйbalance - amount。Затем,возвращатьсяценить(выражатьдляresult)отвечать Должендаодинценаценитьдляamountиз Coin。

код Язык:javascript
копировать
     spec withdraw {
            let balance = global&lt;Balance&lt;CoinType&gt;&gt;(addr).coin.value;
            aborts_if !exists&lt;Balance&lt;CoinType&gt;&gt;(addr);
            aborts_if balance &lt; amount;

        let post balance_post = global&lt;Balance&lt;CoinType&gt;&gt;(addr).coin.value;
        ensures balance_post == balance - amount;
        ensures result == Coin&lt;CoinType&gt; { value: amount };
    }

depositметод

метод depositиззнакимяследующее:

код Язык:javascript
копировать
fun deposit<CoinType>(addr: address, check: Coin<CoinType>) acquires Balance

Метод будет checkДепозит addr。Долженспецификацияопределениеследующее:

код Язык:javascript
копировать
    spec deposit {
        let balance = global<Balance<CoinType>>(addr).coin.value;
        let check_value = check.value;

        aborts_if !exists<Balance<CoinType>>(addr);
        aborts_if balance + check_value > MAX_U64;

        let post balance_post = global<Balance<CoinType>>(addr).coin.value;
        ensures balance_post == balance + check_value;
    }

balanceПредставляет перед выполнениемaddrсерединаиз Токенколичество,check_valueПредставитель хочет Депозитиз Токенколичество.если 1)addrНет КапиталисточникBalance<CoinType>или 2)balanceиcheck_valueИзибольше, чемu64типизмаксимумценить,Метод будетпрекращение。Должен Функциональные атрибуты Проверить баланссуществовать После выполненияданетодеяло正确更новый。

transfer метод

метод transferиззнакимяследующее:

код Язык:javascript
копировать
public fun transfer<CoinType: drop>(from: &signer, to: address, amount: u64, _witness: CoinType) acquires Balance

Долженметодотfromиз Счет Кtoизадреспередачаamountиз Монета. Инструкции следующие:

код Язык:javascript
копировать
    spec transfer {
        let addr_from = signer::address_of(from);

        let balance_from = global<Balance<CoinType>>(addr_from).coin.value;
        let balance_to = global<Balance<CoinType>>(to).coin.value;
        let post balance_from_post = global<Balance<CoinType>>(addr_from).coin.value;
        let post balance_to_post = global<Balance<CoinType>>(to).coin.value;

        ensures balance_from_post == balance_from - amount;
        ensures balance_to_post == balance_to + amount;
    }

addr_fromдаfromизадрес。Затемпридетсяприезжатьaddr_fromиtoсуществоватьперед выполнениеми После выполненияиз Баланс。ensuresПоложение о заявлении,отaddr_fromсерединавычестьamountиз Токенколичество,идобавить вприезжатьtoсередина。Однакои,валидатор выдаст следующее сообщение об ошибке.

код Язык:javascript
копировать
error: post-condition does not hold
   ┌─ ./sources/BasicCoin.move:57:9
   │
62 │         ensures balance_from_post == balance_from - amount;
   │         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   │
   ...

когдаaddr_fromравныйtoчас,Это имущество не удерживается. поэтому,яих Можетсуществоватьметод Добавитьодинутверждениеassert!(from_addr != to),чтобы обеспечитьaddr_fromНетравныйto

упражняться

  • для transferметодвыполнить aborts_ifсостояние。
  • выполнитьmintиpublish_balanceметодизспецификация。

этотупражнятьсяизрешение Можетсуществовать`step_8_sol`[42]попытаться найтиприезжать。

Исходный текст: https://github.com/move-language/move/tree/main/language/documentation/tutorial.

Ссылки

[1]

MoveMoon: https://learnblockchain.cn/people/11436

[2]

Move repository: https://github.com/move-language/move

[3]

README: https://github.com/move-language/move/tree/main/language/move-analyzer/editors/code

[4]

step_1/BasicCoin: https://github.com/solana-labs/move/blob/main/language/documentation/tutorial/step_1/BasicCoin

[5]

sources/FirstModule.move: https://github.com/solana-labs/move/blob/main/language/documentation/tutorial/step_1/BasicCoin/sources/FirstModule.move

[6]

Модуль: https://move-language.github.io/move/modules-and-scripts.html

[7]

Структура: https://move-language.github.io/move/structs-and-resources.html

[8]

signer: https://move-language.github.io/move/signer.html

[9]

step_1/BasicCoin: https://github.com/solana-labs/move/blob/main/language/documentation/tutorial/step_1/BasicCoin

[10]

Move книга: https://move-language.github.io/move/packages.html

[11]

Переместить буклет и часть упаковки: https://move-language.github.io/move/packages.html#movetoml

[12]

Адрес именования: https://move-language.github.io/move/address.html#named-addresses

[13]

Структура: https://move-language.github.io/move/structs-and-resources.html

[14]

Способности: https://move-language.github.io/move/abilities.html

[15]

функция: https://move-language.github.io/move/functions.html

[16]

public(friend): https://move-language.github.io/move/friends.html

[17]

Пять различных глобальных операторов хранения: https://move-language.github.io/move/global-storage-operators.html

[18]

step_2/BasicCoin: https://github.com/solana-labs/move/blob/main/language/documentation/tutorial/step_2/BasicCoin

[19]

FirstModule.moveдокумент: https://github.com/solana-labs/move/blob/main/language/documentation/tutorial/step_2/BasicCoin/sources/FirstModule.move

[20]

здесь: https://github.com/move-language/move/blob/main/language/changes/4-unit-testing.md#testing-annotations-their-meaning-and-usage

[21]

здесь: https://move-language.github.io/move/packages.html#movetoml

[22]

здесь: https://move-language.github.io/move/functions.html#visibility

[23]

BasicCoin.move: https://github.com/solana-labs/move/blob/main/language/documentation/tutorial/step_4/sources/BasicCoin.move

[24]

step_4/BasicCoin: https://github.com/solana-labs/move/blob/main/language/documentation/tutorial/step_4/BasicCoin

[25]

BasicCoin.move: https://github.com/solana-labs/move/blob/main/language/documentation/tutorial/step_4/BasicCoin/sources/BasicCoin.move

[26]

abort: https://move-language.github.io/move/abort-and-assert.html

[27]

Изменяемая ссылка: https://move-language.github.io/move/references.html

[28]

step_4_sol: https://github.com/solana-labs/move/blob/main/language/documentation/tutorial/step_4_sol

[29]

step_5/BasicCoin: https://github.com/solana-labs/move/blob/main/language/documentation/tutorial/step_5/BasicCoin

[30]

BasicCoinМодуль: https://github.com/solana-labs/move/blob/main/language/documentation/tutorial/step_5/BasicCoin/sources/BasicCoin.move

[31]

step_5_sol: https://github.com/solana-labs/move/blob/main/language/documentation/tutorial/step_5_sol

[32]

step_6/BasicCoin/sources/BasicCoin.move: https://github.com/solana-labs/move/blob/main/language/documentation/tutorial/step_6/BasicCoin/sources/BasicCoin.move

[33]

Стандарт токена ERC20: https://ethereum.org/en/developers/docs/standards/tokens/erc-20/

[34]

MyOddCoin: https://github.com/solana-labs/move/blob/main/language/documentation/tutorial/step_6/BasicCoin/sources/MyOddCoin.move

[35]

тест: https://github.com/solana-labs/move/blob/main/language/documentation/tutorial/step_6/BasicCoin/sources/MyOddCoin.move

[36]

здесь: https://move-language.github.io/move/generics.html#phantom-type-parameters

[37]

The Move prover: https://github.com/move-language/move/blob/main/language/move-prover/doc/user/prover-guide.md

[38]

Move Specification Language (MSL): https://github.com/move-language/move/blob/main/language/move-prover/doc/user/spec-lang.md

[39]

BasicCoin.move: https://github.com/solana-labs/move/blob/main/language/documentation/tutorial/step_7/BasicCoin/sources/BasicCoin.move

[40]

BasicCoinОглавление: https://github.com/solana-labs/move/blob/main/language/documentation/tutorial/step_7/BasicCoin

[41]

MSL: https://github.com/move-language/move/blob/main/language/move-prover/doc/user/spec-lang.md

[42]

step_8_sol: https://github.com/solana-labs/move/blob/main/language/documentation/tutorial/step_8_sol

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose