Rust区块链智能合约开发库CosmWasm-core的使用,CosmWasm-core为Rust生态提供模块化WASM虚拟机与Cosmos SDK集成方案

cosmwasm-core

cosmwasm-core on crates.io

这个crate包含了可以在no_std环境中使用的cosmwasm-std组件。所有的符号都被cosmwasm-std重新导出,因此合约开发者不需要直接添加这个依赖。建议尽可能只使用cosmwasm-std。

许可证

这个包是cosmwasm仓库的一部分,遵循Apache License 2.0许可证。

安装

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

cargo add cosmwasm-core

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

cosmwasm-core = "3.0.1"

完整示例代码

以下是一个使用cosmwasm-core开发智能合约的完整示例:

// 导入必要的模块
use cosmwasm_std::{Response, StdResult, DepsMut, Env, MessageInfo};
use cosmwasm_core::exports::Extern;

// 定义合约消息
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum ExecuteMsg {
    // 在这里定义你的合约消息
    Example { value: String },
}

// 执行函数
pub fn execute(
    deps: DepsMut,
    _env: Env,
    _info: MessageInfo,
    msg: ExecuteMsg,
) -> StdResult<Response> {
    match msg {
        ExecuteMsg::Example { value } => {
            // 处理示例消息
            Ok(Response::new().add_attribute("action", "example"))
        }
    }
}

// 初始化函数
pub fn instantiate(
    _deps: DepsMut,
    _env: Env,
    _info: MessageInfo,
    _msg: InstantiateMsg,
) -> StdResult<Response> {
    Ok(Response::default())
}

// 查询函数
pub fn query(_deps: Deps, _env: Env, _msg: QueryMsg) -> StdResult<Binary> {
    // 实现你的查询逻辑
    unimplemented!()
}

// 定义合约入口点
#[cfg(target_arch = "wasm32")]
mod wasm {
    use super::*;
    use cosmwasm_std::{do_handle, do_init, do_query};

    #[no_mangle]
    extern "C" fn init(env_ptr: u32, msg_ptr: u32) -> u32 {
        do_init(
            &instantiate,
            env_ptr,
            msg_ptr,
        )
    }

    #[no_mangle]
    extern "C" fn handle(env_ptr: u32, info_ptr: u32, msg_ptr: u32) -> u32 {
        do_handle(
            &execute,
            env_ptr,
            info_ptr,
            msg_ptr,
        )
    }

    #[no_mangle]
    extern "C" fn query(env_ptr: u32, msg_ptr: u32) -> u32 {
        do_query(
            &query,
            env_ptr,
            msg_ptr,
        )
    }
}

这个示例展示了如何使用cosmwasm-core开发一个基本的智能合约,包括:

  1. 定义合约消息
  2. 实现执行函数
  3. 实现初始化函数
  4. 实现查询函数
  5. 定义WASM入口点

注意:在实际开发中,你应该使用cosmwasm-std而不是直接使用cosmwasm-core,除非你有特殊的需求需要在no_std环境中运行。

完整示例demo

以下是一个更完整的cosmwasm-core智能合约示例:

// 导入所有必要的模块
use cosmwasm_std::{
    Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult,
};
use cosmwasm_core::exports::Extern;
use serde::{Deserialize, Serialize};
use schemars::JsonSchema;

// 定义初始化消息
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct InstantiateMsg {
    pub admin: String,
}

// 定义执行消息
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum ExecuteMsg {
    UpdateAdmin { new_admin: String },
    ExecuteAction { data: String },
}

// 定义查询消息
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum QueryMsg {
    GetAdmin {},
    GetContractInfo {},
}

// 定义合约状态
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct State {
    pub admin: String,
    pub version: String,
}

// 初始化函数
pub fn instantiate(
    deps: DepsMut,
    _env: Env,
    _info: MessageInfo,
    msg: InstantiateMsg,
) -> StdResult<Response> {
    let state = State {
        admin: msg.admin,
        version: "1.0".to_string(),
    };
    
    // 存储状态
    deps.storage.set(b"state", &to_vec(&state)?);
    
    Ok(Response::new().add_attribute("action", "instantiate"))
}

