Написание смарт-контрактов на Rust | Привет, чернила! [Мартовский выпуск Rust Chinese]

задняя часть Rust

Написание смарт-контрактов на Rust | Привет, Ink!

Автор: Ли Дагоу (Ли Аохуа) / Пост-редактор: Чжан Ханьдун


Что такое смарт-контракт WASM?

В прошлом, когда мы говорили о смарт-контрактах, все они были смарт-контрактами Solidity, основанными на EVM.

В настоящее время с развитием технологии смарт-контрактов появилась новая возможность: смарт-контракт WASM,

WASM — это не новый язык программирования, а новый низкоуровневый двоичный синтаксис.

WASM (WebAssembly) — это новый формат байт-кода и совершенно новый лежащий в его основе двоичный синтаксис.Инструкции кода, которые он компилирует, имеют небольшой размер, переносимы, быстро загружаются и совместимы с новым форматом WEB. WASM может поддерживать C/C++/RUST/GO и другие языки для компиляции контрактов после компиляции кода раздела, а разные языки имеют богатые базовые стандартные библиотеки для вызова.

Преимущества ВАСМ:

Будучи совершенно новым форматом байт-кода, WASM благодаря собственным инновациям и оптимизации делает инструкции кода, написанные на поддерживаемых языках, небольшими по размеру, что может быть улучшено с точки зрения хранения, хранения на жестком диске и использования полосы пропускания. оптимизации экономят сетевые ресурсы блокчейна и значительно повышают эффективность передачи по сети.

Использование WASM в смарт-контрактах также будет иметь вышеуказанные характеристики.Наиболее очевидными аспектами являются то, что он требует меньше ресурсов, быстрее и стабильнее выполняет контракты и более эффективно передает информацию по сети. Это может позволить развернуть больше смарт-контрактов в сети блокчейн, а также может предоставить пользователям лучший опыт при использовании смарт-контрактов.

——Анализ преимуществ смарт-контракта WASM:zhuanlan.zhihu.com/p/344347968

Судя по текущей тенденции, публичные сети, такие как Substrate и ETH 2.0, а также ряд сетей альянсов указали, что они будут поддерживать смарт-контракты WASM.

На каких языках можно писать смарт-контракты WASM?

Wasm расширяет семейство языков, доступных разработчикам смарт-контрактов, включая Rust, C/C++, C#, Typescript, Haxe и Kotlin. Это означает, что вы можете писать смарт-контракты на любом языке, с которым вы знакомы.

С точки зрения адаптивности язык Rust в настоящее время лучше адаптируется к смарт-контрактам WASM, цепочка инструментов более полная, а написанные смарт-контракты более безопасны.

Итак, в этой серии в качестве примера будет взят смарт-контракт Ink! на Subtrate, чтобы начать курс 101 по смарт-контрактам WASM.

В этой статье есть ссылка на официальное руководство по Ink!:

субстрат.Дев/субстрат - от...

Конфигурация среды Rust

1. Конфигурация окружения Rust

В операционных системах Linux, таких как MacOS или Ubuntu, мы можем легко установить Rust с помощью одной строки команды:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Кроме того, установитеnightlyВерсия:

rustup install nightly

Для установки под Windows см.:

https://forge.rust-lang.org/infra/other-installation-methods.html

2. Добавьте Rust в среду

Добавьте следующее утверждение в~/.bashrcили~/.zshrcсередина:

export PATH=~/.cargo/bin:$PATH

Потом:

source ~/.bashrc # source ~/.zshrc

3. Измените источник

Мы переключаем исходный код Rust на внутренний, установив следующие переменные среды:

export RUSTUP_DIST_SERVER=https://mirrors.ustc.edu.cn/rust-static
export RUSTUP_UPDATE_ROOT=https://mirrors.ustc.edu.cn/rust-static/rustup

существует~/.cargo/configЗапишите в файл следующее содержимое:

[source.crates-io]
registry = "https://github.com/rust-lang/crates.io-index"
replace-with = 'ustc'
[source.ustc]
registry = "git://mirrors.ustc.edu.cn/crates.io-index"

Конфигурация среды Ink!

После настройки базовой среды Rust мы можем настроить среду разработки, необходимую для Ink!.

# for substrate
rustup component add rust-src --toolchain nightly
rustup target add wasm32-unknown-unknown --toolchain stable
# for canvas node 
cargo install canvas-node --git https://github.com/paritytech/canvas-node.git --tag v0.1.4 --force --locked
# for ink!CLI
cargo install cargo-contract --vers 0.10.0 --force --locked

Мы также должны установить/обновитьbinaryen, Binaryen — это компилятор для WebAssembly.

Установить на Mac:

# for mac
brew upgrade binaryen # 如果没安装用 brew install

Установить в Linux:

Создать проект ink!

Выполните следующую команду:

cargo contract new flipper

После завершения создания заходим в папку:

cd flipper/

