智能合约语言(eDSL)—— wasmtime实现合约引擎补充

1、链上下文

由于我们是应用到区块链中,所以我们需要把链的环境传递给wasmtime,这样wasmtime在运行合约的时候,就可以获取到链上数据;我们运行合约当时的环境,打包成一个变量context,传递给wasmtime。context的结果如下:

rust 复制代码
pub struct Context {

    pub(crate) func_name: String, //调用函数名称

    pub(crate) state: String,//合约状态

    pub(crate) param: String,//调用函数的参数

    pub(crate) invoker: Address, //调用者地址

    pub(crate) owner: Address,//合约拥有者地址

    pub(crate) self_address: Address,//合约地址

    pub(crate) event: Vec<String>,//合约产生的事件

    pub(crate) self_balance: u64,//合约余额

    pub(crate) output_data: String,//合约返回数据

    pub(crate) metadata: Metadata,//链数据,例如高度、时间等

    pub(crate) gas: bool, //是否启动gas

    pub(crate) gas_counter: u64,//gas计数

    pub(crate) gas_limit: u64,//gas限制

    pub(crate) gas_outof: bool,//gas是否超了

}

我们可以看到,都是当前交易和链的情况,例如调用函数,调用者地址,链高度,时间等这些都是当前链的情况,还有一部分数据其实正好相反,是合约产生的,要反馈给链或者用户,例如合约产生的事件,调用函数产生的返回值。

那我们是在什么时候,传递给wasmtime呢?

rust 复制代码
 let mut store = Store::new(&engine, context);

就是在创建store,我们将我们context存入store中,存入的这些数据,我们后续还会继续用到

2、死循环

如果有人编写了一个死循环的合约,然后不小心调用了,怎么办?

我们在创建wasmtime的时候,可以创建一个监控线程,如果wasmtime执行时间超过了我们设定的时间,就会停止wasmitme,然后返回错误。

rust 复制代码
let engine = Engine::new(Config::new().epoch_interruption(true))?;

std::thread::spawn(move || {

        std::thread::sleep(std::time::Duration::from_secs(1));

        engine_clone.increment_epoch();

    });

这里,我们将每次运行的时间设置为1s,超过这个时间,就会报错。

3、合约的存储格式

如果合约编译完之后,直接存储使用,效率还是差一点;我们可以提前(AOT)编译WebAssembly模块。

rust 复制代码
​
pub fn precompile_module(&self, bytes: &[u8]) -> Result<Vec<u8>>

​

存储之前,使用此方法会输出是一个编译过的模块。当我们再次使用的时候,需要调用如下函数解码,

rust 复制代码
​
pub unsafe fn deserialize( engine: &Engine, bytes: impl AsRef<[u8]> ) -> Result<Module>

​

运行现在字节码,性能会极大的提高。

4、添加linker

给wasmtime提供一系列的链环境接口,与之前合约部分,链接口是一一对应的,同样的模块鱼函数;例如获取,合约的拥有者,

rust 复制代码
    linker.func_wrap(

        "xq",

        "get_owner",

        |mut caller: Caller<'_, Context>, ptr: i32| {

            charge_gas(&mut caller, GAS_ENV_FUNC_BASE);

            //let owner:&[u8] = caller.data_mut().owner.deref();

            let addr = caller.data_mut().owner; //

            let owner = &addr.0;

            let mem = match caller.get_export("memory") {

                Some(Extern::Memory(mem)) => mem,

                _ => anyhow::bail!("get_owner:failed to find memory"),

            };

            match mem.write(caller, ptr as usize, owner) {

                Ok(_) => (),

                Err(_) => anyhow::bail!("get_owner:MemoryAccessError"),

            };

            Ok(())

        },

    )?;

我们可以看到闭包中参数,有一个Caller<'_, Context> context就是我们定义链上下文,这样用户在调用合约中的获取合约地址的接口,就会调用到wasmtime中linker中定义的get_owner,而get_owner中,又会从context中获取到context中的合约地址,返回将他作为返回值返回给用户,其实是写入内存中的,这样合约在运行的过程中,就可以获取到合约地址了。

其他接口也是类的,需要我们自己去完成。

https://github.com/XuHugo/xwasm/blob/main/wasm/src/vm.rs

相关推荐
好家伙VCC1 小时前
**发散创新:基于Rust的轻量级权限管理库设计与开源许可证实践**在现代分布式系统中,**权限控制(RBAC
java·开发语言·python·rust·开源
@atweiwei1 小时前
用 Rust 构建agent的 LLM 应用的高性能框架
开发语言·后端·rust·langchain·eclipse·llm·agent
skilllite作者1 小时前
Spec + Task 作为「开发协议层」:Rust 大模型辅助的标准化、harness 化与可回滚
开发语言·人工智能·后端·安全·架构·rust·rust沙箱
搬砖魁首2 小时前
Fabric系列 - HSM之3 区块链上的结合
区块链·php·fabric·长安链·hsm
zsqw1235 小时前
以 Rust 为例,聊聊线性类型,以及整个类型系统
rust·编译器
TechMasterPlus5 小时前
FilAPP 技术深度解析:基于 Filecoin 的去中心化文件存储应用架构
架构·去中心化·区块链
Rust研习社5 小时前
Rust Tracing 实战指南:从基础用法到生产级落地
rust
分布式存储与RustFS6 小时前
MinIO迎来“恶龙”?RustFS这款开源存储简直“不讲武德”
架构·rust·开源·对象存储·minio·企业存储·rustfs
数据知道19 小时前
claw-code 源码分析:从 TypeScript 心智到 Python/Rust——跨栈移植时类型、边界与错误模型怎么对齐?
python·ai·rust·typescript·claude code·claw code