// 执行函数
pub fn execute(
    deps: DepsMut,
    _env: Env,
    info: MessageInfo,
    msg: ExecuteMsg,
) -> StdResult<Response> {
    match msg {
        ExecuteMsg::UpdateAdmin { new_admin } => {
            // 验证调用者是否是当前管理员
            let mut state: State = from_slice(&deps.storage.get(b"state").unwrap())?;
            if info.sender != state.admin {
                return Err(StdError::unauthorized());
            }
            
            // 更新管理员
            state.admin = new_admin;
            deps.storage.set(b"state", &to_vec(&state)?);
            
            Ok(Response::new().add_attribute("action", "update_admin"))
        }
        ExecuteMsg::ExecuteAction { data } => {
            // 执行某些操作
            Ok(Response::new()
                .add_attribute("action", "execute")
                .add_attribute("data", data))
        }
    }
}

// 查询函数
pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
    match msg {
        QueryMsg::GetAdmin {} => {
            let state: State = from_slice(&deps.storage.get(b"state").unwrap())?;
            to_binary(&state.admin)
        }
        QueryMsg::GetContractInfo {} => {
            let state: State = from_slice(&deps.storage.get(b"state").unwrap())?;
            to_binary(&state)
        }
    }
}

// WASM入口点
#[cfg(target_arch = "wasm32")]
mod wasm {
    use super::*;
    use cosmwasm_std::{do_handle, do_init, do_query};

    #[no_mangle]
    extern "C" fn init(env_ptr: u32, msg_ptr: u32) -> u32 {
        do_init(&instantiate, env_ptr, msg_ptr)
    }

    #[no_mangle]
    extern "C" fn handle(env_ptr: u32, info_ptr: u32, msg_ptr: u32) -> u32 {
        do_handle(&execute, env_ptr, info_ptr, msg_ptr)
    }

    #[no_mangle]
    extern "C" fn query(env_ptr: u32, msg_ptr: u32) -> u32 {
        do_query(&query, env_ptr, msg_ptr)
    }
}

这个完整示例展示了:

  1. 完整的合约状态管理
  2. 管理员权限控制
  3. 多种消息类型处理
  4. 状态存储和查询
  5. 错误处理
  6. WASM入口点实现

注意:实际开发中仍建议优先使用cosmwasm-std,除非确实需要在no_std环境中运行。


1 回复

Rust区块链智能合约开发库CosmWasm-core使用指南

简介

CosmWasm-core是一个专为Cosmos生态系统设计的智能合约开发库,它允许开发者使用Rust编写WebAssembly(WASM)智能合约,并与Cosmos SDK无缝集成。该库提供了模块化的WASM虚拟机实现,是构建去中心化应用(dApps)和区块链间通信(IBC)的理想选择。

主要特性

  • 基于Rust的安全智能合约开发环境
  • 高性能WASM虚拟机执行引擎
  • 与Cosmos SDK原生集成
  • 模块化设计,易于扩展
  • 支持跨链通信(IBC)
  • 提供丰富的标准库和工具链

安装与配置

首先,在Cargo.toml中添加依赖:

[dependencies]
cosmwasm-std = "1.0"
cosmwasm-storage = "1.0"
schemars = "0.8"
serde = { version = "1.0", features = ["derive"] }

基本使用示例

1. 创建简单智能合约

