New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ink! 极简入门 #31
Comments
ink!中的函数可以分为两类:
要点
ink!函数 VS. Solidity函数Solidity函数声明: function <function name>(<parameter types>) {internal|external|public|private} [pure|view|payable] [returns (<return types>)] 作为与Solidity中的函数做对比,我列出了如下几点不同:
|
ink!/Rust 与 Solidity 的语言不同因为ink!站在Rust的肩膀上,所以相对Solidity而言,有一些特性无需特别声明即可拥有,同时Solidity具有的一些特性,实际上ink!也无需特别支持。我举几个例子:
ink!因为站在Rust的肩膀上,在智能合约中可以更漓漓尽致的发挥现代语言的编程能力;我个人意见,ink!智能合约的编写会更强大的多。 |
ink! 中的事件(Event)在Solidity中事件扮演了重要的作用, Dapp透过RPC接口监听特定的事件,获取交易执行后的结果;
|
ink! 中的接口,继承(?)前面说过ink!是站在rust的肩膀上,而solidity中的接口在ink!中对应的是Trait 但我觉得装饰器的设计是可以有的,请参见上面的OpenBrush. 在Rust的设计概念中,使用Trait,With Composable over Inheritance
ink!中的Trait,跟Solidity的interface很像。 Solidity中,合约编译后除生成合约字节码之外,还会生成合约ABI,即接口信息;从中我们可以看到该合约提供哪一些服务调用,传入参数和返回参数类型等。 提示: |
ink! 中的错误和错误处理ink!错误定义,采用与Rust一样的定义,使用在Result<T, E>中。 当函数在处理过程中发生了错误,代码可以做如下选择:
如下是范例中定义的错误和检测错误并返回的例子:
合约代码中仍可方便的使用Rust的 合约做条件检查,除了范例代码中用到的手动if检查,还可以使用assert!(), assert_eq!(),...等语句。 参考: |
ink! 合约如何使用第三方库Cargo.toml中添加第三方库的dependencies,在代码中使用use 关键字引入该第三方库即可。 ink! 合约如何调用链上已有合约的函数 - 跨合约调用简单来说,需要把该链上已有合约实例化,之后就可以调用实例(对象)的方法。我们举一个例子来讲述操作细节:
让我们来详细讲述操作步骤:
这里的模式是,生成dapp2的ContractRef,然后把它放在Dapp1的实例中;调用dapp2的方法时,用self.dapp2_instance即可。 小插曲我们现在为Dapp1的合约成员添加一个Mapping,再次编译,结果报错:
因为Mapping要求Dapp1合约实现 想解决这个问题,有如下两种解法:
当需要使用dapp2的方法,使用
合约Code Hash获取链上合约的code hash
Note:
|
Storage LayoutSolidity 和 Ink! 在这部分有一定差异,也有很多相同之处(某种程度来说,应该是说EVM和WebAssembly(Frame?)在这部分的支持) ink!中的每一个合约,一般都选择用一个struct来定义,该struct中的每一个变量,其location都在Storage上(还需要在前面加上#[ink(storage)]宏声明) 在Storage的设计上,目前有V3.x和v4.x,差别好像比较大。 storage model在Solidity中,Storage的存储单元叫 'slot'; 存储单元的大小都是32字节,存储单元的索引index也是一个32比特长度的整形 可以把storage区域看成是一个Key/Value的数据库,而数据结构读取和写入都要靠key的索引 storage的一个cell能放下32个字节的数据,合约中的数据要怎么安排放到cell中,这就是layout。
默认Layout是Spread方式 我们之前说过,目前合约设计中,支持的数据结构有基本类型(primitives,定长数组)和 Mapping 不过在ink! 编程方面,并没有把storage cell index这样的底层细节曝露给上层,而是采用:
下面的例子主要是展示layout实现和trait的关系:
从编程角度,只要上层的编程模型设计正确,对上层编程,隐藏底层细节其实是比较好的设计。在这里存取PackedStruct中的任一数据,都可以用rust的结构体语法,不用去考虑storage cell等繁琐的细节。 当然,如果是spread layout,我们可以使用Key运算的方式,手动让key指向我们想要定位的地方,见如下代码:
Note:
scale_info::TypeInfo 是需要的,只要加了SpreadLayout或者PackedLayout |
ink! doc FAQink! 与 Substrate/Polkadot的关系?Substrate是一个开发框架,可以让开发者基于Substrate框架开发出Dapp; 也有其他的合约开发方法:
合约如何与运行时/runtime交互?参见 Chain Extension一节 How can I use ink! with a Substrate chain with a custom chain config?Please see the env_types argument for the contract macro. It allows you to specify your environment a la #[ink::contract(env = MyEnvironment)]. 合约开始的#![cfg_attr(not(feature = "std"), "no_std")] 是干什么的?告知rust compiler,合约是在如下哪一种模式被编译:
为什么链上Wasm不支持合约使用std库?我们说的std库实际上包含3个部分:
Wasm(即 wasm32-unknown-unknown)编译target不支持std库 为什么合约编译时使用nightly版本?因为合约编译在处理内存分配部分(no_std alloc),依赖几个unstable nightly特性,在Rust 2021版本上。 Security Issuesoverflow:利用Rust本身的语法来保证 Storage Vs. Memory有被#[ink(storage)]修饰的结构体或变量,其存放位置就是storage上,对应于链上数据,生命周期为'static。 打印信息到consoleink_env::debug_println! or debug_print!
如何在合约中使用hash函数?在contracts-pallet中提供crypto hash,可参见https://docs.rs/ink_env/3.3.1/ink_env/hash/trait.CryptoHash.html
如果你想要的hash功能不在其中,则可利用Chain Extension, 打算在ink!中支持浮点数吗?浮点数在区块链领域最大的问题是在于其不确定性(non-deterministic)。 在合约storage中,可以使用rust中的Vec数据结构吗,可以使用string吗?可以,使用ink_prelude::vec::Vec;ink::prelude::string::String。
遇到ContractTrapped错误,是因为什么原因?合约中的代码,有遇到Panic的情况,比如assert!, assert_eq,xxx.unwrap()之类的,也可能是算术运算溢出,当然也有 scale::Encode和scale::Decode trait是干什么的?数据存储在Storage,从Storage取出数据;或者是Dapp调用合约中的函数,传入参数和返回参数,都是要经过scale编码的。 |
ink!的数据类型
ink!语言支持的类型,与Rust语言类型和智能合约的运行环境WebAssembly runtime都相关;
基本上可以分为两大类:
在内存中做计算的数据类型
沿用了很多Rust内置的类型,如:
保存在链上的数据类型
相比内存中做计算的数据类型,存在链上的数据类型多了一个限制:支持SCALE编解码(scale encode/decode trait),如:
此外,ink还通过ink_storage,ink_env等crate,提供了
特别声明
#[ink(storage)]
的标记,同时如果数据类型是非基本类型,如Struct,Enum,还需要加上#[derive(scale::Encode, scale::Decode)]
来让系统自动实现SCALE codecSCALE编码介绍: https://docs.substrate.io/reference/scale-codec/
SCALE实现代码: https://github.com/paritytech/parity-scale-codec
The text was updated successfully, but these errors were encountered: