dApp Docs/MSG链10分钟快速启动
Development reference. Not independently verified for production.

MSG Chain 10分钟快速启动 — 从零开始搭建区块链开发环境

数据来源:MSG Chain 代码库核实

主网状态: No-Go — 当前 MSGChain 主网裁决为 No-Go,以下内容反映代码实际状态,不代表生产可用。


一、MSG Chain 是什么

1.1 架构总览

MSG Chain(Messaging Chain)是一条专注于 AI Agent 经济体的 Layer 1 公链,采用 Cosmos SDK + CosmWasm + Dilithium-5 后量子密码学 的技术栈。类似以太坊使用 Solidity + EVM 开发智能合约,MSG Chain 使用 Rust + CosmWasm(WASM 虚拟机)开发合约。类比 Cosmos SDK 之于 Tendermint 如同 Hardhat 之于以太坊,MSG Chain 的合约开发工具链是 Rust + cargo-wasm。

AI Agent / dApp 应用层
──────────────────────────────
Agent API (REST/WebSocket)  |  MCP Server
JSON-RPC 2.0                |  gRPC
──────────────────────────────
CosmWasm 智能合约层
genesis_registry | dao | treasury | agent | micropayment
──────────────────────────────
MSG Chain 共识层 (Round-Robin + DAR)
Dilithium-5 PQC | BadgerDB | libp2p | 5s 出块
──────────────────────────────
Tendermint/Cosmos SDK 底层

1.2 核心特性

特性 说明
Dilithium-5 PQC 后量子密码学签名,抵抗量子计算攻击。类似 ECDSA 但使用 CRYSTALS-Dilithium 算法
DAR 共识 Dilithium-AR 共识扩展,Round-Robin 出块 + 去中心化自主轮次
CosmWasm 合约 基于 WASM 的智能合约引擎,使用 Rust 编写,类似以太坊的 Solidity
BadgerDB 存储 高性能键值存储,替代 Cosmos SDK 默认的 IAVL 树
AI Agent 原生 内置 Agent 注册、支付、宪章、DID 等 AI 经济体基础设施
5 秒出块 快速交易确认,适合微支付场景
Gas 分配 40/30/20/10 分配给验证者/开发者/燃烧/基金会金库

1.3 区块链核心参数

参数 值
Chain ID msg-chain-1
Chain 数字 ID 1
Bech32 地址前缀 msg
币种类型 (BIP44) 118
MSG 代币精度 18 位小数
Gas 价格 默认 1,000,000,000 attoMSG/gas (0.000000001 MSG/gas)
出块时间 5 秒
共识算法 Round-Robin + DAR (Dilithium-AR)
签名方案 Dilithium-5 (后量子)
状态存储 BadgerDB
最大活跃验证者 100
DAR 滞回区间 104 / 96
Gas 分配比例 40/30/20/10(验证者/开发者/燃烧/基金会金库)

1.4 RPC 端点

环境 RPC 端点 REST 端点
本地开发 http://localhost:26657 http://localhost:1317
未来主网 https://rpc.msgchain.org https://rest.msgchain.org

1.5 系统合约一览

创世注册合约(通过 genesis_registry 寻址):

合约 Canonical Key 核心职责
genesis_registry_v1 genesis_registry 创世注册中心,canonical key 寻址
dao_governance_v1 dao_governance DAO 治理:提案、投票、执行
foundation_treasury_v2 foundation_treasury 金库多签管理
gas_fee_distribution_v2 gas_fee_distribution Gas 费用分配
candidate_node_staking_v2 candidate_node_staking 节点质押
validator_qualification_v2 validator_qualification 验证者资格管理
emission_schedule_v2 emission_schedule 代币发行计划
block_time_schedule_v1 block_time_schedule 出块时间调度
ai_agent_constitution_v1 ai_agent_constitution_v1 AI Agent 宪章/策略
aidid_did_registry_v1 aidid_did_registry_v1 AI 去中心化身份

动态解析合约(不在 genesis 中注册):

合约 说明
agent_registry_v1 Agent 注册与发现
agent_payment_v1 AIPAY 支付系统
micropayment_session_v1 微支付按秒计费
msg_token_cw20 CW20 标准代币
dar_rating_v1 DAR 评分系统

二、环境准备

2.1 安装 Go 1.24+

MSG Chain 节点使用 Go 编写。类似以太坊的 geth 客户端,MSG Chain 节点二进制由 Go 编译。

# 下载 Go 1.21+
wget https://go.dev/dl/go1.21.13.linux-amd64.tar.gz
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.21.13.linux-amd64.tar.gz

# 配置环境变量
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
echo 'export GOPATH=$HOME/go' >> ~/.bashrc
echo 'export PATH=$PATH:$GOPATH/bin' >> ~/.bashrc
source ~/.bashrc

# 验证安装
go version
# 预期输出: go version go1.21.13 linux/amd64

2.2 安装 Rust 1.75+

智能合约使用 Rust 编写。类似以太坊使用 Solidity 编译器,MSG Chain 使用 rustc + wasm 目标编译合约。

# 安装 Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source $HOME/.cargo/env

# 安装 wasm32 编译目标
rustup target add wasm32-unknown-unknown

# 安装 cargo-wasm 和 wasm-opt
cargo install cargo-wasm
cargo install wasm-opt

# 验证安装
rustc --version
# 预期输出: rustc 1.75.0 (82e1608df 2023-12-21)

rustup target list --installed | grep wasm32
# 预期输出: wasm32-unknown-unknown

2.3 安装 Node.js 18+(可选,用于前端开发)

# 使用 nvm 安装
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
source ~/.bashrc
nvm install 18
nvm use 18

# 验证安装
node --version
# 预期输出: v18.20.4
npm --version
# 预期输出: 10.7.0

2.4 安装其他依赖

# Docker(用于合约优化和测试)
sudo apt-get update && sudo apt-get install -y docker.io

# jq(命令行 JSON 处理)
sudo apt-get install -y jq

# make
sudo apt-get install -y build-essential

# libwasmvm(CosmWasm 虚拟机依赖)
# 构建 MSG Chain 时会自动下载

三、10分钟快速启动

3.1 克隆仓库并编译

# 克隆 MSG Chain 仓库
git clone https://github.com/msgchain/msgchain
cd msgchain

# 查看目录结构
ls -la
# 预期包含: Makefile, go.mod, cmd/, x/, app/, contract_reference/

3.2 安装依赖

# 安装 Go 模块和 CosmWasm 依赖
make deps

# 该命令的执行内容包括:
# 1. 下载 Go 模块依赖(go mod download)
# 2. 安装 Rust 工具链(Rust/CosmWasm)
# 3. 编译 wasmvm 库
# 4. 安装 lint 工具

3.3 构建节点二进制

# 构建 Linux 二进制
make build-linux