use cosmwasm_std::{
    entry_point, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult,
};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct InstantiateMsg {
    pub count: i32,
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum ExecuteMsg {
    Increment {},
    Reset { count: i32 },
}

#[entry_point]
pub fn instantiate(
    deps: DepsMut,
    _env: Env,
    _info: MessageInfo,
    msg: InstantiateMsg,
) -> StdResult<Response> {
    Ok(Response::default())
}

#[entry_point]
pub fn execute(
    deps: DepsMut,
    _env: Env,
    _info: MessageInfo,
    msg: ExecuteMsg,
) -> StdResult<Response> {
    match msg {
        ExecuteMsg::Increment {} => Ok(Response::default()),
        ExecuteMsg::Reset { count } => Ok(Response::default()),
    }
}

2. 编译为WASM

在项目根目录下运行:

RUSTFLAGS='-C link-arg=-s' cargo wasm

3. 优化WASM文件

docker run --rm -v "$(pwd)":/code \
  --mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \
  --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
  cosmwasm/rust-optimizer:0.12.6

高级功能

1. 状态管理

use cosmwasm_std::{StdResult, Storage};
use cosmwasm_storage::{singleton, singleton_read};

pub static CONFIG_KEY: &[u8] = b"config";

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct State {
    pub count: i32,
    pub owner: Addr,
}

pub fn store_config(storage: &mut dyn Storage, config: &State) -> StdResult<()> {
    singleton(storage, CONFIG_KEY).save(config)
}

pub fn read_config(storage: &dyn Storage) -> StdResult<State> {
    singleton_read(storage, CONFIG_KEY).load()
}

2. 跨合约调用

use cosmwasm_std::{to_binary, CosmosMsg, WasmMsg};

pub fn call_other_contract(
    contract_addr: Addr,
    msg: &ExecuteMsg,
) -> StdResult<CosmosMsg> {
    Ok(CosmosMsg::Wasm(WasmMsg::Execute {
        contract_addr: contract_addr.to_string(),
        msg: to_binary(msg)?,
        funds: vec![],
    }))
}

测试合约

#[cfg(test)]
mod tests {
    use super::*;
    use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
    use cosmwasm_std::{coins, from_binary};

    #[test]
    fn proper_initialization() {
        let mut deps = mock_dependencies();
        
        let msg = InstantiateMsg { count: 17 };
        let info = mock_info("creator", &coins(1000, "earth"));
        
        let res = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap();
        assert_eq!(0, res.messages.len());
    }
}

部署到Cosmos链

  1. 上传合约代码:
wasmd tx wasm store contract.wasm --from wallet --chain-id my-chain --gas auto -y
  1. 实例化合约:
wasmd tx wasm instantiate $CODE_ID '{"count":0}' --from wallet --label "my contract" --chain-id my-chain --gas auto -y
  1. 执行合约方法:
wasmd tx wasm execute $CONTRACT_ADDR '{"increment":{}}' --from wallet --chain-id my-chain --gas auto -y

最佳实践

  1. 使用Rust的安全特性(如所有权模型)来防止常见漏洞
  2. 为所有公共消息和状态实现Schema
  3. 编写全面的单元测试和集成测试
  4. 使用cosmwasm-check工具验证合约
  5. 遵循最小权限原则设计合约访问控制

CosmWasm-core为Rust开发者提供了强大的工具来构建安全、高效的区块链智能合约,特别适合Cosmos生态系统中的跨链应用开发。

完整示例代码

use cosmwasm_std::{
    entry_point, Binary, Deps, DepsMut, Env, MessageInfo, 
    Response, StdResult, Addr, Storage
};
use cosmwasm_storage::{singleton, singleton_read};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

// 合约状态结构体
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct State {
    pub count: i32,
    pub owner: Addr,
}

// 初始化消息
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct InstantiateMsg {
    pub count: i32,
}

// 执行消息
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum ExecuteMsg {
    Increment {},
    Reset { count: i32 },
    GetCount {},
}

// 查询消息
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum QueryMsg {
    GetCount {},
}

// 查询响应
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct CountResponse {
    pub count: i32,
}

// 状态存储键
pub static CONFIG_KEY: &[u8] = b"config";

// 初始化函数
#[entry_point]
pub fn instantiate(
    deps: DepsMut,
    _env: Env,
    info: MessageInfo,
    msg: InstantiateMsg,
) -> StdResult<Response> {
    let state = State {
        count: msg.count,
        owner: info.sender,
    };
    store_config(deps.storage, &state)?;
    Ok(Response::default())
}

// 执行函数
#[entry_point]
pub fn execute(
    deps: DepsMut,
    _env: Env,
    info: MessageInfo,
    msg: ExecuteMsg,
) -> StdResult<Response> {
    match msg {
        ExecuteMsg::Increment {} => increment(deps, info),
        ExecuteMsg::Reset { count } => reset(deps, info, count),
        ExecuteMsg::GetCount {} => get_count(deps),
    }
}

// 增加计数器
fn increment(deps: DepsMut, info: MessageInfo) -> StdResult<Response> {
    let mut state = read_config(deps.storage)?;
    if info.sender != state.owner {
        return Err(StdError::unauthorized());
    }
    state.count += 1;
    store_config(deps.storage, &state)?;
    Ok(Response::default())
}

// 重置计数器
fn reset(deps: DepsMut, info: MessageInfo, count: i32) -> StdResult<Response> {
    let mut state = read_config(deps.storage)?;
    if info.sender != state.owner {
        return Err(StdError::unauthorized());
    }
    state.count = count;
    store_config(deps.storage, &state)?;
    Ok(Response::default())
}

// 获取计数器值
fn get_count(deps: DepsMut) -> StdResult<Response> {
    let state = read_config(deps.storage)?;
    Ok(Response::new().add_attribute("count", state.count.to_string()))
}

// 查询函数
#[entry_point]
pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
    match msg {
        QueryMsg::GetCount {} => query_count(deps),
    }
}

