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模块。

主要功能

  1. Wasm模块优化
  2. 合约大小缩减
  3. Gas计量工具
  4. 导入/导出处理
  5. 无用代码消除

安装方法

在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("导入移除失败");

性能提示

  1. 对于生产环境,使用ShrinkLevel::Aggressive可以获得最小的Wasm体积
  2. 调试时可以关闭remove_debug_sections以保留调试信息
  3. 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(())
}

这个完整示例演示了:

  1. 从文件读取原始Wasm模块
  2. 进行优化处理(使用激进压缩级别)
  3. 修剪不需要的导出函数
  4. 重命名导入模块
  5. 注入Gas计量规则
  6. 最终输出处理后的Wasm文件

每个步骤都提供了错误处理,并保存中间结果以便调试。

回到顶部