# 验证构建
ls -la build/msgd
# 预期输出: build/msgd 可执行文件

# 检查版本
./build/msgd version
# 预期输出: msg-chain-1

3.4 初始化本地测试网

类似以太坊上的 Ganache 或 Hardhat 本地网络,MSG Chain 提供单节点测试环境。

# 初始化本地测试网
./build/msgd init --chain-id=msg-chain-1

# 该命令会创建:
# - $HOME/.msgd/config/ 目录(配置文件)
# - $HOME/.msgd/data/ 目录(区块链数据)
# - genesis.json(创世文件)
# - config.toml(节点配置)
# - app.toml(应用配置)

# 查看生成的配置文件
ls -la ~/.msgd/config/
# 预期包含: genesis.json, config.toml, app.toml, node_key.json, priv_validator_key.json

# 查看创世文件
cat ~/.msgd/config/genesis.json | jq '.chain_id'
# 预期输出: "msg-chain-1"

3.5 创建验证者账户

# 创建验证者密钥(类似以太坊的 keystore 文件)
./build/msgd keys add validator --keyring-backend test

# 预期输出包含:
# - name: validator
# - address: msg1...
# - pubkey: '{"@type":"/cosmos.crypto.dilithium.PubKey","key":"..."}'
# - mnemonic: "..."(24个助记词,请安全保存)

# 查看所有密钥
./build/msgd keys list --keyring-backend test
# 预期输出: 包含 validator 账户信息

# 查看账户地址
VALIDATOR_ADDR=$(./build/msgd keys show validator -a --keyring-backend test)
echo "Validator address: $VALIDATOR_ADDR"
# 预期输出: msg1...

3.6 添加创世账户并分配资金

# 将验证者地址添加到创世账户
./build/msgd add-genesis-account $VALIDATOR_ADDR 1000000000000000000umsg --keyring-backend test

# 验证创世账户
cat ~/.msgd/config/genesis.json | jq '.app_state.bank.balances[] | select(.address=="'"$VALIDATOR_ADDR"'")'
# 预期输出: {"address": "msg1...", "coins": [{"denom": "umsg", "amount": "1000000000000000000"}]}

# 创建验证者交易(将账户注册为验证者)
./build/msgd gentx validator 500000000000000000umsg \
  --chain-id=msg-chain-1 \
  --keyring-backend test

# 收集创世交易到 genesis.json
./build/msgd collect-gentxs

# 验证创世文件完整性
./build/msgd validate-genesis
# 预期输出: File at ~/.msgd/config/genesis.json is a valid genesis file

3.7 修改节点配置

# 修改 app.toml 中 Gas 价格设置
sed -i 's/minimum-gas-prices = ""/minimum-gas-prices = "1000000000attoMSG"/' ~/.msgd/config/app.toml

# 修改 config.toml 中 RPC 配置(允许外部访问)
sed -i 's/laddr = "tc[未公开路径]"/laddr = "tc[未公开路径]"/' ~/.msgd/config/config.toml
sed -i 's/cors_allowed_origins = \[\]/cors_allowed_origins = ["*"]/' ~/.msgd/config/config.toml

# 确认配置已更新
grep -E "minimum-gas-prices|laddr" ~/.msgd/config/app.toml ~/.msgd/config/config.toml

3.8 启动节点

# 启动 MSG Chain 节点
./build/msgd start

# 预期输出(持续滚动):
# INFO [2026-07-05|12:00:00] Starting node with ABCI Tendermint in-process
# INFO [2026-07-05|12:00:05] Committed state       module=state height=1 txs=0
# INFO [2026-07-05|12:00:10] Committed state       module=state height=2 txs=0
# ...

# 如果需要后台运行:
# nohup ./build/msgd start > msgd.log 2>&1 &

3.9 验证节点运行

打开新终端:

# 查询节点状态
curl -s http://localhost:26657/status | jq '.result.sync_info'
# 预期输出:
# {
#   "latest_block_height": "10",
#   "latest_block_time": "2026-07-05T12:00:50Z",
#   "catching_up": false
# }

# 查询账户余额
./build/msgd query bank balances $VALIDATOR_ADDR
# 预期输出:
# balances:
# - amount: "1000000000000000000"
#   denom: umsg

3.10 部署第一个 CosmWasm 合约

3.10.1 准备合约二进制文件

# 使用已有的合约模板(contract_reference 目录中)
ls contract_reference/contracts/
# 预期包含: agent_payment_v1, agent_registry_v1, counter_v1 等

# 找到一个已编译的 WASM 文件
find contract_reference -name "*.wasm" 2>/dev/null

# 如果没有预编译文件,使用示例合约
# 或者从 https://github.com/CosmWasm/cw-plus/releases 下载 cw20_base.wasm

3.10.2 上传合约代码

类似以太坊上部署合约的第一步是发送合约字节码,MSG Chain 使用 tx wasm store 上传 WASM 二进制。

# 上传合约 WASM 到链上
./build/msgd tx wasm store contract_reference/contracts/counter_v1.wasm \
  --from validator \
  --gas auto \
  --gas-prices 1000000000attoMSG \
  --gas-adjustment 1.3 \
  --chain-id msg-chain-1 \
  --keyring-backend test \
  --node tcp://localhost:26657 \
  -y

# 预期输出:
# code_id: 1
# gas_used: 1234567
# txhash: ABCDEF...(交易哈希)

# 查询已上传的合约代码
./build/msgd query wasm list-code
# 预期输出:
# code_infos:
# - code_id: "1"
#   creator: msg1...
#   data_hash: ...

3.10.3 实例化合约

类似以太坊上通过 new Contract() 创建合约实例,MSG Chain 使用 tx wasm instantiate。

# 实例化合约
CODE_ID=1
INIT_MSG='{"count": 0}'

./build/msgd tx wasm instantiate $CODE_ID "$INIT_MSG" \
  --from validator \
  --label "my-first-contract" \
  --gas auto \
  --gas-prices 1000000000attoMSG \
  --gas-adjustment 1.3 \
  --chain-id msg-chain-1 \
  --keyring-backend test \
  --node tcp://localhost:26657 \
  -y

# 记录合约地址(从输出中获取)

# 查询已实例化的合约
./build/msgd query wasm list-contract-by-code $CODE_ID
# 预期输出:
# contracts:
# - msg1...(合约地址)

3.10.4 查询合约状态

类似以太坊上调用 view 函数,MSG Chain 使用 query wasm contract-state smart。

CONTRACT_ADDR="msg1..." # 替换为上一步获取的地址

# 查询合约当前状态
./build/msgd query wasm contract-state smart $CONTRACT_ADDR '{"get_count": {}}'
# 预期输出:
# data:
#   count: 0

# 查询合约原始存储
./build/msgd query wasm contract-state all $CONTRACT_ADDR

3.10.5 执行合约交易

