Rust Wasm工具库pwasm-utils的使用,pwasm-utils为WebAssembly编译和优化提供高效工具链支持
pwasm-utils
⚠️ 该仓库/crate已废弃且不再维护:pwasm-utils 是一个用于 pwasm-ethereum 和 substrate 合约开发的 WASM 工具集合,但目前已不再维护。
CLI工具安装
cargo install pwasm-utils --features cli
安装后将包含以下二进制工具:
- wasm-build
- wasm-check
- wasm-ext
- wasm-gas
- wasm-pack
- wasm-prune
- wasm-stack-height
符号修剪 (wasm-prune)
wasm-prune <input_wasm_binary.wasm> <output_wasm_binary.wasm>
此命令会优化 WASM 符号树,仅保留合约 call
函数入口使用的元素。
气体计数器 (wasm-gas)
用于开发目的,可以在原始 WASM 合约中注入气体计数器:
wasm-gas <input_wasm_binary.wasm> <output_wasm_binary.wasm>
完整示例
以下是使用 pwasm-utils 处理 WASM 文件的完整示例:
// 1. 首先编译合约为Wasm格式
cargo build --target wasm32-unknown-unknown --release
// 2. 使用wasm-prune优化Wasm文件
wasm-prune target/wasm32-unknown-unknown/release/contract.wasm optimized.wasm
// 3. (可选)注入gas计数器
wasm-gas optimized.wasm final.wasm
// 4. 检查优化后的Wasm文件
wasm-check final.wasm
许可证
pwasm-utils 采用双重许可:MIT 许可证和 Apache 许可证(2.0版),用户可以自行选择。
贡献
所有提交到 pwasm-utils 的贡献默认都采用上述双重许可,除非贡献者明确声明其他许可方式。
完整示例代码
以下是一个更完整的示例,展示如何使用 pwasm-utils 工具链处理合约:
// 假设我们有一个简单的智能合约项目结构
// Cargo.toml 文件内容:
/*
[package]
name = "my-contract"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
pwasm-std = "0.15"
*/
// src/lib.rs 合约示例代码:
#![no_std]
use pwasm_std::call;
#[no_mangle]
pub extern "C" fn call() {
// 合约逻辑代码
}
// 构建和处理流程:
// 1. 构建合约
// cargo build --target wasm32-unknown-unknown --release
// 2. 优化合约大小
// wasm-prune target/wasm32-unknown-unknown/release/my-contract.wasm pruned.wasm
// 3. 注入gas计数器
// wasm-gas pruned.wasm final.wasm
// 4. 验证结果
// wasm-check final.wasm
注意:由于该项目已废弃,建议考虑迁移到 wasm-instrument 和 binaryen 工具链。
1 回复
Rust Wasm工具库pwasm-utils的使用指南
概述
pwasm-utils是一个专为WebAssembly(Wasm)编译和优化设计的Rust工具库,它提供了一系列高效的工具链支持,帮助开发者更好地处理Wasm模块。
主要功能
- Wasm模块优化
- 合约大小缩减
- Gas计量工具
- 导入/导出处理
- 无用代码消除
安装方法
在Cargo.toml中添加依赖:
[dependencies]
pwasm-utils = "0.16"
使用示例
1. 优化Wasm模块
use pwasm_utils::{optimize, OptimizationOptions};
let wasm_bytes: Vec<u8> = /* 你的原始Wasm字节码 */;
// 优化Wasm模块
let optimized = optimize(
&wasm_bytes,
OptimizationOptions {
shrink_level: pwasm_utils::ShrinkLevel::Aggressive,
..Default::default()
}
).expect("优化失败");
// 保存优化后的Wasm
std::fs::write("optimized.wasm", optimized).expect("写入文件失败");
2. 移除无用导出
use pwasm_utils::exports;
let wasm_bytes: Vec<u8> = /* 你的Wasm字节码 */;
// 只保留特定的导出函数
let pruned = exports::prune(
&wasm_bytes,
&["memory", "main"]
).expect("导出修剪失败");
// 保存处理后的Wasm
std::fs::write("pruned.wasm", pruned).expect("写入文件失败");
3. 注入Gas计量
use pwasm_utils::gas_metering;
let wasm_bytes: Vec<u8> = /* 你的Wasm字节码 */;
// 为Wasm模块注入Gas计量
let metered = gas_metering::inject(
&wasm_bytes,
&gas_metering::ConstantCostRules::default(),
"env"
).expect("Gas计量注入失败");
// 保存处理后的Wasm
std::fs::write("metered.wasm", metered).expect("写入文件失败");
高级用法
自定义优化选项
use pwasm_utils::{optimize, OptimizationOptions, ShrinkLevel};
let options = OptimizationOptions {
shrink_level: ShrinkLevel::Default,
optimize_for_size: true,
remove_debug_sections: true,
..Default::default()
};
let optimized = optimize(&wasm_bytes, options).expect("优化失败");
处理导入项
use pwasm_utils::imports;
// 重命名导入模块
let renamed = imports::rename(
&wasm_bytes,
"old_module",
"new_module"
).expect("导入重命名失败");
// 或者完全移除特定导入
let removed = imports::remove(
&wasm_bytes,
&["env::print"]
).expect("导入移除失败");
性能提示
- 对于生产环境,使用
ShrinkLevel::Aggressive
可以获得最小的Wasm体积 - 调试时可以关闭
remove_debug_sections
以保留调试信息 - Gas计量对于区块链智能合约开发特别有用
注意事项
- 优化过程可能会改变函数和变量的名称
- 某些极端优化可能会影响运行时的性能表现
- 建议在优化前后进行充分的测试
pwasm-utils是Rust Wasm工具链中的重要组成部分,特别适合需要精细控制Wasm输出的开发者使用。
完整示例demo
下面是一个完整的示例,展示了如何使用pwasm-utils处理Wasm模块:
use std::fs;
use pwasm_utils::{
optimize,
exports,
gas_metering,
imports,
OptimizationOptions,
ShrinkLevel
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. 读取原始Wasm文件
let wasm_bytes = fs::read("input.wasm")?;
// 2. 优化Wasm模块
let optimized = optimize(
&wasm_bytes,
OptimizationOptions {
shrink_level: ShrinkLevel::Aggressive,
optimize_for_size: true,
remove_debug_sections: true,
..Default::default()
}
)?;
fs::write("optimized.wasm", &optimized)?;
// 3. 处理导出项
let pruned = exports::prune(
&optimized,
&["memory", "main", "alloc", "dealloc"]
)?;
fs::write("pruned.wasm", &pruned)?;
// 4. 处理导入项
let renamed = imports::rename(
&pruned,
"env",
"imports"
)?;
// 5. 注入Gas计量
let metered = gas_metering::inject(
&renamed,
&gas_metering::ConstantCostRules::default(),
"imports"
)?;
fs::write("final.wasm", &metered)?;
println!("Wasm处理完成!");
Ok(())
}
这个完整示例演示了:
- 从文件读取原始Wasm模块
- 进行优化处理(使用激进压缩级别)
- 修剪不需要的导出函数
- 重命名导入模块
- 注入Gas计量规则
- 最终输出处理后的Wasm文件
每个步骤都提供了错误处理,并保存中间结果以便调试。