Структура каталога проекта контракта:

flipper
|
+-- lib.rs                <-- Contract Source Code
|
+-- Cargo.toml            <-- Rust Dependencies and ink! Configuration
|
+-- .gitignore

контрактный тест

cargo +nightly test

Если все пойдет хорошо, будет выведен следующий вывод:

$ cargo +nightly test
    running 2 tests
    test flipper::tests::it_works ... ok
    test flipper::tests::default_works ... ok

    test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

составление контракта

cargo +nightly contract build

image-20210323213148674

Если все пойдет хорошо, каталог сгенерируетtarget/inkпапку, в которой находятся следующие файлы:

image-20210323205600627

в,flipper.contractфайл контракта, который будет использоваться во время развертывания, который можно рассматривать какsolidityв контрактеbinдокумент.

metadata.jsonявляется метаданными и может рассматриваться какsolidityв контрактеabiдокумент.

Развертывание контракта

пройти черезcanvasЗапустите локальную работающую ноду разработки!

canvas --dev --tmp

An image of the terminal starting a Substrate node

Откройте следующий URL-адрес, и эта страница автоматически подключится к локально запущенному узлу разработки:

image-20210323210306845

загрузитьflipper.contractэтот файл:

Contracts code page for deploying Flipper

Щелкните полностью, чтобы развернуть:

image-20210323210730452

image-20210323210747989

image-20210323210811846

вызов по контракту

нажмитеExecute:

image-20210323210928445

выберитеget():boolфункцию, нажмите «Позвонить»:

image-20210323211004303

Вернуть результат вызова:

image-20210323211027286

Интерпретация исходного кода Flipper

// Copyright 2018-2020 Parity Technologies (UK) Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![cfg_attr(not(feature = "std"), no_std)]

use ink_lang as ink;

#[ink::contract]
pub mod flipper {
    #[ink(storage)]
    pub struct Flipper {
        value: bool,
    }

    impl Flipper {
        /// Creates a new flipper smart contract initialized with the given value.
        #[ink(constructor)]
        pub fn new(init_value: bool) -> Self {
            Self { value: init_value }
        }

        /// Creates a new flipper smart contract initialized to `false`.
        #[ink(constructor)]
        pub fn default() -> Self {
            Self::new(Default::default())
        }

        /// Flips the current value of the Flipper's bool.
        #[ink(message)]
        pub fn flip(&mut self) {
            self.value = !self.value;
        }

        /// Returns the current value of the Flipper's bool.
        #[ink(message)]
        pub fn get(&self) -> bool {
            self.value
        }
    }

    #[cfg(test)]
    mod tests {
        use super::*;

        #[test]
        fn default_works() {
            let flipper = Flipper::default();
            assert_eq!(flipper.get(), false);
        }

        #[test]
        fn it_works() {
            let mut flipper = Flipper::new(false);
            assert_eq!(flipper.get(), false);
            flipper.flip();
            assert_eq!(flipper.get(), true);
        }
    }
}

1. cfgиcfg_attrиспользование

cfg— это специальное свойство в Rust, которое позволяет нам компилировать код на основе флагов и передавать его компилятору.

В этом договоре мы видим:

#[cfg(test)]

Этот флаг означает, что приведенный ниже код является модульным тестом.

2. реализовать ключевое слово

Implement some functionality for a type.

Делайте реализации функций для типа.

Стандартный шаблон:

struct Example {
    number: i32,
    # 许多变量……
}

impl Example {
    fn boo() {
        println!("boo! Example::boo() was called!");
    }

    fn answer(&mut self) {
        self.number += 42;
    }
		# 许多函数……
}

Примените к этому контракту, сначала мы определяем контрактstruct:

pub struct Flipper {
	value: bool, # 其中包含一个变量 value
}

тогда правильноstructСделайте дополнительную реализацию:

impl Flipper {
	……
}

3. #[ink(constructor)]и#[ink(message)]

#[ink(constructor)]Указывает, что эта строка функции оператора является конструктором контракта, который эквивалентенsolidityв контрактеconstructor.

docs.solidity wolf.org/en/v0.7.2/ из…

#[ink(message)]Указывает, что функция под этой строкой утверждения является нормальной функцией контракта, например, в примереgetфункция:

/// Returns the current value of the Flipper's bool.
#[ink(message)]
pub fn get(&self) -> bool {
	self.value
}

Об авторе:

Ли Дагоу (Li Aohua), заместитель директора Центра исследований технологий и приложений блокчейна Шанхайского университета международного бизнеса и экономики, технический директор Bailian Education, FISCO BCOS (WeBank Blockchain Framework), сертифицированный лектор по блокчейну, 5-летний инженер по блокчейну, Пекинский университет Владелец. Области исследований включают: системы блокчейна, механизмы консенсуса, смарт-контракты, приложения блокчейна, цифровую идентификацию и т. д.

Содержание: мартовский номер Rust_Magazine