Skip to content

Latest commit

 

History

History
191 lines (170 loc) · 5.4 KB

pythontorust.md

File metadata and controls

191 lines (170 loc) · 5.4 KB

Python合约和rust合约对比

新建合约

新建Python版本合约,建议开发者使用smartx在线开发工具进行开发测试。

rust版本合约可以使用cargo命令新建合约。

//创建rust合约示例
cargo new --lib helloworld

合约入口函数

python 合约的入口函数是main函数, main函数中,会根据传进来的方法名的不同,跳转到响应的方法处执行。

rust 合约的入口函数是invoke函数,invoke函数会根据传进来参数的不同跳转到响应的函数处执行。

示例

python 版本合约main函数示例

def main(operation, args):
    if operation = "init":
        return init()
    else:
        return False

rust版本合约示例

#[no_mangle]
pub fn invoke() {
    //Oep8TokenDispatcher是使用abi_codegen::contract自动生成的类,实现了对合约请求的自动派发和结果的序列化操作
    let mut dispatcher = Oep8TokenDispatcher::new(Oep8TokenInstance);//通过代码生成器,生成Oep8TokenDispatcher对象实例
    runtime::ret(&dispatcher.dispatch(&runtime::input()));//
}

包引用

Python版本合约需要引用boa包目录下的库函数 示例

from boa.interop.System.Storage import Get, GetContext, Put

rust版本合约需要引用ontio-std库下面的库函数 示例

extern crate ontio_std as ostd;
use ostd::{database, runtime};

常量定义

python 合约中常量定义

INITIALIZED = "init"

rust合约中常量定义

const INITED: &str = "Initialized";

数据存储

python 合约需要引入PutGet保存和读取数据。 示例

Put(GetContext(), KEY, value)//GetContext用于获取合约上下文信息, 数据已K-V键值对的形式保存Get(GetContext(), KEY)//根据KEY获得value

rust合约需要引入database模块中的putget方法,此外,rust合约支持ListStoreHashmapStore数据类型, ListStoreHashMapStore是对PutGet的进一步封装,均支持遍历所有数据,方法执行结束自动保存功能。

rust合约中putget方法示例

database::put(INITED, true);
let val :bool = database::get(INITED).unwrap_or_default();

ListStore使用示例

//引用database
use database::ListStore;
fn init(){
    let mut list: ListStore<String> = ListStore::open("key".to_string());//新建List实例或者打开已经存在的数据,
    list.push("value".to_string());
}

HashMapStore使用示例

use database::HashMapStore;
let mut m = HashMapStore::open("test".to_string());
m.put("hello", "world");

合约编译成字节码

python合约通过smartx编译成字节码

rust合约编译成字节码使用下面的命令

cargo build --release --target wasm32-unknown-unknown

注意:在使用上面命令之前,请先通过下面的命令安装wasm32-unknown-unknown插件,

rustup target add wasm32-unknown-unknown

合约测试

smartx工具支持python合约单步调试等功能

rust合约测试比较方便,在合约文件中添加下面代码

#[cfg(test)]
mod test;

然后就可以编写单独的测试文件,详情请查看examples目录下的合约例子

rust合约常用函数示例

  1. base58编码的地址转换成Address对象实例
const _ADDR_EMPTY: Address = ostd::base58!("AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM");
  1. 校验签名
use ostd::{database, runtime};
runtime::check_witness(&owner);
  1. 合约中可以直接用assert_eq!assert!等判断条件是true还是false。
  2. rust合约中ListStore的使用介绍
  • 新建或者打开已经存在的一个ListStore
let mut list: ListStore<String> = ListStore::open("key".to_string());

Note:创建ListStore的时候,传进来的"key"用来存储ListStore中的数据,所以开发者在使用put方法保存数据或者使用delete方法删除数据时, 一定不要和ListStore使用同一个"key"。

  • 添加元素
list.push("value".to_string());

ListStore中添加的元素,会先保存到缓存中,需要调用flush方法才会保存到数据库中,当执行list的合约方法结束的时候合约会自动调用flush方法将list中的数据保存到数据库。

  • 删除元素 按照索引删除元素,所以需要用户知道要删除的元素的索引
list.remove(1);

Note: 对ListStore中的数据进行增加或者删除的时候,并不会立即落账,需要调用flush方法使最新的变化落账,在合约方法执行结束的时候ListStore会自动调用flush方法。

  • 查询元素 根据索引查询元素
let x = list.get(1);
  • 遍历list
while let Some(data) = iter.next() {
   println!("{}", data);
}
  1. HashMapStore使用介绍
  • 新建一个HashMapStore
let mut m:HashMapStore<String, String> = HashMapStore::open("test".to_string());
  • 添加元素
m.put("hello1", "world1");
  • 查询元素 根据key获得value
m.get(&"hello1".to_string()).unwrap();
  • 访问已经存在数据库中的hashmap格式的数据
let mut m2: HashMap<String, String> = HashMap::open("test".to_string());
  • 删除元素 根据key删除元素
m.remove("hello1");
  • 遍历HashMapStore
let mut iter = m.iter();
let mut ind = 0;
while let Some((k, v)) = iter.next() {
    assert_eq!(k, &format!("hello{}", ind));
    assert_eq!(v, format!("world{}", ind));
    ind += 1;
}