// 查询计数器值
fn query_count(deps: Deps) -> StdResult<Binary> {
    let state = read_config(deps.storage)?;
    let resp = CountResponse { count: state.count };
    to_binary(&resp)
}

// 存储配置
pub fn store_config(storage: &mut dyn Storage, config: &State) -> StdResult<()> {
    singleton(storage, CONFIG_KEY).save(config)
}

// 读取配置
pub fn read_config(storage: &dyn Storage) -> StdResult<State> {
    singleton_read(storage, CONFIG_KEY).load()
}

#[cfg(test)]
mod tests {
    use super::*;
    use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
    use cosmwasm_std::{coins, from_binary, StdError};

    #[test]
    fn proper_initialization() {
        let mut deps = mock_dependencies();
        let msg = InstantiateMsg { count: 17 };
        let info = mock_info("creator", &coins(1000, "earth"));
        
        let res = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap();
        assert_eq!(0, res.messages.len());
        
        let state = read_config(&deps.storage).unwrap();
        assert_eq!(17, state.count);
        assert_eq!("creator", state.owner);
    }

    #[test]
    fn increment() {
        let mut deps = mock_dependencies();
        let msg = InstantiateMsg { count: 17 };
        let info = mock_info("creator", &coins(2, "token"));
        let _res = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap();

        let info = mock_info("creator", &coins(2, "token"));
        let msg = ExecuteMsg::Increment {};
        let _res = execute(deps.as_mut(), mock_env(), info, msg).unwrap();

        let state = read_config(&deps.storage).unwrap();
        assert_eq!(18, state.count);
    }

    #[test]
    fn reset() {
        let mut deps = mock_dependencies();
        let msg = InstantiateMsg { count: 17 };
        let info = mock_info("creator", &coins(2, "token"));
        let _res = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap();

        let info = mock_info("creator", &coins(2, "token"));
        let msg = ExecuteMsg::Reset { count: 5 };
        let _res = execute(deps.as_mut(), mock_env(), info, msg).unwrap();

        let state = read_config(&deps.storage).unwrap();
        assert_eq!(5, state.count);
    }

    #[test]
    fn unauthorized_reset() {
        let mut deps = mock_dependencies();
        let msg = InstantiateMsg { count: 17 };
        let info = mock_info("creator", &coins(2, "token"));
        let _res = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap();

        let info = mock_info("someone", &coins(2, "token"));
        let msg = ExecuteMsg::Reset { count: 5 };
        let res = execute(deps.as_mut(), mock_env(), info, msg);
        match res {
            Err(StdError::Unauthorized { .. }) => {}
            _ => panic!("Must return unauthorized error"),
        }
    }
}
回到顶部