类似以太坊上发送交易修改合约状态,MSG Chain 使用 tx wasm execute。

# 执行 increment 操作
./build/msgd tx wasm execute $CONTRACT_ADDR '{"increment": {}}' \
  --from validator \
  --gas auto \
  --gas-prices 1000000000attoMSG \
  --gas-adjustment 1.3 \
  --chain-id msg-chain-1 \
  --keyring-backend test \
  --node tcp://localhost:26657 \
  -y

# 再次查询验证状态变化
./build/msgd query wasm contract-state smart $CONTRACT_ADDR '{"get_count": {}}'
# 预期输出:
# data:
#   count: 1

3.10.6 完整的合约部署脚本

#!/bin/bash
# deploy.sh — 完整合约部署自动化脚本
# 使用方法: bash deploy.sh <contract.wasm> <init_msg.json>

set -e

CONTRACT_WASM=$1
INIT_MSG=${2:-'{}'}
LABEL=${3:-"my-contract"}
KEYRING=${KEYRING:-test}
CHAIN_ID=${CHAIN_ID:-msg-chain-1}
NODE=${NODE:-tcp://localhost:26657}
FROM=${FROM:-validator}
GAS_PRICES=${GAS_PRICES:-1000000000attoMSG}
GAS_ADJUSTMENT=${GAS_ADJUSTMENT:-1.3}

echo "=== Deploying contract: $CONTRACT_WASM ==="

# Step 1: Store contract
echo ">> Storing contract..."
STORE_OUTPUT=$(./build/msgd tx wasm store "$CONTRACT_WASM" \
  --from "$FROM" \
  --gas auto \
  --gas-prices "$GAS_PRICES" \
  --gas-adjustment "$GAS_ADJUSTMENT" \
  --chain-id "$CHAIN_ID" \
  --keyring-backend "$KEYRING" \
  --node "$NODE" \
  -y)
echo "$STORE_OUTPUT"
CODE_ID=$(echo "$STORE_OUTPUT" | grep -oP 'code_id: \K\d+')
echo ">> Code ID: $CODE_ID"

# Step 2: Instantiate contract
echo ">> Instantiating contract with code_id=$CODE_ID..."
INSTANTIATE_OUTPUT=$(./build/msgd tx wasm instantiate "$CODE_ID" "$INIT_MSG" \
  --from "$FROM" \
  --label "$LABEL" \
  --gas auto \
  --gas-prices "$GAS_PRICES" \
  --gas-adjustment "$GAS_ADJUSTMENT" \
  --chain-id "$CHAIN_ID" \
  --keyring-backend "$KEYRING" \
  --node "$NODE" \
  -y)
echo "$INSTANTIATE_OUTPUT"
CONTRACT_ADDR=$(echo "$INSTANTIATE_OUTPUT" | grep -oP 'contract_address: \K\S+')
echo ">> Contract Address: $CONTRACT_ADDR"

# Step 3: Query contract
echo ">> Querying contract..."
./build/msgd query wasm contract-state smart "$CONTRACT_ADDR" '{"get_count": {}}' \
  --node "$NODE"

echo "=== Deployment complete! ==="
echo "Code ID: $CODE_ID"
echo "Contract Address: $CONTRACT_ADDR"

四、创建第一个智能合约

类似以太坊上用 Hardhat 创建 Solidity 项目,MSG Chain 使用 Cargo 创建 Rust 项目。本节创建一个完整的计数器合约。

4.1 初始化合约项目

# 创建合约项目
cargo new --lib my-counter
cd my-counter

# 添加 wasm 编译目标(如果之前未添加)
rustup target add wasm32-unknown-unknown

4.2 编写 Cargo.toml

[package]
name = "my-counter"
version = "0.1.0"
edition = "2021"
description = "A simple counter contract for MSG Chain"
authors = ["msgchain-developer"]

[lib]
crate-type = ["cdylib", "rlib"]

[profile.release]
opt-level = 3
debug = false
rpath = false
lto = true
debug-assertions = false
codegen-units = 1
panic = "abort"
overflow-checks = true

[dependencies]
cosmwasm-std = { version = "1.5", features = ["staking"] }
cosmwasm-storage = "1.5"
cosmwasm-schema = "1.5"
cw-storage-plus = "1.2"
cw2 = "1.2"
serde = { version = "1", features = ["derive"] }
thiserror = "1"

[features]
default = []
library = []

4.3 编写消息定义(src/msg.rs)

类似 Solidity 中的函数签名和事件定义,CosmWasm 使用 Rust 结构体定义合约接口。

use cosmwasm_schema::cw_serde;
use cosmwasm_std::Addr;

#[cw_serde]
pub struct InstantiateMsg {
    pub count: i32,
    pub owner: Option<String>,
}

#[cw_serde]
pub enum ExecuteMsg {
    Increment {},
    Reset { count: i32 },
    UpdateOwner { new_owner: String },
}

#[cw_serde]
pub enum QueryMsg {
    GetCount {},
    GetOwner {},
}

#[cw_serde]
pub struct CountResponse {
    pub count: i32,
}

#[cw_serde]
pub struct OwnerResponse {
    pub owner: String,
}

4.4 编写状态管理(src/state.rs)

类似 Solidity 中的 mapping 和 uint 状态变量,CosmWasm 使用 cw-storage-plus 进行持久化存储。

use cw_storage_plus::Item;
use serde::{Deserialize, Serialize};

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

pub const STATE: Item<State> = Item::new("state");

4.5 编写合约主文件(src/contract.rs)

这是合约的核心逻辑,类似 Solidity 中的合约方法实现。

use cosmwasm_std::{
    entry_point, to_binary, Binary, Deps, DepsMut, Env, MessageInfo,
    Response, StdError, StdResult,
};

use crate::msg::{
    CountResponse, ExecuteMsg, InstantiateMsg, OwnerResponse, QueryMsg,
};
use crate::state::{State, STATE};

#[entry_point]
pub fn instantiate(
    deps: DepsMut,
    _env: Env,
    info: MessageInfo,
    msg: InstantiateMsg,
) -> StdResult<Response> {
    let owner = msg.owner.unwrap_or_else(|| info.sender.to_string());

    let state = State {
        count: msg.count,
        owner: owner.clone(),
    };
    STATE.save(deps.storage, &state)?;

    // 使用 cw2 设置合约版本
    cw2::set_contract_version(deps.storage, "my-counter", "0.1.0")?;

    Ok(Response::new()
        .add_attribute("method", "instantiate")
        .add_attribute("owner", owner)
        .add_attribute("count", msg.count.to_string()))
}

#[entry_point]
pub fn execute(
    deps: DepsMut,
    _env: Env,
    info: MessageInfo,
    msg: ExecuteMsg,
) -> StdResult<Response> {
    match msg {
        ExecuteMsg::Increment {} => try_increment(deps),
        ExecuteMsg::Reset { count } => try_reset(deps, info, count),
        ExecuteMsg::UpdateOwner { new_owner } => try_update_owner(deps, info, new_owner),
    }
}

fn try_increment(deps: DepsMut) -> StdResult<Response> {
    STATE.update(deps.storage, |mut state| -> StdResult<_> {
        state.count += 1;
        Ok(state)
    })?;

    Ok(Response::new().add_attribute("method", "increment"))
}

fn try_reset(deps: DepsMut, info: MessageInfo, count: i32) -> StdResult<Response> {
    let state = STATE.load(deps.storage)?;
    if info.sender.to_string() != state.owner {
        return Err(StdError::generic_err("Unauthorized: only owner can reset"));
    }

    STATE.update(deps.storage, |mut state| -> StdResult<_> {
        state.count = count;
        Ok(state)
    })?;

    Ok(Response::new().add_attribute("method", "reset"))
}

fn try_update_owner(
    deps: DepsMut,
    info: MessageInfo,
    new_owner: String,
) -> StdResult<Response> {
    let state = STATE.load(deps.storage)?;
    if info.sender.to_string() != state.owner {
        return Err(StdError::generic_err("Unauthorized: only owner can update owner"));
    }

    STATE.update(deps.storage, |mut state| -> StdResult<_> {
        state.owner = new_owner.clone();
        Ok(state)
    })?;

    Ok(Response::new().add_attribute("method", "update_owner"))
}

#[entry_point]
pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
    match msg {
        QueryMsg::GetCount {} => to_binary(&query_count(deps)?),
        QueryMsg::GetOwner {} => to_binary(&query_owner(deps)?),
    }
}

