Rust Wasm虚拟机库soroban-wasmi的使用,为智能合约执行提供高效Wasm运行环境

Rust Wasm虚拟机库soroban-wasmi的使用,为智能合约执行提供高效Wasm运行环境

Wasmi - WebAssembly (Wasm) 解释器

Wasmi Logo

Wasmi是一个高效且轻量级的WebAssembly解释器,专注于受限和嵌入式系统。

主要特性

Wasmi具有以下显著特性:

  • 简单、正确和确定性的WebAssembly执行
  • 适用于嵌入式环境的低开销、跨平台WebAssembly运行时
  • 抵抗JIT炸弹的翻译
  • 松散地镜像Wasmtime API
  • 100%通过WebAssembly规范测试套件
  • 内置燃料计量支持
  • 支持官方的Wasm C-API

WebAssembly提案支持

新的Wasmi引擎支持多种WebAssembly提案,未来还将支持更多。

WebAssembly提案 状态 注释
mutable-global 自版本0.14.0
saturating-float-to-int 自版本0.14.0
sign-extension 自版本0.14.0
multi-value 自版本0.14.0
bulk-memory 自版本0.24.0
reference-types 自版本0.24.0
simd 不太可能支持
tail-calls 自版本0.28.0
extended-const 自版本0.29.0
function-references 📅 计划中但尚未实现
gc 📅 计划中但尚未实现
multi-memory 📅 计划中但尚未实现
threads 📅 计划中但尚未实现
relaxed-simd 不太可能支持,因为simd不太可能支持
component-model 📅 计划中但尚未实现
exception-handling 📅 计划中但尚未实现
branch-hinting 📅 计划中但尚未实现
WASI 👨‍🔬 通过wasmi_wasi crate实验性支持WASI (wasip1)
C-API 👨‍🔬 通过wasmi_c_api_impl crate实验性支持官方Wasm C-API

开发

构建与测试

克隆Wasmi仓库并使用cargo构建:

git clone https://github.com/wasmi-labs/wasmi.git --recursive
cd wasmi
cargo build
cargo test

基准测试

使用以下命令对Wasmi进行基准测试:

cargo bench

支持的平台

Wasmi支持广泛的架构和平台。

  • Wasmi可以在no_std嵌入式环境中使用,因此不需要标准库(std)
  • 只有部分平台在CI中检查并由Wasmi维护者保证完全工作

示例代码

以下是一个使用soroban-wasmi执行Wasm智能合约的完整示例:

use soroban_wasmi::{
    Config, Engine, Externals, FuncRef, ImportsBuilder, Module, ModuleRef, Store, Value,
};

// 定义自定义的外部函数调用接口
struct MyExternals;

impl Externals for MyExternals {
    fn invoke_index(
        &mut self,
        _index: u32,
        _args: &[Value],
    ) -> Result<Option<Value>, soroban_wasmi::Trap> {
        // 在这里实现外部函数调用逻辑
        Ok(None)
    }
}

fn main() -> anyhow::Result<()> {
    // 1. 创建Wasm引擎配置
    let config = Config::default();
    
    // 2. 创建引擎和存储
    let engine = Engine::new(&config);
    let mut store = Store::new(&engine, ());
    
    // 3. 加载Wasm模块
    let wasm_bytes = include_bytes!("contract.wasm");
    let module = Module::new(&engine, &wasm_bytes[..])?;
    
    // 4. 设置导入函数(可选)
    let imports = ImportsBuilder::new(); // 可以添加需要的导入
    
    // 5. 实例化模块
    let mut externals = MyExternals;
    let instance = ModuleRef::new(&mut store, &module, &imports)?;
    
    // 6. 查找并调用合约函数
    let add_func = instance.get_func(&store, "add").expect("add function not found");
    let result = add_func.call(
        &mut store, 
        &mut externals, 
        &[Value::I32(1), Value::I32(2)],
    )?;
    
    println!("Result: {:?}", result);
    
    Ok(())
}

完整示例代码

