Polka链的宠物项目2合约代码--by Skyh0714

1. 添加模块

分析项目结构

u

听说runtime才是模块内容
substrate-package/substratekitties/runtime/src 中加入substratekitties.rs
image.png

直接在这个文件写入程序框架

use support::{decl_storage, decl_module};

pub trait Trait: system::Trait {}

decl_storage! {
    trait Store for Module as KittyStorage {
        // Declare storage and getter functions here
    }
}

decl_module! {
    pub struct Module for enum Call where origin: T::Origin {
        // Declare public functions here
    }
}

另外要在lib.rs三处加入模块, 我看到有类似template模块就在下面加了

// #1
/// Used for the module template in `./template.rs`
mod template;
// Add this line
mod substratekitties;

// #2
/// Used for the module template in `./template.rs`
impl template::Trait for Runtime {
    type Event = Event;
}
// Add this line
impl substratekitties::Trait for Runtime {

}

// #3
construct_runtime!(
    pub enum Runtime with Log(InternalLog: DigestItem) where
        Block = Block,
        NodeBlock = opaque::Block,
        UncheckedExtrinsic = UncheckedExtrinsic
{
                // Used for the module template in `./template.rs`
        TemplateModule: template::{Module, Call, Storage, Event},
        Substratekitties: substratekitties::{Module, Call, Storage}, //Add

});

这样就可以运行了:

./scripts/build.sh
cargo build --release

编译只把新增加的编译出来


image.png

我打算再写多些功能些

2. 学习Rust (可跳过,直接看代码)

Substrate 本身支持 Rust 中可用的所有原始类型(boolu8u32 等)以及一些 Substrate 中的特定自定义类型 (AccountId, Balance, Hash, and more...)
要存储这些基本存储值,你需要导入 support::StorageValue

// 导入
use support::{decl_storage, decl_module, StorageValue, dispatch::Result};
use system::ensure_signed;

// 声明
decl_storage! {
    trait Store for Module as Example {
        MyU32: u32;
        MyBool get(my_bool_getter): bool;
    }
}
// put
>::put(1337);
// get
let my_bool = >::get();
let also_my_bool = Self::my_bool_getter();

函数的第一个参数始终是 origin。 origin 包含有关调用来源的信息。通常分为三组:由外部帐户签名的 public 调用。允许仅由治理系统进行的 root 调用。允许仅由块作者和验证者进行的 inherent 调用。
函数必须返回 support::dispatch 模块中的 Result 类型。这意味着成功的函数调用将始终返回 Ok(()),否则应捕获可能导致问题的任何错误并返回 Err()

system module 中有三个方便的调用函数 ensure_signed, ensure_root 和 ensure_inherent,可以调用三者中匹配的函数并返回一个结果
我们可以使用 system 中的 ensure_signed() 函数来检查 origin,并 "ensure" 消息是由有效帐户签名的。

decl_module! {
    pub struct Module for enum Call where origin: T::Origin {

        fn my_function(origin, input_bool: bool) -> Result {
            let _sender = ensure_signed(origin)?;

            >::put(input_bool);

            Ok(())
        }
    }
}

默认的 runtime 模板包含一组 modules,这些 modules 暴露出了你开发区块链需要涉及的类型。在你开发了更多 module 后,你甚至会自己构造新类型并暴露给 runtime 的其他部分。
我们将使用 3 种 substrate 特定类型:AccountId, Balance, Hash
我们的 module 本身不能访问这些类型,但我们可以通过让 module 的 Trait 继承定义了这些类型的 module 来轻松获取访问权限。在当前情况下,balances module 有我们需要的一切东西:

// 定义
decl_storage! {
    trait Store for Module as Example {
        SomeValue get(some_value_getter): map u32 => u32;
        MyValue: map T::AccountId => u32;
    }
}
// 插入
>::insert(key, value);
// 查询
let my_value = >::get(key);
let also_my_value = Self::some_value_getter(key);

3. 运行程序1

use support::{decl_storage, decl_module, StorageMap, dispatch::Result};
use system::ensure_signed;

pub trait Trait: balances::Trait {}

decl_storage! {
    trait Store for Module as KittyStorage {
        Value: map T::AccountId => u64;
    }
}