fn query_count(deps: Deps) -> StdResult<CountResponse> {
    let state = STATE.load(deps.storage)?;
    Ok(CountResponse { count: state.count })
}

fn query_owner(deps: Deps) -> StdResult<OwnerResponse> {
    let state = STATE.load(deps.storage)?;
    Ok(OwnerResponse { owner: state.owner })
}

4.6 编写库入口(src/lib.rs)

pub mod contract;
pub mod msg;
pub mod state;

#[cfg(test)]
mod testing;

4.7 编写测试(src/testing.rs)

use crate::contract::{execute, instantiate, query};
use crate::msg::{
    CountResponse, ExecuteMsg, InstantiateMsg, OwnerResponse, QueryMsg,
};
use cosmwasm_std::testing::{
    mock_dependencies, mock_env, mock_info,
};
use cosmwasm_std::{from_binary, Addr};

#[test]
fn proper_initialization() {
    let mut deps = mock_dependencies();
    let env = mock_env();
    let info = mock_info("creator", &[]);

    let msg = InstantiateMsg {
        count: 0,
        owner: None,
    };
    let res = instantiate(deps.as_mut(), env.clone(), info, msg).unwrap();
    assert_eq!(res.attributes.len(), 3);

    // Query count
    let query_res = query(deps.as_ref(), env.clone(), QueryMsg::GetCount {}).unwrap();
    let count_res: CountResponse = from_binary(&query_res).unwrap();
    assert_eq!(count_res.count, 0);

    // Query owner
    let query_res = query(deps.as_ref(), env.clone(), QueryMsg::GetOwner {}).unwrap();
    let owner_res: OwnerResponse = from_binary(&query_res).unwrap();
    assert_eq!(owner_res.owner, "creator");
}

#[test]
fn increment() {
    let mut deps = mock_dependencies();
    let env = mock_env();
    let info = mock_info("creator", &[]);

    let instantiate_msg = InstantiateMsg {
        count: 0,
        owner: None,
    };
    instantiate(deps.as_mut(), env.clone(), info.clone(), instantiate_msg).unwrap();

    let execute_msg = ExecuteMsg::Increment {};
    execute(deps.as_mut(), env.clone(), info, execute_msg).unwrap();

    let query_res = query(deps.as_ref(), env.clone(), QueryMsg::GetCount {}).unwrap();
    let count_res: CountResponse = from_binary(&query_res).unwrap();
    assert_eq!(count_res.count, 1);
}

#[test]
fn reset_with_authorized_owner() {
    let mut deps = mock_dependencies();
    let env = mock_env();
    let info = mock_info("owner", &[]);

    let instantiate_msg = InstantiateMsg {
        count: 5,
        owner: Some("owner".to_string()),
    };
    instantiate(deps.as_mut(), env.clone(), info.clone(), instantiate_msg).unwrap();

    let execute_msg = ExecuteMsg::Reset { count: 0 };
    execute(deps.as_mut(), env.clone(), info, execute_msg).unwrap();

    let query_res = query(deps.as_ref(), env.clone(), QueryMsg::GetCount {}).unwrap();
    let count_res: CountResponse = from_binary(&query_res).unwrap();
    assert_eq!(count_res.count, 0);
}

#[test]
fn reset_unauthorized() {
    let mut deps = mock_dependencies();
    let env = mock_env();
    let info = mock_info("owner", &[]);

    let instantiate_msg = InstantiateMsg {
        count: 5,
        owner: Some("owner".to_string()),
    };
    instantiate(deps.as_mut(), env.clone(), info, instantiate_msg).unwrap();

    let unauthorized_info = mock_info("attacker", &[]);
    let execute_msg = ExecuteMsg::Reset { count: 0 };
    let res = execute(deps.as_mut(), env.clone(), unauthorized_info, execute_msg);
    assert!(res.is_err());
}

4.8 编译合约

# 编译为 WASM 二进制
RUSTFLAGS='-C link-arg=-s' cargo build --release --target wasm32-unknown-unknown

# 查看编译产物
ls -la target/wasm32-unknown-unknown/release/my_counter.wasm
# 预期输出: 约 150KB 的 WASM 文件

# 优化 WASM 大小(减小部署成本和 gas 消耗)
wasm-opt -Os -o optimized.wasm target/wasm32-unknown-unknown/release/my_counter.wasm

# 查看优化前后对比
ls -la optimized.wasm target/wasm32-unknown-unknown/release/my_counter.wasm
# 优化后体积通常减少 50-70%

# 生成 JSON Schema(便于前端和客户端使用)
cargo schema
ls -la schema/
# 预期包含:
# - execute_msg.json
# - instantiate_msg.json
# - query_msg.json

4.9 生成合约 Schema

// src/bin/schema.rs(可选 — 自动由 cargo schema 生成)
use cosmwasm_schema::write_api;
use my_counter::msg::{ExecuteMsg, InstantiateMsg, QueryMsg};

fn main() {
    write_api! {
        instantiate: InstantiateMsg,
        execute: ExecuteMsg,
        query: QueryMsg,
    }
}

4.10 完整项目结构