以下是一个更完整的soroban-wasmi使用示例,包含合约加载、实例化和调用的完整流程:

use soroban_wasmi::{
    Config, Engine, Externals, ImportsBuilder, Module, ModuleRef, Store, Value
};
use std::fs;

// 自定义外部函数实现
struct ContractExternals {
    call_count: u32,
}

impl Externals for ContractExternals {
    fn invoke_index(
        &mut self,
        index: u32,
        args: &[Value],
    ) -> Result<Option<Value>, soroban_wasmi::Trap> {
        self.call_count += 1;
        println!("Called external function {} with args: {:?}", index, args);
        
        // 示例:当调用index为0的外部函数时返回42
        if index == 0 {
            return Ok(Some(Value::I32(42)));
        }
        
        Ok(None)
    }
}

fn main() -> anyhow::Result<()> {
    // 1. 配置Wasm引擎
    let config = Config::default()
        .with_stack_limit(1024 * 1024)  // 设置栈大小限制
        .with_fuel_metering(true);      // 启用燃料计量
    
    // 2. 创建引擎和存储
    let engine = Engine::new(&config);
    let mut store = Store::new(&engine, ());
    
    // 3. 加载Wasm合约
    let wasm_bytes = fs::read("smart_contract.wasm")?;
    let module = Module::new(&engine, &wasm_bytes[..])?;
    
    // 4. 设置导入函数
    let imports = ImportsBuilder::new()
        // 可以在这里添加需要的导入函数
        // .with("env", "log", FuncType::new(vec![ValueType::I32], vec![]))
        ;
    
    // 5. 实例化模块
    let mut externals = ContractExternals { call_count: 0 };
    let instance = ModuleRef::new(&mut store, &module, &imports)?;
    
    // 6. 调用合约函数
    // 6.1 调用add函数
    if let Ok(add_func) = instance.get_func(&store, "add") {
        let result = add_func.call(
            &mut store,
            &mut externals,
            &[Value::I32(2), Value::I32(3)],
        )?;
        println!("add(2, 3) = {:?}", result);
    }
    
    // 6.2 调用get_value函数
    if let Ok(get_value_func) = instance.get_func(&store, "get_value") {
        let result = get_value_func.call(
            &mut store,
            &mut externals,
            &[],
        )?;
        println!("get_value() = {:?}", result);
    }
    
    println!("Total external calls: {}", externals.call_count);
    
    Ok(())
}

安装

在项目目录中运行以下Cargo命令:

cargo add soroban-wasmi

或者在Cargo.toml中添加以下行:

soroban-wasmi = "0.36.1-soroban.22.0.0"

许可证

根据以下任一许可证授权:

  • Apache License, Version 2.0
  • MIT license

1 回复

Rust Wasm虚拟机库soroban-wasmi的使用指南

soroban-wasmi是一个为智能合约执行优化的Wasm虚拟机库,基于wasmi项目开发,专为Stellar区块链上的Soroban智能合约平台设计。

主要特性

  • 高性能Wasm执行环境
  • 专为智能合约场景优化
  • 完善的沙盒安全机制
  • 支持WASI接口
  • 轻量级设计

安装方法

在Cargo.toml中添加依赖:

[dependencies]
soroban-wasmi = "0.3.0"

基本使用方法

1. 初始化虚拟机

use soroban_wasmi::{Engine, Module, Instance, Linker};

// 创建Wasm引擎
let engine = Engine::default();

// 加载Wasm模块
let wasm_bytes = include_bytes!("contract.wasm");
let module = Module::new(&engine, &wasm_bytes[..]).expect("Failed to load module");

2. 执行智能合约

// 创建链接器并定义主机函数
let mut linker = Linker::new(&engine);
linker.func_wrap("env", "log", |caller: &mut soroban_wasmi::Caller<()>, ptr: u32, len: u32| {
    // 处理日志逻辑
    Ok(())
}).expect("Failed to define host function");

// 创建实例
let mut store = soroban_wasmi::Store::new(&engine, ());
let instance = linker.instantiate(&mut store, &module)
    .expect("Failed to instantiate module");