decl_module! {
    pub struct Module for enum Call where origin: T::Origin {

        fn set_value(origin, value: u64) -> Result {
            let sender = ensure_signed(origin)?;

            >::insert(sender, value);

            Ok(())
        }
    }
}

运行程序

./scripts/build.sh
cargo build --release
./target/release/substratekitties purge-chain --dev
#再启动
./target/release/substratekitties --dev

https://polkadot.js.org/apps/#/extrinsics
extrinsics这里能看到自己方法

image.png

chain_state这里可以看到输出变量
image.png

4. 高级Rust

定义struct, 并在struct中使用泛型,
自定义的 Encode 和 Decode traits,你需要从 parity_codec_derive crate 中导入它们
#[derive(...)]。这是 Rust 编译器提供的属性,允许基本地实现某些 trait。第二行,
#[cfg_attr(feature = "std", derive(Debug))] 对 Debug trait 做了同样的事情,但仅在使用“标准”库时启用,即在编译本机二进制文件而不是 Wasm 的时候。

use runtime_primitives::traits::{As, Hash};
use parity_codec::{Encode, Decode};
// 定义
#[derive(Encode, Decode, Default, Clone, PartialEq)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct MyStruct {
    some_number: u32,
    some_generic: A,
    some_other_generic: B,
}
// 存储
decl_storage! {
    trait Store for Module as Example {
        MyItem: map T::AccountId => MyStruct;
    }
}
// 插入
decl_module! {
    pub struct Module for enum Call where origin: T::Origin {
        fn create_struct(origin, value: u32, balance: T::Balance, hash: T::Hash) -> Result {
            let sender = ensure_signed(origin)?;

            let new_struct = MyStruct {
                some_number: value,
                some_generic: balance,
                some_other_generic: hash,
            };

            >::insert(sender, new_struct);
            Ok(())
        }
    }
}
// 初始化 T::Hash 和 T::Balance
let hash_of_zero = ::Hashing::hash_of(&0);
let my_zero_balance = >::sa(0);

Substrate 不直接支持字符串。Runtime 存储用于存储 runtime 运行的业务逻辑的状态。它不是存储 UI 所需的一般数据。如果你确实需要将一些任意数据存储到 runtime,你总是可以创建一个 bytearray(Vec),但更合乎逻辑的做法是将哈希值存储到 IPFS 之类的服务中,然后获取数据用于 UI 展示。这超出了本次研讨会的范围,但可能会在以后为你的 kitty 添加其他元数据

5 运行程序2

use support::{decl_storage, decl_module, StorageMap, dispatch::Result};
use system::ensure_signed;
use runtime_primitives::traits::{As, Hash};
use parity_codec::{Encode, Decode};

#[derive(Encode, Decode, Default, Clone, PartialEq)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct Kitty {
    id: Hash,
    dna: Hash,
    price: Balance,
    gen: u64,
}

pub trait Trait: balances::Trait {}

decl_storage! {
    trait Store for Module as KittyStorage {
        OwnedKitty get(kitty_of_owner): map T::AccountId => Kitty;
    }
}

decl_module! {
    pub struct Module for enum Call where origin: T::Origin {

        fn create_kitty(origin) -> Result {
            let sender = ensure_signed(origin)?;

            let new_kitty = Kitty {
                id: ::Hashing::hash_of(&0),
                dna: ::Hashing::hash_of(&0),
                price: >::sa(0),
                gen: 0,
            };

            >::insert(&sender, new_kitty);

            Ok(())
        }
    }
}

重新运行

./scripts/build.sh
cargo build --release
./target/release/substratekitties purge-chain --dev
./target/release/substratekitties --dev

首先注册结构,在Setting>developer页面输入保存

{
    "Kitty": {
        "id": "H256",
        "dna": "H256",
        "price": "Balance",
        "gen": "u64"
    }
}
image.png

在extrinsics创建


image.png

chainstate
就能看到你生成的kittyies


image.png

今天学习了rust基本语法和substrate基本操作, 基本是创建变量, map, 定义和生成struct, 下次再通过区块链共同学习rust更多

你可能感兴趣的:(Polka链的宠物项目2合约代码--by Skyh0714)