my-counter/
├── Cargo.toml          # 项目配置和依赖
├── src/
│   ├── lib.rs          # 库入口
│   ├── contract.rs     # 合约逻辑(入口点)
│   ├── msg.rs          # 消息定义(InstantiateMsg, ExecuteMsg, QueryMsg)
│   ├── state.rs        # 状态存储定义
│   └── testing.rs      # 单元测试
├── schema/             # 生成的 JSON Schema
│   ├── execute_msg.json
│   ├── instantiate_msg.json
│   └── query_msg.json
├── optimized.wasm       # 优化后的 WASM 二进制
└── target/              # 编译产物

五、使用 CosmJS 与链交互

类似 ethers.js 之于以太坊,CosmJS 是 MSG Chain 的 JavaScript SDK。

5.1 安装 CosmJS

# 在前端项目中安装
npm install @cosmjs/cosmwasm-stargate @cosmjs/proto-signing @cosmjs/encoding @cosmjs/stargate

5.2 连接客户端

// src/lib/cosmos.ts
import { CosmWasmClient, SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate";
import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";
import { GasPrice } from "@cosmjs/stargate";

const RPC_ENDPOINT = "http://localhost:26657";
const CHAIN_ID = "msg-chain-1";

let cosmWasmClient: CosmWasmClient | null = null;
let signingClient: SigningCosmWasmClient | null = null;

export async function getQueryClient(): Promise<CosmWasmClient> {
  if (!cosmWasmClient) {
    cosmWasmClient = await CosmWasmClient.connect(RPC_ENDPOINT);
  }
  return cosmWasmClient;
}

export async function getSigningClient(mnemonic: string): Promise<SigningCosmWasmClient> {
  const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, {
    prefix: "msg",
    gasPrice: GasPrice.fromString("1000000000attoMSG"),
  });
  signingClient = await SigningCosmWasmClient.connectWithSigner(RPC_ENDPOINT, wallet);
  return signingClient;
}

5.3 查询合约

// src/lib/query.ts
import { getQueryClient } from "./cosmos";

export async function queryContract<T>(
  contractAddress: string,
  queryMsg: Record<string, unknown>
): Promise<T> {
  const client = await getQueryClient();
  return client.queryContractSmart(contractAddress, queryMsg);
}

// 查询计数器合约
export async function getCount(contractAddress: string): Promise<number> {
  const result = await queryContract<{ count: number }>(contractAddress, {
    get_count: {},
  });
  return result.count;
}

export async function getOwner(contractAddress: string): Promise<string> {
  const result = await queryContract<{ owner: string }>(contractAddress, {
    get_owner: {},
  });
  return result.owner;
}

5.4 执行交易

// src/lib/execute.ts
import { getSigningClient } from "./cosmos";

export async function executeContract(
  mnemonic: string,
  contractAddress: string,
  executeMsg: Record<string, unknown>
) {
  const client = await getSigningClient(mnemonic);
  const [account] = await client.getAccounts();

  const result = await client.execute(
    account.address,
    contractAddress,
    executeMsg,
    "auto"
  );

  return {
    transactionHash: result.transactionHash,
    gasUsed: result.gasUsed,
    height: result.height,
    rawLog: result.rawLog,
  };
}

// 执行 Increment
export async function increment(
  mnemonic: string,
  contractAddress: string
) {
  return executeContract(mnemonic, contractAddress, {
    increment: {},
  });
}

// 执行 Reset(仅 owner 可调用)
export async function reset(
  mnemonic: string,
  contractAddress: string,
  count: number
) {
  return executeContract(mnemonic, contractAddress, {
    reset: { count },
  });
}

5.5 查询余额

// src/lib/balance.ts
import { getQueryClient } from "./cosmos";

export async function getBalance(address: string) {
  const client = await getQueryClient();
  return client.getBalance(address, "umsg");
}

export async function getAllBalances(address: string) {
  const client = await getQueryClient();
  return client.getAllBalances(address);
}

5.6 查询区块和交易

// src/lib/chain.ts
import { getQueryClient } from "./cosmos";

export async function getBlock(height?: number) {
  const client = await getQueryClient();
  return client.getBlock(height);
}

export async function getHeight(): Promise<number> {
  const client = await getQueryClient();
  return client.getHeight();
}

export async function getTx(hash: string) {
  const client = await getQueryClient();
  return client.getTx(hash);
}

5.7 完整示例:从查询到交易

// src/examples/counter-workflow.ts
import { getQueryClient, getSigningClient } from "../cosmos";
import { queryContract } from "../query";

async function counterWorkflow() {
  const mnemonic = "your test mnemonic here...";
  const contractAddress = "msg1...your-contract-address";

  // 1. 查询当前计数
  const count = await queryContract<{ count: number }>(contractAddress, {
    get_count: {},
  });
  console.log("Current count:", count.count);

  // 2. 获取签名客户端
  const signingClient = await getSigningClient(mnemonic);
  const [account] = await signingClient.getAccounts();
  console.log("Sender address:", account.address);

  // 3. 执行 Increment
  const result = await signingClient.execute(
    account.address,
    contractAddress,
    { increment: {} },
    "auto"
  );
  console.log("Transaction hash:", result.transactionHash);

  // 4. 确认状态变化
  const newCount = await queryContract<{ count: number }>(contractAddress, {
    get_count: {},
  });
  console.log("New count:", newCount.count);

  // 5. 查询交易详情
  const tx = await signingClient.getTx(result.transactionHash);
  console.log("Gas used:", tx?.gasUsed);
}

counterWorkflow().catch(console.error);

六、使用 Keplr 钱包连接

类似 MetaMask 连接到以太坊网络,Keplr 是 Cosmos 生态的标准钱包。以下配置可将 MSG Chain 添加到 Keplr。

6.1 Keplr 链配置

// src/config/keplr.ts
export const msgChainConfig = {
  chainId: "msg-chain-1",
  chainName: "MSG Chain",
  rpc: "http://localhost:26657",
  rest: "http://localhost:1317",
  bip44: { coinType: 118 },
  bech32Config: {
    bech32PrefixAccAddr: "msg",
    bech32PrefixAccPub: "msgpub",
    bech32PrefixValAddr: "msgvaloper",
    bech32PrefixValPub: "msgvaloperpub",
    bech32PrefixConsAddr: "msgvalcons",
    bech32PrefixConsPub: "msgvalconspub",
  },
  currencies: [
    {
      coinDenom: "MSG",
      coinMinimalDenom: "umsg",
      coinDecimals: 18,
    },
  ],
  feeCurrencies: [
    {
      coinDenom: "MSG",
      coinMinimalDenom: "umsg",
      coinDecimals: 18,
      gasPriceStep: {
        low: 0.01,
        average: 0.025,
        high: 0.04,
      },
    },
  ],
  stakeCurrency: {
    coinDenom: "MSG",
    coinMinimalDenom: "umsg",
    coinDecimals: 18,
  },
  gasPriceStep: {
    low: 0.01,
    average: 0.025,
    high: 0.04,
  },
};