// 获取入口函数
let run = instance.get_typed_func::<(), i32>(&store, "run")
    .expect("Failed to get function");

// 执行合约
let result = run.call(&mut store, ()).expect("Execution failed");
println!("Contract execution result: {}", result);

高级功能

1. 内存访问

let memory = instance.get_memory(&store, "memory")
    .expect("Failed to get memory");

// 写入数据到Wasm内存
let data = b"Hello, Soroban!";
let offset = 0x1000;
memory.write(&mut store, offset, data)
    .expect("Failed to write memory");

// 从Wasm内存读取数据
let mut buffer = vec![0; data.len()];
memory.read(&store, offset, &mut buffer)
    .expect("Failed to read memory");

2. 燃料计量

use soroban_wasmi::Config;

// 配置燃料限制
let mut config = Config::default();
config.consume_fuel(true);
config.set_fuel(10_000_000).expect("Failed to set fuel");

let engine = Engine::new(&config);

3. 使用WASI

use soroban_wasmi::wasi::WasiCtxBuilder;

// 配置WASI环境
let wasi = WasiCtxBuilder::new()
    .inherit_stdio()
    .inherit_args().unwrap()
    .build();

let mut store = Store::new(&engine, wasi);

性能优化建议

  1. 对于高频调用的合约,缓存Module实例
  2. 合理设置燃料限制
  3. 限制内存使用量
  4. 使用预编译的Wasm模块

错误处理

match run.call(&mut store, ()) {
    Ok(result) => println!("Success: {}", result),
    Err(e) => match e {
        soroban_wasmi::Error::Trap(trap) => {
            println!("Trap occurred: {:?}", trap);
        }
        soroban_wasmi::Error::Link(_) => {
            println!("Linking error");
        }
        _ => println!("Other error: {:?}", e),
    },
}

完整示例代码

use soroban_wasmi::{
    Config, Engine, Module, Instance, Linker, 
    Store, wasi::WasiCtxBuilder, Error
};

fn main() -> Result<(), Error> {
    // 1. 配置引擎
    let mut config = Config::default();
    config.consume_fuel(true);
    config.set_fuel(1_000_000)?;
    
    // 2. 创建引擎
    let engine = Engine::new(&config);
    
    // 3. 加载Wasm模块
    let wasm_bytes = include_bytes!("contract.wasm");
    let module = Module::new(&engine, &wasm_bytes[..])?;
    
    // 4. 配置WASI环境
    let wasi = WasiCtxBuilder::new()
        .inherit_stdio()
        .inherit_args()?
        .build();
    
    // 5. 创建存储
    let mut store = Store::new(&engine, wasi);
    
    // 6. 创建链接器并定义主机函数
    let mut linker = Linker::new(&engine);
    linker.func_wrap("env", "log", |caller: &mut soroban_wasmi::Caller<()>, ptr: u32, len: u32| {
        // 从内存中读取日志内容
        let memory = caller.get_memory("memory").unwrap();
        let mut buffer = vec![0; len as usize];
        memory.read(caller, ptr as usize, &mut buffer)?;
        let message = String::from_utf8_lossy(&buffer);
        println!("[合约日志] {}", message);
        Ok(())
    })?;
    
    // 7. 实例化模块
    let instance = linker.instantiate(&mut store, &module)?;
    
    // 8. 获取内存
    let memory = instance.get_memory(&store, "memory")?;
    
    // 9. 写入输入数据到内存
    let input = b"测试输入数据";
    let input_offset = 0x1000;
    memory.write(&mut store, input_offset, input)?;
    
    // 10. 获取并调用合约函数
    let process = instance.get_typed_func::<(u32, u32), i32>(&store, "process")?;
    let result = process.call(&mut store, (input_offset as u32, input.len() as u32))?;
    
    println!("合约处理结果: {}", result);
    
    Ok(())
}

soroban-wasmi为智能合约执行提供了安全高效的Wasm运行环境,特别适合区块链场景下的合约执行需求。

回到顶部