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/