6.2 钱包连接 Hook

// src/hooks/useKeplr.ts
import { useCallback, useEffect, useState } from "react";
import { msgChainConfig } from "../config/keplr";

interface KeplrState {
  address: string | null;
  isConnected: boolean;
  isInstalled: boolean;
  balance: string | null;
}

export function useKeplr() {
  const [state, setState] = useState<KeplrState>({
    address: null,
    isConnected: false,
    isInstalled: false,
    balance: null,
  });

  useEffect(() => {
    const keplrExists = typeof window !== "undefined" && window.keplr;
    setState((prev) => ({ ...prev, isInstalled: !!keplrExists }));
  }, []);

  const connect = useCallback(async () => {
    if (!window.keplr) {
      alert("请安装 Keplr 钱包扩展");
      return;
    }

    try {
      await window.keplr.experimentalSuggestChain(msgChainConfig);
      await window.keplr.enable(msgChainConfig.chainId);

      const offlineSigner = window.keplr.getOfflineSigner(msgChainConfig.chainId);
      const accounts = await offlineSigner.getAccounts();
      const address = accounts[0]?.address || null;

      setState({
        address,
        isConnected: !!address,
        isInstalled: true,
        balance: null,
      });
    } catch (err) {
      console.error("Keplr connection failed:", err);
      setState((prev) => ({ ...prev, isConnected: false }));
    }
  }, []);

  const disconnect = useCallback(() => {
    setState({
      address: null,
      isConnected: false,
      isInstalled: true,
      balance: null,
    });
  }, []);

  return {
    ...state,
    connect,
    disconnect,
  };
}

6.3 使用 Keplr 签名客户端

// src/lib/keplr-signer.ts
import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate";
import { GasPrice } from "@cosmjs/stargate";
import { msgChainConfig } from "../config/keplr";

export async function getKeplrSigningClient() {
  if (!window.keplr) {
    throw new Error("Keplr 未安装");
  }

  await window.keplr.enable(msgChainConfig.chainId);
  const offlineSigner = window.keplr.getOfflineSigner(msgChainConfig.chainId);

  const client = await SigningCosmWasmClient.connectWithSigner(
    msgChainConfig.rpc,
    offlineSigner,
    {
      gasPrice: GasPrice.fromString("1000000000attoMSG"),
    }
  );

  return client;
}

export async function getKeplrAddress(): Promise<string> {
  if (!window.keplr) {
    throw new Error("Keplr 未安装");
  }

  await window.keplr.enable(msgChainConfig.chainId);
  const offlineSigner = window.keplr.getOfflineSigner(msgChainConfig.chainId);
  const accounts = await offlineSigner.getAccounts();
  return accounts[0].address;
}

6.4 React 连接按钮组件

// src/components/KeplrConnect.tsx
import React from "react";
import { useKeplr } from "../hooks/useKeplr";

export function KeplrConnect() {
  const { address, isConnected, isInstalled, connect, disconnect } = useKeplr();

  if (!isInstalled) {
    return (
      <div className="p-4 bg-yellow-100 rounded-lg">
        <p className="text-yellow-800">
          请安装{" "}
          <a
            href="https://chrome.google.com/webstore/detail/keplr/dmkamcknogkgcdfhhbddcghachkejeap"
            target="_blank"
            rel="noopener noreferrer"
            className="underline"
          >
            Keplr 钱包
          </a>
        </p>
      </div>
    );
  }

  if (!isConnected) {
    return (
      <button
        onClick={connect}
        className="bg-blue-600 text-white px-6 py-2 rounded-lg hover:bg-blue-700 transition-colors"
      >
        连接 Keplr 钱包
      </button>
    );
  }

  return (
    <div className="flex items-center gap-4 p-4 bg-green-50 rounded-lg">
      <div className="flex items-center gap-2">
        <span className="w-2 h-2 bg-green-500 rounded-full animate-pulse" />
        <span className="text-green-800 font-medium">已连接</span>
      </div>
      <code className="text-sm bg-white px-3 py-1 rounded border">
        {address?.slice(0, 8)}...{address?.slice(-6)}
      </code>
      <button
        onClick={disconnect}
        className="text-sm text-gray-600 hover:text-red-600 underline"
      >
        断开
      </button>
    </div>
  );
}

6.5 TypeScript 类型声明

// src/types/keplr.d.ts
import { Window as KeplrWindow } from "@keplr-wallet/types";

declare global {
  interface Window extends KeplrWindow {}
}
# 安装 Keplr 类型定义
npm install --save-dev @keplr-wallet/types

七、Make 命令速查表

7.1 完整命令列表

命令 说明 预期耗时
make deps 安装 Go 和 Rust/CosmWasm 依赖 2-5 分钟
make lint 运行代码格式和 lint 检查 30 秒
make test 运行单元测试 1-3 分钟
make test-quantum 运行后量子密码学测试(Dilithium-5) 2-5 分钟
make build-linux 编译 Linux 二进制 2-5 分钟
make ci-contracts CI 管道:编译+测试所有合约 5-10 分钟

7.2 节点管理命令

# 初始化测试网
./build/msgd init --chain-id=msg-chain-1

# 启动节点
./build/msgd start

# 查询节点状态
curl -s http://localhost:26657/status | jq

# 查询节点健康
curl -s http://localhost:26657/health

# 查询网络信息
curl -s http://localhost:26657/net_info | jq '.result.n_peers'

# 查询区块
curl -s http://localhost:26657/block?height=1 | jq

# 查询未确认交易
curl -s http://localhost:26657/unconfirmed_txs | jq '.result.n_txs'

7.3 密钥管理命令

# 创建密钥
./build/msgd keys add <key-name> --keyring-backend test

# 从助记词恢复密钥
./build/msgd keys add <key-name> --recover --keyring-backend test

# 列出密钥
./build/msgd keys list --keyring-backend test

# 显示密钥地址
./build/msgd keys show <key-name> -a --keyring-backend test

# 显示密钥公钥
./build/msgd keys show <key-name> -p --keyring-backend test

# 删除密钥
./build/msgd keys delete <key-name> --keyring-backend test -y

7.4 账户和余额命令

# 查询余额
./build/msgd query bank balances <address>

# 查询账户详情
./build/msgd query auth account <address>

# 转账
./build/msgd tx bank send <from> <to> <amount> \
  --from <key-name> \
  --gas auto \
  --gas-prices 1000000000attoMSG \
  --chain-id msg-chain-1

# 查询未花费输出
./build/msgd query bank spendable-balances <address>

7.5 合约管理命令

# 上传合约代码
./build/msgd tx wasm store <contract.wasm> \
  --from <key-name> \
  --gas auto \
  --gas-prices 1000000000attoMSG \
  --gas-adjustment 1.3 \
  --chain-id msg-chain-1

# 列出已上传代码
./build/msgd query wasm list-code

# 查看代码详情
./build/msgd query wasm code <code-id>

# 实例化合约
./build/msgd tx wasm instantiate <code-id> '<init-msg>' \
  --from <key-name> \
  --label "<label>" \
  --gas auto \
  --gas-prices 1000000000attoMSG \
  --chain-id msg-chain-1

# 执行合约
./build/msgd tx wasm execute <contract-addr> '<execute-msg>' \
  --from <key-name> \
  --gas auto \
  --gas-prices 1000000000attoMSG \
  --chain-id msg-chain-1

# 查询合约(智能查询)
./build/msgd query wasm contract-state smart <contract-addr> '<query-msg>'

# 查询合约原始存储
./build/msgd query wasm contract-state all <contract-addr>

# 查询合约原始键值
./build/msgd query wasm contract-state raw <contract-addr> <key-hex>

# 按代码 ID 列出合约
./build/msgd query wasm list-contract-by-code <code-id>

# 查询合约历史
./build/msgd query wasm contract-history <contract-addr>

# 迁移合约到新代码
./build/msgd tx wasm migrate <contract-addr> <new-code-id> '{}' \
  --from <key-name> \
  --gas auto \
  --gas-prices 1000000000attoMSG \
  --chain-id msg-chain-1

7.6 验证者管理命令

# 创建验证者
./build/msgd tx staking create-validator \
  --amount 500000000000000000umsg \
  --pubkey $(./build/msgd tendermint show-validator) \
  --moniker "my-validator" \
  --chain-id msg-chain-1 \
  --from validator \
  --gas auto \
  --gas-prices 1000000000attoMSG

# 查询验证者集
./build/msgd query staking validators

# 查询验证者详情
./build/msgd query staking validator <valoper-address>

# 委托
./build/msgd tx staking delegate <valoper-address> <amount> \
  --from <key-name> \
  --gas auto \
  --gas-prices 1000000000attoMSG \
  --chain-id msg-chain-1

# 取消委托
./build/msgd tx staking unbond <valoper-address> <amount> \
  --from <key-name> \
  --gas auto \
  --gas-prices 1000000000attoMSG \
  --chain-id msg-chain-1

# 领取奖励
./build/msgd tx distribution withdraw-rewards <valoper-address> \
  --from <key-name> \
  --gas auto \
  --gas-prices 1000000000attoMSG \
  --chain-id msg-chain-1 \
  --commission

7.7 查询命令

# 查询交易
./build/msgd query tx <tx-hash>

# 查询交易事件
./build/msgd query txs --events 'message.sender=<address>'

# 查询共识参数
./build/msgd query consensus params

# 查询参数
./build/msgd query params subspace <subspace> <key>

# 查询当前出块高度
curl -s http://localhost:26657/status | jq '.result.sync_info.latest_block_height'

# 查询代币供应量
./build/msgd query total-supply

# 查询创世文件
cat ~/.msgd/config/genesis.json | jq '.'

八、常见问题

8.1 节点无法启动

现象: ./build/msgd start 报错或闪退

解决方案:

# 1. 检查是否已有节点在运行
ps aux | grep msgd
killall msgd

# 2. 检查配置文件是否存在
ls -la ~/.msgd/config/
# 如果不存在,重新执行 init

# 3. 重置数据(保留密钥和配置)
./build/msgd unsafe-reset-all
# 然后重新启动

# 4. 检查端口是否被占用
lsof -i :26657
lsof -i :26656
# 如果有冲突,修改 config.toml 中的端口

# 5. 查看日志
./build/msgd start --log_level="info"

8.2 合约部署失败

现象: tx wasm store 返回错误码

解决方案:

# 1. 检查 WASM 文件是否正确
file contract.wasm
# 预期输出: contract.wasm: WebAssembly (wasm) binary module version ...

# 2. 检查 WASM 大小(最大 800KB)
ls -la contract.wasm
# 如果超过 800KB,使用 wasm-opt 优化

# 3. 确保 minimum-gas-prices 配置正确
cat ~/.msgd/config/app.toml | grep minimum-gas-prices
# 应该输出: minimum-gas-prices = "1000000000attoMSG"

# 4. 检查账户余额是否足够
./build/msgd query bank balances $(./build/msgd keys show validator -a --keyring-backend test)

# 5. 增加 gas 配额
./build/msgd tx wasm store contract.wasm \
  --from validator \
  --gas 5000000 \
  --gas-prices 1000000000attoMSG \
  --chain-id msg-chain-1

# 6. 检查 wasm 合约是否有入口点
# CosmWasm 合约必须包含 #[entry_point] 标记的 instantiate/execute/query 函数

8.3 交易失败

现象: 交易广播成功但执行失败(code != 0)

解决方案:

# 1. 查看交易日志
./build/msgd query tx <tx-hash> | jq '.raw_log'

# 常见错误消息:
# - "out of gas" → 增加 --gas-adjustment 或直接指定 gas
# - "insufficient funds" → 检查余额
# - "unauthorized" → 检查权限(可能需要特定角色)
# - "contract not found" → 检查合约地址

# 2. 检查 Chain ID 是否正确
./build/msgd tx ... --chain-id msg-chain-1

# 3. 检查 Gas 价格是否高于最小值
# 默认最小值是 1000000000attoMSG,如果指定更低的价格会被拒绝

# 4. 确认 nonce 正确(等待前一笔交易确认)
# 对于顺序交易,确保前一笔已完成

8.4 Keplr 无法连接

现象: 钱包无法添加 MSG Chain

解决方案:

# 1. 确认 Keplr 已安装
# 访问 chrome://extensions/ 检查 Keplr

# 2. 确认 RPC/REST 端点可访问
curl http://localhost:26657/status
curl http://localhost:1317/cosmos/base/tendermint/v1beta1/node_info

# 3. 确认 CORS 配置正确
# 检查 config.toml:
# cors_allowed_origins = ["*"]
# cors_allowed_methods = ["HEAD", "GET", "POST", "PUT", "DELETE"]
# cors_allowed_headers = ["*"]

# 4. 重启节点使配置生效
killall msgd && ./build/msgd start

# 5. 尝试直接通过 Keplr API 添加
# 在浏览器控制台执行:
# await window.keplr.experimentalSuggestChain({
#   chainId: "msg-chain-1",
#   chainName: "MSG Chain",
#   rpc: "http://localhost:26657",
#   rest: "http://localhost:1317",
#   bip44: { coinType: 118 },
#   bech32Config: {
#     bech32PrefixAccAddr: "msg",
#     bech32PrefixAccPub: "msgpub",
#     bech32PrefixValAddr: "msgvaloper",
#     bech32PrefixValPub: "msgvaloperpub",
#     bech32PrefixConsAddr: "msgvalcons",
#     bech32PrefixConsPub: "msgvalconspub",
#   },
#   currencies: [{ coinDenom: "MSG", coinMinimalDenom: "umsg", coinDecimals: 18 }],
#   feeCurrencies: [{ coinDenom: "MSG", coinMinimalDenom: "umsg", coinDecimals: 18, gasPriceStep: { low: 0.01, average: 0.025, high: 0.04 } }],
#   stakeCurrency: { coinDenom: "MSG", coinMinimalDenom: "umsg", coinDecimals: 18 },
# });

8.5 Gas 相关错误

现象: out of gas in location: ... 或 gas estimate error

解决方案:

# 方法1:增加 gas 调整因子
--gas-adjustment 2.0

# 方法2:手动指定 gas 上限
--gas 10000000

# 方法3:提高 gas 价格
--gas-prices 1000000000attoMSG

# 方法4:检查合约大小(大合约需要更多 gas)
ls -lh contract.wasm

# 方法5:优化 WASM 文件
wasm-opt -Os -o optimized.wasm contract.wasm

8.6 数据目录管理

# 查看数据目录位置
echo $HOME/.msgd

# 查看数据大小
du -sh ~/.msgd/data/

# 查看配置
ls -la ~/.msgd/config/

# 完整重置测试网(谨慎!会清除所有区块数据)
./build/msgd unsafe-reset-all

# 备份密钥(从助记词恢复即可,私钥文件在)
cat ~/.msgd/config/priv_validator_key.json

# 备份节点密钥
cat ~/.msgd/config/node_key.json

8.7 Dilithium-5 问题

现象: 签名验证失败或密钥不匹配

解决方案:

# 1. 确认密钥是 Dilithium-5 类型
./build/msgd keys show validator -p --keyring-backend test
# 预期输出包含: @type: /cosmos.crypto.dilithium.PubKey

# 2. 检查应用配置
cat ~/.msgd/config/app.toml | grep -A5 "dilithium"
# 应该包含 dilithium 相关配置

# 3. 运行 PQ 测试验证
make test-quantum

# 4. 对于签名跨链验证
# 注意 Dilithium-5 签名不可与 ECDSA 互操作

8.8 CosmWasm 编译问题

现象: cargo build --target wasm32-unknown-unknown 失败

解决方案:

# 1. 确保 wasm32 target 已安装
rustup target list --installed | grep wasm32
rustup target add wasm32-unknown-unknown

# 2. 检查 Rust 版本
rustc --version
# 需要 Rust 1.75+

# 3. 清理缓存后重试
cargo clean
RUSTFLAGS='-C link-arg=-s' cargo build --release --target wasm32-unknown-unknown

# 4. 检查 Cargo.toml 中 cosmic-std 版本
# 必须使用 cosmwasm-std 1.x

# 5. 如果报错: "WASM binary size exceeds maximum"
# 使用 wasm-opt 优化:
wasm-opt -Os -o optimized.wasm target/wasm32-unknown-unknown/release/my_counter.wasm

# 6. 如果报错: "link-arg not supported"
# 确保使用 --target wasm32-unknown-unknown

8.9 常见端口冲突

默认端口 用途 配置文件
26656 P2P 通信 config.toml p2p.laddr
26657 RPC config.toml rpc.laddr
26660 Prometheus config.toml instrumentation.prometheus_listen_addr
1317 REST API app.toml api.address
9090 gRPC app.toml grpc.address
# 修改端口示例
sed -i 's/tc[未公开路径]' ~/.msgd/config/config.toml

九、完整开发工作流总结

9.1 10 分钟启动检查清单

☐ Go 1.21+ 已安装 (go version)
☐ Rust 1.75+ 已安装 (rustc --version)
☐ wasm32 target 已安装 (rustup target list --installed)
☐ Node.js 18+ 已安装 (node --version)
☐ MSG Chain 仓库已克隆 (git clone)
☐ make deps 完成
☐ make build-linux 成功
☐ ./build/msgd init --chain-id=msg-chain-1 完成
☐ 验证者账户已创建 (keys add)
☐ 创世账户已添加 (add-genesis-account)
☐ 验证者交易已创建 (gentx)
☐ 创世交易已收集 (collect-gentxs)
☐ 节点已启动 (msgd start)
☐ 节点同步中 (curl status)
☐ 合约已上传 (tx wasm store)
☐ 合约已实例化 (tx wasm instantiate)
☐ 合约已查询 (query wasm contract-state smart)

9.2 一条命令启动测试网

# 完全自动化的测试网初始化脚本
#!/bin/bash
set -e

echo "=== MSG Chain 测试网一键启动 ==="

MSG_CHAIN_HOME="$HOME/.msgd"
CHAIN_ID="msg-chain-1"

# 1. 清理旧数据
rm -rf "$MSG_CHAIN_HOME"
echo "[1/7] 旧数据已清理"

# 2. 初始化
./build/msgd init --chain-id=$CHAIN_ID
echo "[2/7] 节点已初始化"

# 3. 创建验证者
echo "y" | ./build/msgd keys add validator --keyring-backend test 2>/dev/null
VALIDATOR_ADDR=$(./build/msgd keys show validator -a --keyring-backend test)
echo "[3/7] 验证者账户: $VALIDATOR_ADDR"

# 4. 添加创世账户
./build/msgd add-genesis-account $VALIDATOR_ADDR 1000000000000000000umsg --keyring-backend test
echo "[4/7] 创世账户已添加"

# 5. 创建验证者交易
./build/msgd gentx validator 500000000000000000umsg \
  --chain-id=$CHAIN_ID \
  --keyring-backend test
echo "[5/7] 验证者交易已创建"

# 6. 收集创世交易
./build/msgd collect-gentxs
echo "[6/7] 创世交易已收集"

# 7. 配置 Gas 价格
sed -i 's/minimum-gas-prices = ""/minimum-gas-prices = "1000000000"/' "$MSG_CHAIN_HOME/config/app.toml"

# 8. 启动节点
echo "[7/7] 启动节点..."
./build/msgd start

9.3 常用链接

资源 链接
MSG Chain 官网 https://msgchain.org
白皮书 AI 入口 https://msgchain.org/whitepaper/modules/ai_control_plane.html
合约 Schema https://msgchain.org/whitepaper/contract_reference/contracts/{合约名}/
Agent API OpenAPI https://msgchain.org/whitepaper/api_specs/openapi/agent_surface.yaml
CosmWasm 文档 https://docs.cosmwasm.com
CosmJS 文档 https://cosmwasm.github.io/cosmjs
Keplr 文档 https://docs.keplr.app

本文档基于 MSG Chain 代码库核实的技术事实。
白皮书系统: https://msgchain.org/whitepaper/