AI Task L2 执行层接入指南
MSG Chain 去中心化 AI 任务计算层
文档版本: v0.1.0 (规划态)
状态:X-L2-Planning=true
⚠️ No-Go Disclaimer: MSGChain 主网裁决为 No-Go。本文件所有内容反映的是开发阶段的技术设计,不代表主网未独立核验上线状态。生产部署状态请以白皮书为准:https://msgchain.org/whitepaper/
目录
1. 概述
1.1 什么是 AI Task L2
AI Task L2 是 MSG Chain 的去中心化 AI 任务执行层,采用 L1 结算 + L2 执行 的双层架构设计(类似 Arbitrum L2 的结算模式与 Akash 的计算市场模型的结合)。其核心思想是:
- L1(MSG Chain 主链):负责任务结算、争议仲裁、治理决策、资金托管
- L2(AI Task 执行层):负责离线 AI 推理、工具调用、工作流编排等计算密集型任务
通过这种分离架构,AI 计算的执行成本不与 L1 区块空间竞争,同时 L1 的安全保证为计算结果提供最终确定性。
1.2 为什么需要 AI Task L2
| 需求 | L1 原生限制 | L2 方案优势 |
|---|---|---|
| AI 推理执行 | 链上 gas 成本极高,无法运行大模型 | 离线执行,仅上链承诺与证明 |
| 执行时间 | 受限于区块时间(5s) | 秒级到分钟级,无区块约束 |
| 计算资源 | 受限于验证者节点配置 | 可调度专用 GPU/TPU 节点 |
| 隐私保护 | 所有数据公开可见 | TEE/ZK 证明可验证隐私计算 |
| 任务规模 | 单交易大小有限 | 支持大型输入/输出(MB~GB 级) |
1.3 当前状态
Status: 规划态 (Planning Stage)
X-L2-Planning: true
已就绪基础组件:
├── Agent API 层 ── 未独立核验上线状态 (v1.0)
├── 交易收据系统 ── 已实现
├── 事件系统 ── 已实现
├── RPC 接口 ── 已实现
├── Agent 注册表 ── 已实现
├── 基金会金库 ── foundation_treasury_v2 (未独立核验上线状态)
├── DAO 治理 ── dao_governance_v1 (未独立核验上线状态)
├── AI Agent 宪法 ── ai_agent_constitution_v1 (未独立核验上线状态)
└── Agent Payment 支付 ── agent_payment_v1 (未独立核验上线状态)
待实现组件 (全部标记 X-L2-Planning=true):
├── TaskManager 合约 ── 规划中
├── ReceiptRegistry 合约 ── 规划中
├── DisputeResolver 合约 ── 规划中
├── Settlement 合约 ── 规划中
├── Off-chain Executor ── 规划中
├── Proof 证明系统 ── 规划中
└── L1 Anchor 锚定机制 ── 规划中
1.4 核心概念
- Task:描述一个 AI 任务的数据结构,包含模型引用、输入承诺、参数配置等
- Receipt:任务执行结果的收据,包含输出承诺、执行证明哈希、运行时哈希
- Proof:证明任务被正确执行的加密证据(ZK/SNARK/TEE 证明)
- Challenge:对任务执行结果的质疑,触发争议解决流程
- Settlement:任务完成后的最终结算,包括支付释放和状态最终化
- L1 Anchor:将 L2 状态根定期锚定到 L1 主链,提供最终确定性
2. 架构总览
2.1 系统架构
┌──────────────────────────────────────────────────────────────────┐
│ L1: MSG Chain 主链 │
│ │
│ ┌──────────────────┐ ┌──────────────┐ ┌────────────────────┐ │
│ │ Settlement 合约 │ │ Governance │ │ Treasury │ │
│ │ (Settlement) │ │ (DAO) │ │ (金库) │ │
│ │ X-L2-Planning │ │ deployed │ │ deployed │ │
│ └────────┬─────────┘ └──────────────┘ └────────────────────┘ │
│ │ │
│ ┌────────▼─────────┐ ┌──────────────┐ ┌────────────────────┐ │
│ │ TaskManager │ │ ReceiptReg │ │ DisputeResolver │ │
│ │ X-L2-Planning │ │ X-L2-Plan │ │ X-L2-Planning │ │
│ └────────┬─────────┘ └──────────────┘ └────────────────────┘ │
│ │ │
│ └──────────────┬────────────────┘ │
│ │ L1 Anchor │
└──────────────────────────┼────────────────────────────────────────┘
│
Bridge Layer (桥接层)
│
┌──────────────────────────┼────────────────────────────────────────┐
│ │ L2: AI Task 执行层 │
│ ┌──────────────────┐ │ │
│ │ Off-chain │◄───┘ │
│ │ Executor │ │
│ │ (X-L2-Planning) │ │
│ └────────┬─────────┘ │
│ │ │
│ ┌────────▼─────────┐ ┌──────────────┐ ┌────────────────────┐ │
│ │ Worker 节点池 │ │ Proof Gen │ │ TEE/Enclave │ │
│ │ (GPU/CPU) │ │ (ZK/TEE) │ │ 执行环境 │ │
│ └───────────────────┘ └──────────────┘ └────────────────────┘ │
│ │
│ ┌───────────────────┐ ┌──────────────┐ │
│ │ Task Scheduler │ │ Webhook │ │
│ │ (可选) │ │ Notifier │ │
│ └───────────────────┘ └──────────────┘ │
└──────────────────────────────────────────────────────────────────┘
2.2 核心流程
1. Submit Task ──► 2. Off-chain Execute ──► 3. Submit Receipt
│ │ │
▼ ▼ ▼
TaskManager Worker 节点 ReceiptRegistry
▲ ▲ │
│ │ ▼
8. L1 Anchor ◄── 7. Settle ◄──── 6. Verify ◄── 5. Challenge
│ │ │
▼ ▼ ▼
L1 Finality Settlement 合约 DisputeResolver
2.3 与 L1 现有合约的关系
AI Task L2 完全复用了 MSG Chain L1 现有基础设施:
| L1 组件 | 合约 | 用途 |
|---|---|---|
| DAO 治理 | dao_governance_v1 |
L2 合约升级提案、参数投票 |
| 基金会金库 | foundation_treasury_v2 |
Worker 奖励发放、Slashing 资金归集 |
| Agent 支付 | agent_payment_v1 |
基于里程碑的任务支付会话 |
| AI Agent 宪法 | ai_agent_constitution_v1 |
Worker 行为授权与合规检查 |
| Agent API | agent_v1 REST API |
任务提交、状态查询接口 |
2.4 设计原则
- 最小信任假设:L2 执行结果必须可通过 L1 验证,无需信任任何第三方
- 阶段性最终性:optimistic 验证 + 挑战窗口,类似 Arbitrum 的挑战期设计
- 模块化合约:每个功能模块独立合约,通过 Dispatch 消息通信
- 经济安全:Worker 需要质押(bond),恶意行为将被 slashing
- 渐进式去中心化:从单 Worker 验证逐步过渡到多 Worker 共识验证
3. Task 生命周期
3.1 Task 定义
一个 Task 在系统中的完整定义如下:
// === X-L2-Planning=true ===
// 文件: contracts/ai-task-l2/src/msg.rs
use cosmwasm_std::Addr;
use serde::{Deserialize, Serialize};
/// Task 状态枚举
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub enum TaskStatus {
Pending, // 等待 Worker 接单
Accepted, // 已被 Worker 接受
Executing, // 执行中
Completed, // 执行完成,Receipt 已提交
Challenged, // 被质疑
Disputed, // 争议处理中
Settled, // 已结算
Cancelled, // 已取消
Expired, // 已过期
}
/// Task 数据结构
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Task {
pub id: String, // 全局唯一 Task ID
pub task_type: String, // 任务类型 (inference/tool/orchestration)
pub creator: Addr, // 任务创建者
pub worker: Option<Addr>, // 接单 Worker
pub model_ref: String, // AI 模型引用 (model_id or model_hash)
pub model_hash: String, // 模型 SHA3-256 哈希 (输入承诺)
pub runtime_hash: String, // 运行时环境哈希
pub input_commitment: String, // 输入数据承诺 (SHA3-256)
pub output_commitment: Option<String>, // 输出数据承诺 (执行后设置)
pub params: TaskParams, // 执行参数
pub reward: String, // 奖励金额 (u128 string)
pub bond: String, // Worker 质押金额
pub deadline: u64, // 截止时间戳 (unix seconds)
pub challenge_window: u64, // 挑战窗口时长 (seconds)
pub status: TaskStatus, // 当前状态
pub created_at: u64, // 创建时间戳
pub updated_at: u64, // 最后更新时间戳
pub metadata: Option<String>, // 附加元数据 (JSON)
}
/// Task 执行参数
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct TaskParams {
pub max_gas: u64, // 最大 gas 消耗
pub max_timeout: u64, // 最大执行时间 (seconds)
pub input_format: String, // 输入格式 (json/text/binary)
pub output_format: String, // 输出格式
pub proof_required: bool, // 是否需要 ZK 证明
pub tee_required: bool, // 是否需要 TEE 执行
pub min_worker_reputation: u64, // 最低 Worker 信誉分
pub quorum_count: u64, // 共识验证数量 (0=单 Worker)
}
/// 收据数据结构
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Receipt {
pub task_id: String, // 对应 Task ID
pub worker: Addr, // 执行 Worker
pub output_commitment: String, // 输出承诺 (SHA3-256)
pub execution_proof: String, // 执行证明 (proof_hash)
pub runtime_hash: String, // 运行时哈希
pub output_uri: Option<String>, // 输出数据 URI (IPFS/Arweave)
pub gas_used: u64, // 实际 gas 消耗
pub status: String, // 执行状态 (success/partial/failed)
pub submitted_at: u64, // 提交时间戳
pub proof_level: String, // 证明级别 (none/hash/zk/tee)
}
/// 挑战数据结构
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Challenge {
pub id: String, // 挑战 ID
pub task_id: String, // 被质疑的 Task ID
pub challenger: Addr, // 挑战者
pub reason: String, // 质疑原因
pub proof_hash: String, // 反证哈希
pub status: ChallengeStatus, // 挑战状态
pub created_at: u64,
pub resolved_at: Option<u64>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub enum ChallengeStatus {
Open, // 等待响应
Responded, // Worker 已回应
Resolved, // 已解决
Expired, // 过期
}
3.2 Task 提交流程
Task 提交可以通过两种方式:
方式 A:通过 L1 CosmWasm 合约提交
// === X-L2-Planning=true ===
// 合约提交 Task 的 ExecuteMsg
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum ExecuteMsg {
SubmitTask {
task: Task,
deposit: String, // 押金 + 奖励
},
AcceptTask {
task_id: String,
bond: String, // Worker 质押
},
SubmitReceipt {
task_id: String,
receipt: Receipt,
},
ChallengeTask {
task_id: String,
reason: String,
deposit: String, // 挑战押金
},
RespondChallenge {
task_id: String,
challenge_id: String,
evidence: String, // 反证数据哈希
},
SettleTask {
task_id: String,
},
CancelTask {
task_id: String,
},
}
方式 B:通过 Agent API 提交(建议)
利用未独立核验上线状态的 Agent API 接口提交任务:
// Agent API Task 提交示例
// POST /agent/v1/work/tasks/offer
const taskOfferPayload = {
work_id: "task-001",
call_chain_id: "ai-l2-call-chain-001",
capability_ref: "ai-inference-v1",
task_ref: "llm-inference-task",
service_terms_hash: "abc123...",
price_asset: "uom",
price_amount: "1000000",
budget_id: "budget-001",
escrow_id: "escrow-001",
escrow_lock_hash: "def456...",
provider_requirements_hash: "ghi789...",
metadata_hash: "jkl012..."
};
// 实际请求
const response = await fetch("https://node.msgchain.io/agent/v1/work/tasks/offer", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "your-api-key"
},
body: JSON.stringify(taskOfferPayload)
});
3.3 Task 状态机
┌──────────┐
│ Pending │◄──── SubmitTask
└────┬─────┘
│ AcceptTask
▼
┌──────────┐
┌───►│ Accepted │
│ └────┬─────┘
│ │ Worker 开始执行
│ ▼
│ ┌───────────┐
│ │ Executing │
│ └────┬──────┘
│ │ SubmitReceipt
│ ▼
│ ┌───────────┐
│ │ Completed │
│ └────┬──────┘
│ │
┌────┴────┐ │
│ │ │
▼ │ ▼
┌─────────┐ │ ┌─────────┐
│Expired │ │ │Settled │◄── Final
└─────────┘ │ └─────────┘
│
┌────┘
▼
┌───────────┐
│Challenged │
└─────┬─────┘
│ RespondChallenge
▼
┌──────────┐
│ Disputed │
└─────┬────┘
│ Resolve
▼
┌──────────┐
│ Settled │── 或 ──► Slashed
└──────────┘
3.4 完整生命周期示例
// === X-L2-Planning=true ===
// Task 完整生命周期 (TypeScript)
interface TaskLifecycleExample {
// 1. 创建 Task
async function createAndExecuteTask(): Promise<void> {
// Step 1: 提交 Task
const taskId = await submitTask({
modelRef: "gpt4-model-v1",
modelHash: sha256(input),
inputCommitment: sha256(inputData),
reward: "1000000uom",
challengeWindow: 86400, // 24h
});
// Step 2: 查询 Task 状态
let status = await queryTaskStatus(taskId);
console.log("Task status:", status); // Pending
// Step 3: Worker 接单 (由 Worker 节点调用)
await acceptTask(taskId, { bond: "500000uom" });
// Step 4: 获取输入数据 (从 IPFS/链上)
const input = await fetchTaskInput(taskId);
// Step 5: 执行 AI 推理 (off-chain)
const output = await runInference(input);
// Step 6: 提交 Receipt
await submitReceipt(taskId, {
outputCommitment: sha256(output),
executionProof: generateProof(output),
runtimeHash: runtimeEnvHash(),
gasUsed: computeGasCost(),
proofLevel: "tee",
});
// Step 7: 等待挑战窗口结束 (无挑战则自动结算)
await waitForChallengeWindow(taskId);
// Step 8: 结算
await settleTask(taskId);
// Step 9: 查询最终状态
const finalStatus = await queryTaskStatus(taskId); // Settled
console.log("Final status:", finalStatus);
}
}
4. Task 合约设计
4.1 合约架构
CosmWasm 合约部署架构:
L1 MSG Chain
│
├── TaskManager.wasm [X-L2-Planning=true]
│ ├── 状态: Task 存储
│ ├── Execute: submit/accept/cancel
│ └── Query: get_task/list_tasks
│
├── ReceiptRegistry.wasm [X-L2-Planning=true]
│ ├── 状态: Receipt 存储
│ ├── Execute: submit_receipt
│ └── Query: get_receipt/list_receipts
│
├── DisputeResolver.wasm [X-L2-Planning=true]
│ ├── 状态: Challenge/Dispute 存储
│ ├── Execute: challenge/respond/resolve
│ └── Query: get_challenge
│
├── Settlement.wasm [X-L2-Planning=true]
│ ├── 状态: Settlement 记录
│ ├── Execute: settle/claim
│ └── Query: get_settlement
│
├── dao_governance_v1.wasm [未独立核验上线状态]
│ └── 合约升级提案 / 参数治理
│
├── foundation_treasury_v2.wasm [未独立核验上线状态]
│ └── 奖励分发 / Slashing 归集
│
└── ai_agent_constitution_v1.wasm [未独立核验上线状态]
└── Worker 行为授权检查
4.2 TaskManager 合约
// === X-L2-Planning=true ===
// 文件: contracts/ai-task-l2/src/contract.rs
use cosmwasm_std::{
entry_point, to_json_binary, Addr, Binary, Coin, Deps, DepsMut, Env,
MessageInfo, Order, Response, StdResult, Storage,
};
use cw_storage_plus::{Item, Map};
use crate::error::ContractError;
use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg, TaskStatus};
use crate::state::{Config, Task};
// === 状态存储 ===
pub const CONFIG: Item<Config> = Item::new("config");
pub const TASKS: Map<&str, Task> = Map::new("tasks");
pub const TASK_COUNT: Item<u64> = Item::new("task_count");
// === 实例化 ===
#[entry_point]
pub fn instantiate(
deps: DepsMut,
_env: Env,
info: MessageInfo,
msg: InstantiateMsg,
) -> StdResult<Response> {
let config = Config {
admin: info.sender,
treasury_contract: deps.api.addr_validate(&msg.treasury_contract)?,
governance_contract: deps.api.addr_validate(&msg.governance_contract)?,
min_bond: msg.min_bond,
max_challenge_window: msg.max_challenge_window,
protocol_fee_percent: msg.protocol_fee_percent,
paused: false,
};
CONFIG.save(deps.storage, &config)?;
TASK_COUNT.save(deps.storage, &0u64)?;
Ok(Response::new()
.add_attribute("method", "instantiate")
.add_attribute("admin", info.sender))
}
// === 执行接口 ===
#[entry_point]
pub fn execute(
deps: DepsMut,
env: Env,
info: MessageInfo,
msg: ExecuteMsg,
) -> Result<Response, ContractError> {
match msg {
ExecuteMsg::SubmitTask { task, deposit } => {
execute_submit_task(deps, env, info, task, deposit)
}
ExecuteMsg::AcceptTask { task_id, bond } => {
execute_accept_task(deps, env, info, task_id, bond)
}
ExecuteMsg::SubmitReceipt { task_id, receipt } => {
execute_submit_receipt(deps, env, info, task_id, receipt)
}
ExecuteMsg::ChallengeTask { task_id, reason, deposit } => {
execute_challenge_task(deps, env, info, task_id, reason, deposit)
}
ExecuteMsg::RespondChallenge { task_id, challenge_id, evidence } => {
execute_respond_challenge(deps, env, info, task_id, challenge_id, evidence)
}
ExecuteMsg::SettleTask { task_id } => {
execute_settle_task(deps, env, info, task_id)
}
ExecuteMsg::CancelTask { task_id } => {
execute_cancel_task(deps, env, info, task_id)
}
}
}
// === 查询接口 ===
#[entry_point]
pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
match msg {
QueryMsg::GetTask { task_id } => {
to_json_binary(&query_task(deps, task_id)?)
}
QueryMsg::ListTasks { start_after, limit } => {
to_json_binary(&query_list_tasks(deps, start_after, limit)?)
}
QueryMsg::GetConfig {} => {
to_json_binary(&CONFIG.load(deps.storage)?)
}
QueryMsg::GetTaskCount {} => {
to_json_binary(&TASK_COUNT.load(deps.storage)?)
}
QueryMsg::ListTasksByStatus { status, start_after, limit } => {
to_json_binary(&query_tasks_by_status(deps, status, start_after, limit)?)
}
}
}
4.3 TaskManager 核心逻辑
// === X-L2-Planning=true ===
// 文件: contracts/ai-task-l2/src/execution.rs
use cosmwasm_std::{Coin, DepsMut, Env, MessageInfo, Response, Storage, Uint128};
use crate::error::ContractError;
use crate::state::{Config, Task, TaskStatus, Receipt, Challenge, ChallengeStatus};
use crate::contract::{CONFIG, TASKS, TASK_COUNT};
/// 提交 Task
pub fn execute_submit_task(
deps: DepsMut,
env: Env,
info: MessageInfo,
task: Task,
deposit: Coin,
) -> Result<Response, ContractError> {
let config = CONFIG.load(deps.storage)?;
if config.paused {
return Err(ContractError::ContractPaused {});
}
// 验证押金
let required_amount = task.reward.parse::<Uint128>()
.map_err(|_| ContractError::InvalidAmount)?;
if deposit.amount < required_amount {
return Err(ContractError::InsufficientDeposit {});
}
// 生成 Task ID
let count = TASK_COUNT.load(deps.storage)?;
let task_id = format!("task-{}", count + 1);
let new_task = Task {
id: task_id.clone(),
task_type: task.task_type,
creator: info.sender.clone(),
worker: None,
model_ref: task.model_ref,
model_hash: task.model_hash,
runtime_hash: task.runtime_hash,
input_commitment: task.input_commitment,
output_commitment: None,
params: task.params,
reward: task.reward,
bond: task.bond,
deadline: env.block.time.seconds() + 3600, // 1h deadline
challenge_window: task.challenge_window,
status: TaskStatus::Pending,
created_at: env.block.time.seconds(),
updated_at: env.block.time.seconds(),
metadata: task.metadata,
};
TASKS.save(deps.storage, &task_id, &new_task)?;
TASK_COUNT.save(deps.storage, &(count + 1))?;
Ok(Response::new()
.add_attribute("action", "submit_task")
.add_attribute("task_id", &task_id)
.add_attribute("creator", info.sender)
.add_attribute("reward", &task.reward))
}
/// Worker 接单
pub fn execute_accept_task(
deps: DepsMut,
env: Env,
info: MessageInfo,
task_id: String,
bond: Coin,
) -> Result<Response, ContractError> {
let config = CONFIG.load(deps.storage)?;
let mut task = TASKS.load(deps.storage, &task_id)?;
if task.status != TaskStatus::Pending {
return Err(ContractError::InvalidStatus {});
}
if env.block.time.seconds() > task.deadline {
task.status = TaskStatus::Expired;
TASKS.save(deps.storage, &task_id, &task)?;
return Err(ContractError::TaskExpired {});
}
let min_bond = Uint128::from(config.min_bond);
if bond.amount < min_bond {
return Err(ContractError::InsufficientBond {});
}
task.worker = Some(info.sender.clone());
task.status = TaskStatus::Accepted;
task.updated_at = env.block.time.seconds();
TASKS.save(deps.storage, &task_id, &task)?;
Ok(Response::new()
.add_attribute("action", "accept_task")
.add_attribute("task_id", &task_id)
.add_attribute("worker", info.sender))
}
/// 提交 Receipt
pub fn execute_submit_receipt(
deps: DepsMut,
env: Env,
info: MessageInfo,
task_id: String,
receipt: Receipt,
) -> Result<Response, ContractError> {
let mut task = TASKS.load(deps.storage, &task_id)?;
if task.status != TaskStatus::Accepted
&& task.status != TaskStatus::Executing
{
return Err(ContractError::InvalidStatus {});
}
if task.worker.as_ref() != Some(&info.sender) {
return Err(ContractError::Unauthorized {});
}
task.output_commitment = Some(receipt.output_commitment.clone());
task.status = TaskStatus::Completed;
task.updated_at = env.block.time.seconds();
TASKS.save(deps.storage, &task_id, &task)?;
// 存储 Receipt
RECEIPTS.save(deps.storage, &task_id, &receipt)?;
Ok(Response::new()
.add_attribute("action", "submit_receipt")
.add_attribute("task_id", &task_id)
.add_attribute("worker", info.sender))
}
4.4 查询接口定义
// === X-L2-Planning=true ===
// 文件: contracts/ai-task-l2/src/msg.rs
use cosmwasm_std::Addr;
use serde::{Deserialize, Serialize};
use crate::state::{Receipt, Challenge, Task};
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct InstantiateMsg {
pub treasury_contract: String,
pub governance_contract: String,
pub min_bond: u128,
pub max_challenge_window: u64,
pub protocol_fee_percent: u64,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum ExecuteMsg {
SubmitTask {
task: Task,
deposit: Coin,
},
AcceptTask {
task_id: String,
bond: Coin,
},
SubmitReceipt {
task_id: String,
receipt: Receipt,
},
ChallengeTask {
task_id: String,
reason: String,
deposit: Coin,
},
RespondChallenge {
task_id: String,
challenge_id: String,
evidence: String,
},
SettleTask {
task_id: String,
},
CancelTask {
task_id: String,
},
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum QueryMsg {
GetTask {
task_id: String,
},
ListTasks {
start_after: Option<String>,
limit: Option<u32>,
},
GetConfig {},
GetTaskCount {},
ListTasksByStatus {
status: String,
start_after: Option<String>,
limit: Option<u32>,
},
GetReceipt {
task_id: String,
},
GetChallenge {
challenge_id: String,
},
}
4.5 DisputeResolver 合约
// === X-L2-Planning=true ===
// 争议解决合约核心逻辑
/// 发起挑战
pub fn execute_challenge(
deps: DepsMut,
env: Env,
info: MessageInfo,
task_id: String,
reason: String,
deposit: Coin,
) -> Result<Response, ContractError> {
let config = CONFIG.load(deps.storage)?;
let task = TASKS.load(deps.storage, &task_id)?;
// 仅在 Completed 状态才能被挑战
if task.status != TaskStatus::Completed {
return Err(ContractError::InvalidStatus {});
}
// 检查是否在挑战窗口内
let challenge_deadline = task.receipt_submitted_at + task.challenge_window;
if env.block.time.seconds() > challenge_deadline {
return Err(ContractError::ChallengeWindowExpired {});
}
// 验证挑战押金 (押金 = task奖励 * 挑战费率)
let challenge_fee = Uint128::from(config.challenge_fee_percent)
* task_reward(task) / Uint128::new(100);
if deposit.amount < challenge_fee {
return Err(ContractError::InsufficientChallengeDeposit {});
}
let challenge_id = format!("challenge-{}", task_id);
let challenge = Challenge {
id: challenge_id.clone(),
task_id: task_id.clone(),
challenger: info.sender.clone(),
reason,
proof_hash: String::new(),
status: ChallengeStatus::Open,
created_at: env.block.time.seconds(),
resolved_at: None,
};
CHALLENGES.save(deps.storage, &challenge_id, &challenge)?;
let mut task = task.clone();
task.status = TaskStatus::Challenged;
TASKS.save(deps.storage, &task_id, &task)?;
Ok(Response::new()
.add_attribute("action", "challenge_task")
.add_attribute("task_id", &task_id)
.add_attribute("challenge_id", &challenge_id)
.add_attribute("challenger", info.sender))
}
/// 裁决争议
pub fn execute_resolve_dispute(
deps: DepsMut,
env: Env,
info: MessageInfo,
task_id: String,
challenge_id: String,
verdict: Verdict,
) -> Result<Response, ContractError> {
let config = CONFIG.load(deps.storage)?;
// 仅允许 DAO / 仲裁者 调用
if info.sender != config.arbitrator {
return Err(ContractError::Unauthorized {});
}
let mut challenge = CHALLENGES.load(deps.storage, &challenge_id)?;
let mut task = TASKS.load(deps.storage, &task_id)?;
challenge.status = ChallengeStatus::Resolved;
challenge.resolved_at = Some(env.block.time.seconds());
CHALLENGES.save(deps.storage, &challenge_id, &challenge)?;
match verdict {
Verdict::WorkerValid => {
task.status = TaskStatus::Completed;
// 返还挑战者押金给 Worker (惩罚恶意挑战)
// Worker 获得奖励
}
Verdict::ChallengerValid => {
task.status = TaskStatus::Disputed;
// Slash Worker 质押
// 奖励挑战者
}
Verdict::Split => {
task.status = TaskStatus::Settled;
// 按比例分配
}
}
TASKS.save(deps.storage, &task_id, &task)?;
Ok(Response::new()
.add_attribute("action", "resolve_dispute")
.add_attribute("task_id", &task_id)
.add_attribute("verdict", format!("{:?}", verdict)))
}
4.6 Settlement 合约
// === X-L2-Planning=true ===
// 结算合约核心逻辑
/// 结算 Task (挑战窗口过期后)
pub fn execute_settle(
deps: DepsMut,
env: Env,
info: MessageInfo,
task_id: String,
) -> Result<Response, ContractError> {
let config = CONFIG.load(deps.storage)?;
let mut task = TASKS.load(deps.storage, &task_id)?;
match task.status {
TaskStatus::Completed => {
// 检查挑战窗口是否已过
let settle_time = task.receipt_submitted_at + task.challenge_window;
if env.block.time.seconds() < settle_time {
return Err(ContractError::ChallengeWindowNotExpired {});
}
}
TaskStatus::Challenged | TaskStatus::Disputed => {
// 等待仲裁结果
return Err(ContractError::DisputeInProgress {});
}
_ => return Err(ContractError::InvalidStatus {}),
}
// 计算费用
let reward_amount = Uint128::from_str(&task.reward)?;
let protocol_fee = reward_amount * Uint128::from(config.protocol_fee_percent) / Uint128::new(100);
let worker_payment = reward_amount - protocol_fee;
// 转移资金:
// 1. Protocol fee -> Treasury
// 2. Worker payment -> Worker
// 3. Creator deposit -> unlock remaining
task.status = TaskStatus::Settled;
TASKS.save(deps.storage, &task_id, &task)?;
Ok(Response::new()
.add_attribute("action", "settle_task")
.add_attribute("task_id", &task_id)
.add_attribute("worker_payment", &worker_payment.to_string())
.add_attribute("protocol_fee", &protocol_fee.to_string()))
}
4.7 合约部署流程
# === X-L2-Planning=true ===
# 部署流程 (规划)
# 1. 编译合约
cd contracts/ai-task-l2
cargo wasm
docker run --rm -v "$(pwd)":/code \
--mount type=volume,source="$(basename "$(pwd)")_cache",target=/target \
--mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
cosmwasm/rust-optimizer:0.15.0
# 2. 上传 WASM 到 MSG Chain
msgchain tx wasm store artifacts/ai_task_l2.wasm \
--from admin --gas auto --gas-adjustment 1.3 \
--chain-id msg-chain-1
# 3. 实例化合约
msgchain tx wasm instantiate <CODE_ID> \
'{
"treasury_contract": "msg1treasury...",
"governance_contract": "msg1governance...",
"min_bond": "500000000",
"max_challenge_window": 86400,
"protocol_fee_percent": 5
}' \
--label "ai-task-l2-manager" \
--admin msg1admin... \
--from admin --chain-id msg-chain-1
# 4. 查询合约
msgchain query wasm contract-state smart <CONTRACT_ADDR> \
'{"get_config":{}}'
5. Off-chain Executor
5.1 架构设计
Off-chain Executor 是 AI Task L2 的执行引擎,负责:
- 监听 L1 上的 Task 事件
- 调度 Worker 节点执行任务
- 收集执行结果并生成 Receipt
- 将 Receipt 提交回 L1
- 通过 Webhook 通知任务完成
┌─────────────────────────────────────────────────────────┐
│ Off-chain Executor │
│ │
│ ┌────────────────────┐ ┌──────────────────────────┐ │
│ │ Event Watcher │ │ Task Scheduler │ │
│ │ (监听 L1 事件) │──►│ (任务调度队列) │ │
│ └────────────────────┘ └───────────┬──────────────┘ │
│ │ │
│ ┌────────────────────┐ ┌───────────▼──────────────┐ │
│ │ Result Collector │◄──│ Worker Pool │ │
│ │ (收集执行结果) │ │ (GPU/CPU 节点) │ │
│ └────────────────────┘ └──────────────────────────┘ │
│ │ │
│ ┌────────────────────┐ ┌───────────▼──────────────┐ │
│ │ Receipt Submit │ │ Webhook Notifier │ │
│ │ (提交收据到 L1) │ │ (回调通知) │ │
│ └────────────────────┘ └──────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
5.2 Executor 核心实现
// === X-L2-Planning=true ===
// 文件: executor/src/index.ts
import { EventEmitter } from "events";
import { CosmWasmClient, SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate";
import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";
import { calculateFee, GasPrice } from "@cosmjs/stargate";
// === 类型定义 ===
interface TaskOffer {
workId: string;
callChainId: string;
capabilityRef: string;
taskRef: string;
serviceTermsHash: string;
priceAmount: string;
budgetId: string;
escrowId: string;
escrowLockHash: string;
}
interface ExecutionResult {
taskId: string;
output: string;
outputHash: string;
proofHash: string;
gasUsed: number;
status: "success" | "partial" | "failed";
}
interface ExecutorConfig {
chainId: string;
rpcEndpoint: string;
mnemonic: string;
contractAddress: string;
gasPrice: string;
workerId: string;
maxConcurrent: number;
pollInterval: number;
webhookUrl?: string;
}
// === Executor 主类 ===
export class AIExecutor extends EventEmitter {
private client!: CosmWasmClient;
private signingClient!: SigningCosmWasmClient;
private config: ExecutorConfig;
private activeTasks: Map<string, AbortController> = new Map();
private running = false;
constructor(config: ExecutorConfig) {
super();
this.config = config;
}
// === 初始化 ===
async initialize(): Promise<void> {
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(
this.config.mnemonic,
{ prefix: "msg" }
);
this.client = await CosmWasmClient.connect(this.config.rpcEndpoint);
const gasPrice = GasPrice.fromString(this.config.gasPrice);
this.signingClient = await SigningCosmWasmClient.connectWithSigner(
this.config.rpcEndpoint,
wallet,
{ gasPrice }
);
console.log(`[Executor] Initialized worker: ${this.config.workerId}`);
console.log(`[Executor] Chain ID: ${this.config.chainId}`);
console.log(`[Executor] Contract: ${this.config.contractAddress}`);
}
// === 启动监听 ===
async start(): Promise<void> {
this.running = true;
console.log("[Executor] Starting event watcher...");
this.pollTasks();
}
async stop(): Promise<void> {
this.running = false;
for (const [taskId, controller] of this.activeTasks) {
controller.abort();
}
this.activeTasks.clear();
console.log("[Executor] Stopped.");
}
// === 轮询待处理任务 ===
private async pollTasks(): Promise<void> {
while (this.running) {
try {
const pendingTasks = await this.queryPendingTasks();
for (const task of pendingTasks) {
if (this.activeTasks.size >= this.config.maxConcurrent) {
break;
}
if (!this.activeTasks.has(task.workId)) {
this.executeTask(task).catch((err) => {
console.error(`[Executor] Task ${task.workId} failed:`, err);
});
}
}
} catch (err) {
console.error("[Executor] Poll error:", err);
}
await new Promise((resolve) =>
setTimeout(resolve, this.config.pollInterval)
);
}
}
// === 查询待处理任务 (通过 Agent API) ===
private async queryPendingTasks(): Promise<TaskOffer[]> {
// 使用未独立核验上线状态的 Agent API 查询待处理任务
const response = await fetch(
`${this.config.rpcEndpoint}/agent/v1/work/tasks/offer`,
{
method: "GET",
headers: { "X-API-Key": process.env.AGENT_API_KEY || "" },
}
);
const data = await response.json();
return data.data?.pending_tasks || [];
}
// === 执行单个 Task ===
private async executeTask(task: TaskOffer): Promise<void> {
const controller = new AbortController();
this.activeTasks.set(task.workId, controller);
try {
console.log(`[Executor] Accepting task: ${task.workId}`);
// Step 1: 接受任务 (通过 Agent API)
await this.acceptTask(task);
// Step 2: 执行 AI 推理
console.log(`[Executor] Executing task: ${task.workId}`);
const result = await this.runInference(task, controller.signal);
// Step 3: 生成证明
const proof = await this.generateExecutionProof(result);
// Step 4: 提交收据
console.log(`[Executor] Submitting receipt for: ${task.workId}`);
await this.submitReceipt(task.workId, result, proof);
// Step 5: 通知回调
if (this.config.webhookUrl) {
await this.notifyWebhook(task.workId, result);
}
console.log(`[Executor] Task completed: ${task.workId}`);
this.emit("taskCompleted", { taskId: task.workId, result });
} catch (err: any) {
if (err.name === "AbortError") {
console.log(`[Executor] Task cancelled: ${task.workId}`);
} else {
console.error(`[Executor] Task error: ${task.workId}:`, err);
this.emit("taskFailed", { taskId: task.workId, error: err.message });
}
} finally {
this.activeTasks.delete(task.workId);
}
}
// === 接受任务 (复用 Agent API) ===
private async acceptTask(task: TaskOffer): Promise<void> {
const response = await fetch(
`${this.config.rpcEndpoint}/agent/v1/work/tasks/${task.workId}/accept`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": process.env.AGENT_API_KEY || "",
},
body: JSON.stringify({
provider_agent: this.config.workerId,
provider_owner: process.env.WALLET_ADDRESS,
acceptance_hash: crypto.createHash("sha256")
.update(task.workId + Date.now())
.digest("hex"),
capability_proof_hash: task.serviceTermsHash,
}),
}
);
if (!response.ok) {
throw new Error(`Accept task failed: ${response.statusText}`);
}
}
// === AI 推理执行 (使用现有的 Agent Sandbox API) ===
private async runInference(
task: TaskOffer,
signal: AbortSignal
): Promise<ExecutionResult> {
// TODO: 实现实际的 AI 推理逻辑
// 可使用现有的 agent_sandbox_api 沙箱执行环境
// 或调用外部 AI 推理 API
const input = await this.fetchTaskInput(task.workId);
// const output = await aiModel.invoke(input, { signal });
const output = `mock-output-${task.workId}`;
const outputHash = crypto.createHash("sha256")
.update(output)
.digest("hex");
const proofHash = crypto.createHash("sha256")
.update(outputHash + this.config.workerId)
.digest("hex");
return {
taskId: task.workId,
output,
outputHash,
proofHash,
gasUsed: 100000,
status: "success",
};
}
// === 生成执行证明 ===
private async generateExecutionProof(
result: ExecutionResult
): Promise<string> {
// TODO: 实现实际证明生成
// 可支持: ZK/SNARK 证明, TEE 证明, 或简单的哈希承诺
return crypto.createHash("sha256")
.update(result.outputHash + result.taskId + Date.now())
.digest("hex");
}
// === 提交收据 (通过 Agent API) ===
private async submitReceipt(
taskId: string,
result: ExecutionResult,
proofHash: string
): Promise<void> {
const response = await fetch(
`${this.config.rpcEndpoint}/agent/v1/work/tasks/${taskId}/receipt`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": process.env.AGENT_API_KEY || "",
},
body: JSON.stringify({
provider_owner: process.env.WALLET_ADDRESS,
receipt_hash: result.outputHash,
output_hash: result.outputHash,
proof_hash: proofHash,
proof_level: "tee",
runtime_hash: crypto.createHash("sha256")
.update(this.config.workerId)
.digest("hex"),
status: result.status,
}),
}
);
if (!response.ok) {
throw new Error(`Submit receipt failed: ${response.statusText}`);
}
}
// === 获取任务输入 ===
private async fetchTaskInput(taskId: string): Promise<string> {
// TODO: 从 IPFS / L1 存储获取 Task 输入
return `mock-input-${taskId}`;
}
// === Webhook 回调通知 ===
private async notifyWebhook(
taskId: string,
result: ExecutionResult
): Promise<void> {
if (!this.config.webhookUrl) return;
await fetch(this.config.webhookUrl, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
event: "task.completed",
taskId,
outputHash: result.outputHash,
status: result.status,
timestamp: new Date().toISOString(),
}),
});
}
}
// === 启动入口 ===
async function main() {
const executor = new AIExecutor({
chainId: "msg-chain-1",
rpcEndpoint: process.env.RPC_ENDPOINT || "http://localhost:26657",
mnemonic: process.env.WORKER_MNEMONIC || "",
contractAddress: process.env.CONTRACT_ADDRESS || "",
gasPrice: "0.025uom",
workerId: process.env.WORKER_ID || "worker-1",
maxConcurrent: parseInt(process.env.MAX_CONCURRENT || "5"),
pollInterval: parseInt(process.env.POLL_INTERVAL || "5000"),
webhookUrl: process.env.WEBHOOK_URL,
});
await executor.initialize();
await executor.start();
// Graceful shutdown
process.on("SIGINT", async () => {
await executor.stop();
process.exit(0);
});
}
if (require.main === module) {
main().catch(console.error);
}
5.3 基于现有 Agent API 的集成
Executor 完全复用 MSG Chain 现有 Agent API 端点:
// === X-L2-Planning=true ===
// 文件: executor/src/agent-client.ts
/// Agent API 客户端 (复用未独立核验上线状态接口)
class AgentAPIClient {
private baseUrl: string;
private apiKey: string;
constructor(baseUrl: string, apiKey: string) {
this.baseUrl = baseUrl;
this.apiKey = apiKey;
}
private async request(method: string, path: string, body?: any) {
const response = await fetch(`${this.baseUrl}${path}`, {
method,
headers: {
"Content-Type": "application/json",
"X-API-Key": this.apiKey,
},
body: body ? JSON.stringify(body) : undefined,
});
return response.json();
}
// 未独立核验上线状态端点: 查询账户
async getAccount(address: string) {
return this.request("GET", `/agent/v1/query/account/${address}`);
}
// 未独立核验上线状态端点: 查询余额
async getBalance(address: string) {
return this.request("GET", `/agent/v1/query/balance/${address}`);
}
// 未独立核验上线状态端点: 查询交易
async getTx(txHash: string) {
return this.request("GET", `/agent/v1/query/tx/${txHash}`);
}
// 未独立核验上线状态端点: 查询区块
async getBlock(height: number) {
return this.request("GET", `/agent/v1/query/block/${height}`);
}
// 未独立核验上线状态端点: 事件历史
async getEvents(type: string, address?: string) {
const params = new URLSearchParams({ type });
if (address) params.append("address", address);
return this.request("GET", `/agent/v1/events/history?${params}`);
}
// 未独立核验上线状态端点: Oracle 价格
async getOraclePrice(token: string) {
return this.request("GET", `/agent/v1/oracle/price?token=${token}`);
}
// 未独立核验上线状态端点: Work 任务报价
async offerWork(payload: any) {
return this.request("POST", "/agent/v1/work/tasks/offer", payload);
}
// 未独立核验上线状态端点: 接受 Work 任务
async acceptWork(workId: string, payload: any) {
return this.request(
"POST",
`/agent/v1/work/tasks/${workId}/accept`,
payload
);
}
// 未独立核验上线状态端点: 提交 Work 收据
async submitWorkReceipt(workId: string, payload: any) {
return this.request(
"POST",
`/agent/v1/work/tasks/${workId}/receipt`,
payload
);
}
// 未独立核验上线状态端点: 结算 Work
async settleWork(workId: string, payload: any) {
return this.request(
"POST",
`/agent/v1/work/tasks/${workId}/settle`,
payload
);
}
// 未独立核验上线状态端点: 挑战 Work
async challengeWork(workId: string, payload: any) {
return this.request(
"POST",
`/agent/v1/work/tasks/${workId}/challenge`,
payload
);
}
// 未独立核验上线状态端点: 查询 Work 状态
async getWork(workId: string) {
return this.request("GET", `/agent/v1/work/tasks/${workId}`);
}
// 未独立核验上线状态端点: 查询 Work 追踪链
async getWorkTrace(callChainId: string) {
return this.request("GET", `/agent/v1/work/traces/${callChainId}`);
}
// 未独立核验上线状态端点: 注册 AI 模型
async registerModel(payload: any) {
return this.request("POST", "/agent/v1/models", payload);
}
// 未独立核验上线状态端点: 创建沙箱钱包
async createSandboxWallet(payload: any) {
return this.request("POST", "/agent/v1/sandbox/wallets/create", payload);
}
// 未独立核验上线状态端点: Payment 意图
async paymentIntent(payload: any) {
return this.request("POST", "/agent/v1/payments/intents", payload);
}
// 未独立核验上线状态端点: Payment 结算
async paymentSettle(paymentId: string, payload: any) {
return this.request(
"POST",
`/agent/v1/payments/${paymentId}/settle`,
payload
);
}
// 未独立核验上线状态端点: 查询 Worker 信誉
async getReputation(providerAgent: string) {
return this.request("GET", `/agent/v1/reputation/${providerAgent}`);
}
}
5.4 Task Scheduler
// === X-L2-Planning=true ===
// 文件: executor/src/scheduler.ts
interface SchedulerConfig {
maxRetries: number;
retryDelay: number;
workerBlacklistDuration: number;
}
class TaskScheduler {
private workers: Map<string, WorkerInfo> = new Map();
private queue: TaskOffer[] = [];
private blacklist: Map<string, number> = new Map();
private config: SchedulerConfig;
constructor(config: SchedulerConfig) {
this.config = config;
}
// 注册 Worker
registerWorker(workerId: string, capabilities: string[], score: number) {
this.workers.set(workerId, {
workerId,
capabilities,
score,
activeTasks: 0,
lastHeartbeat: Date.now(),
});
}
// 任务调度算法
scheduleTask(task: TaskOffer): string | null {
// 过滤: 有能力的、不在黑名单的、活跃任务最少的 Worker
const candidates = Array.from(this.workers.values())
.filter((w) => !this.blacklist.has(w.workerId))
.filter((w) => w.capabilities.includes(task.capabilityRef))
.sort((a, b) => a.activeTasks - b.activeTasks);
if (candidates.length === 0) return null;
// 选择负载最低的 Worker
const selected = candidates[0];
selected.activeTasks++;
return selected.workerId;
}
// Task 失败处理
handleTaskFailure(taskId: string, workerId: string) {
const worker = this.workers.get(workerId);
if (worker) {
worker.activeTasks = Math.max(0, worker.activeTasks - 1);
worker.score = Math.max(0, worker.score - 10);
}
// 加入黑名单
this.blacklist.set(
workerId,
Date.now() + this.config.workerBlacklistDuration
);
// 重新入队
const failedTask = this.queue.find((t) => t.workId === taskId);
if (failedTask && failedTask.retries < this.config.maxRetries) {
failedTask.retries++;
setTimeout(() => {
this.queue.push(failedTask);
}, this.config.retryDelay);
}
}
}
6. 证明与验证
6.1 证明系统概览
证明系统确保 L2 执行结果可在 L1 上验证。支持以下证明类型:
| 证明级别 | 安全性 | 成本 | 适用场景 |
|---|---|---|---|
none |
低 (信任假设) | 无 | 测试、低价值任务 |
hash |
中 (output commitment) | 低 | 常规 AI 推理 |
tee |
高 (硬件信任根) | 中 | 隐私计算、高价值任务 |
zk |
最高 (密码学证明) | 高 | 金融计算、跨链验证 |
quorum |
高 (多 Worker 共识) | 中 | 关键决策、高频任务 |
6.2 Output Commitment 方案
Task 执行结果的承诺链:
input_data ──SHA3-256──► input_commitment
│
model_hash + runtime_hash
│
┌───────────┴────────────┐
│ AI 推理执行 │
└───────────┬────────────┘
│
output_data ──SHA3-256──► output_commitment
│
+ execution_context (worker_id, timestamp, nonce)
│
──SHA3-256──► receipt_hash
│
+ proof_data (TEE quote / ZK proof / quorum sig)
│
──SHA3-256──► proof_commitment
// === X-L2-Planning=true ===
// 承诺生成逻辑
import { createHash, randomBytes } from "crypto";
interface CommitmentChain {
inputCommitment: string;
outputCommitment: string;
receiptHash: string;
proofCommitment: string;
}
function generateCommitmentChain(
input: Buffer,
output: Buffer,
modelHash: string,
runtimeHash: string,
workerId: string,
nonce: string = randomBytes(16).toString("hex")
): CommitmentChain {
const inputCommitment = createHash("sha256").update(input).digest("hex");
const outputCommitment = createHash("sha256").update(output).digest("hex");
const receiptPayload = [
outputCommitment,
modelHash,
runtimeHash,
workerId,
nonce,
].join("|");
const receiptHash = createHash("sha256")
.update(receiptPayload)
.digest("hex");
const proofPayload = [
receiptHash,
workerId,
nonce,
].join("|");
const proofCommitment = createHash("sha256")
.update(proofPayload)
.digest("hex");
return { inputCommitment, outputCommitment, receiptHash, proofCommitment };
}
6.3 执行证明类型 (TypeScript)
// === X-L2-Planning=true ===
// 执行证明类型定义
/// TEE 证明 (基于 Intel SGX / AMD SEV)
interface TEEProof {
proofType: "tee";
teePlatform: "intel-sgx" | "amd-sev" | "arm-cca";
quote: string; // TEE 远程证明 Quote
enclaveHash: string; // Enclave 测量值 (MRENCLAVE)
signerHash: string; // 签名者哈希 (MRSIGNER)
reportData: string; // 报告数据 (包含 output_commitment)
timestamp: number;
}
/// ZK 证明 (基于 zkSNARK / zkSTARK)
interface ZKProof {
proofType: "zk";
zkScheme: "groth16" | "plonk" | "stark";
circuitHash: string; // 电路哈希
proof: string; // ZK 证明数据 (bytes)
publicInputs: string[]; // 公开输入
verificationKey: string; // 验证密钥哈希
}
/// 多 Worker 共识证明
interface QuorumProof {
proofType: "quorum";
quorumCount: number; // 参与 Worker 数量
threshold: number; // 共识阈值
signatures: WorkerSignature[];
consensusHash: string; // 共识结果哈希
}
interface WorkerSignature {
workerId: string;
signature: string; // 对 output_commitment 的签名
timestamp: number;
}
/// 统一证明类型
type ExecutionProof = TEEProof | ZKProof | QuorumProof;
/// 证明验证结果
interface VerificationResult {
valid: boolean;
verifiedAt: number;
verifier: string;
reason?: string;
}
6.4 验证策略
// === X-L2-Planning=true ===
// 验证器实现
class ProofVerifier {
/// 验证执行证明
async verifyProof(
task: Task,
receipt: Receipt,
proof: ExecutionProof
): Promise<VerificationResult> {
switch (proof.proofType) {
case "tee":
return this.verifyTEEProof(task, receipt, proof);
case "zk":
return this.verifyZKProof(task, receipt, proof);
case "quorum":
return this.verifyQuorumProof(task, receipt, proof);
default:
return {
valid: false,
verifiedAt: Date.now(),
verifier: "ai-task-l2",
reason: "unsupported_proof_type",
};
}
}
/// 验证 TEE 证明
private async verifyTEEProof(
task: Task,
receipt: Receipt,
proof: TEEProof
): Promise<VerificationResult> {
// 1. 验证 TEE Quote 签名链 (验证 Intel/AMD 证书链)
// 2. 验证 MRENCLAVE 匹配已知的受信任执行环境
// 3. 验证 report_data 包含正确的 output_commitment
// 4. 验证时间戳在有效窗口内
const reportData = proof.reportData;
const expectedData = receipt.outputCommitment + task.id;
if (reportData !== expectedData) {
return {
valid: false,
verifiedAt: Date.now(),
verifier: "ai-task-l2",
reason: "report_data_mismatch",
};
}
// TEE quote 验证逻辑 (占位)
const quoteValid = await this.verifyTEEQuote(proof.quote);
if (!quoteValid) {
return {
valid: false,
verifiedAt: Date.now(),
verifier: "ai-task-l2",
reason: "invalid_tee_quote",
};
}
return { valid: true, verifiedAt: Date.now(), verifier: "ai-task-l2" };
}
/// 验证 ZK 证明
private async verifyZKProof(
task: Task,
receipt: Receipt,
proof: ZKProof
): Promise<VerificationResult> {
// ZK 证明验证 (使用验证密钥和公开输入)
// publicInputs = [input_commitment, output_commitment, model_hash, runtime_hash]
const isValid = await this.verifyZKCircuit(
proof.circuitHash,
proof.proof,
proof.publicInputs,
proof.verificationKey
);
return {
valid: isValid,
verifiedAt: Date.now(),
verifier: "ai-task-l2",
reason: isValid ? undefined : "zk_proof_invalid",
};
}
/// 验证共识证明
private async verifyQuorumProof(
task: Task,
receipt: Receipt,
proof: QuorumProof
): Promise<VerificationResult> {
// 1. 验证签名 Worker 是否在注册表中
// 2. 验证签名数量 >= 阈值
// 3. 验证每个签名是否对应 output_commitment
// 4. 验证签名是否有效 (Worker 公钥)
if (proof.signatures.length < proof.threshold) {
return {
valid: false,
verifiedAt: Date.now(),
verifier: "ai-task-l2",
reason: "insufficient_signatures",
};
}
const validSigs = proof.signatures.filter((sig) =>
this.verifyWorkerSignature(
sig.workerId,
receipt.outputCommitment,
sig.signature
)
);
return {
valid: validSigs.length >= proof.threshold,
verifiedAt: Date.now(),
verifier: "ai-task-l2",
reason:
validSigs.length >= proof.threshold
? undefined
: "signature_verification_failed",
};
}
/// 验证 TEE Quote (占位)
private async verifyTEEQuote(quote: string): Promise<boolean> {
// TODO: 实现 Intel SGX / AMD SEV Quote 验证
return true;
}
/// 验证 ZK 电路 (占位)
private async verifyZKCircuit(
circuitHash: string,
proof: string,
publicInputs: string[],
verificationKey: string
): Promise<boolean> {
// TODO: 实现 ZK 证明验证
return true;
}
/// 验证 Worker 签名
private verifyWorkerSignature(
workerId: string,
message: string,
signature: string
): boolean {
// TODO: 使用 Worker 公钥验证签名
return true;
}
}
6.5 挑战与争议流程
挑战流程:
┌────────────┐
│ Task完成 │
└──────┬─────┘
│ 挑战窗口开启 (如 24h)
▼
┌────────────┐
│ 监控挑战事件 │◄── 任何人都可发起挑战
└──────┬─────┘
│
┌────────────┴────────────┐
│ │
▼ ▼
┌────────────────┐ ┌──────────────────┐
│ 无人挑战 │ │ 有人发起挑战 │
│ wait window │ │ deposit + reason │
└────────┬───────┘ └────────┬─────────┘
│ │
▼ ▼
┌────────────────┐ ┌──────────────────┐
│ Auto Settle │ │ Worker 回应机会 │
│ 释放奖励 │ │ (24h 回应窗口) │
└────────────────┘ └────────┬─────────┘
│
┌────────────┴────────────┐
│ │
▼ ▼
┌────────────────┐ ┌──────────────────┐
│ Worker 回应 │ │ Worker 未回应 │
│ 提交反证 │ │ 默认 Worker 有错 │
└────────┬───────┘ └────────┬─────────┘
│ │
▼ ▼
┌────────────────┐ ┌──────────────────┐
│ 仲裁 / DAO │ │ Slash Worker │
│ 判决 │ │ 奖励挑战者 │
└────────┬───────┘ └──────────────────┘
│
┌────────────┴────────────┐
│ │
▼ ▼
┌────────────────┐ ┌──────────────────┐
│ Worker 胜诉 │ │ 挑战者胜诉 │
│ 释放 Worker │ │ Slash Worker │
│ 惩罚挑战者 │ │ 奖励挑战者 │
└────────────────┘ └──────────────────┘
// === X-L2-Planning=true ===
// 挑战监控器
class ChallengeMonitor {
private client: CosmWasmClient;
private contractAddress: string;
private challengeWindow: number; // seconds
constructor(client: CosmWasmClient, contractAddress: string, challengeWindow: number) {
this.client = client;
this.contractAddress = contractAddress;
this.challengeWindow = challengeWindow;
}
/// 监听挑战事件
async watchChallenges(): Promise<void> {
const events = await this.client.getEvents(
this.contractAddress,
{ wasm: { action: "challenge_task" } },
0, // from block
Date.now() // to timestamp
);
for (const event of events) {
const taskId = event.attributes.find((a) => a.key === "task_id")?.value;
const challengeId = event.attributes.find(
(a) => a.key === "challenge_id"
)?.value;
if (taskId && challengeId) {
await this.handleChallenge(taskId, challengeId);
}
}
}
/// 处理挑战
private async handleChallenge(
taskId: string,
challengeId: string
): Promise<void> {
console.log(`[Challenge] Task ${taskId} challenged: ${challengeId}`);
// 启动挑战倒计时
setTimeout(async () => {
const deadline = await this.getResponseDeadline(taskId);
if (Date.now() > deadline) {
await this.resolveChallenge(taskId, challengeId);
}
}, this.challengeWindow * 1000);
}
/// 获取回应截止时间
private async getResponseDeadline(taskId: string): Promise<number> {
const task = await this.client.queryContractSmart(
this.contractAddress,
{ get_task: { task_id: taskId } }
);
return task.challenge_response_deadline;
}
/// 裁决挑战
private async resolveChallenge(
taskId: string,
challengeId: string
): Promise<void> {
// 如果 Worker 未在窗口内回应,自动裁决
// 发送 resolve 交易到 L1
console.log(`[Challenge] Resolving ${challengeId} for task ${taskId}`);
}
}
7. 经济模型
7.1 Task 定价模型
Task 总成本 = L1 Gas 费 + L2 计算费
L1 Gas 费 = SubmitTxGas + ReceiptTxGas + SettleTxGas
≈ 300,000 gas × 0.025 uom/gas = 7,500 uom
L2 计算费 = model_compute_cost × input_size_multiplier
+ storage_cost × output_size
+ proof_generation_cost
| 定价参数 | 说明 | 默认值 |
|---|---|---|
base_compute_price |
基础计算单价 | 100 uom/s |
input_multiplier |
输入大小倍率 | size_bytes / 1024 |
output_multiplier |
输出大小倍率 | size_bytes / 1024 |
proof_markup |
证明生成加成 | ZK: 500%, TEE: 100%, hash: 0% |
protocol_fee |
协议手续费率 | 5% |
7.2 Worker Bonding / Slashing
// === X-L2-Planning=true ===
// 质押与惩罚逻辑
/// Bond 池管理
pub struct BondPool {
pub worker: Addr,
pub total_bond: Uint128,
pub locked_bond: Uint128, // 当前任务中锁定的质押
pub available_bond: Uint128, // 可用质押
pub reputation_score: u64,
pub completed_tasks: u64,
pub failed_tasks: u64,
pub last_slash_time: u64,
}
/// Slashing 规则
pub enum SlashReason {
InvalidOutput, // 输出承诺与执行结果不匹配
Timeout, // 执行超时
DoubleSubmission, // 重复提交收据
MaliciousBehavior, // 恶意行为
ChallengeLost, // 挑战失败
}
/// Slashing 比例
pub fn get_slash_percentage(reason: SlashReason) -> u64 {
match reason {
SlashReason::InvalidOutput => 100, // 100% of task bond
SlashReason::Timeout => 25, // 25%
SlashReason::DoubleSubmission => 50, // 50%
SlashReason::MaliciousBehavior => 100, // 100% + reputation reset
SlashReason::ChallengeLost => 50, // 50%
}
}
7.3 奖励分配
Task 完成后的资金流:
Task Creator Deposit (1,000,000 uom)
│
├── 90% → Worker Payment (900,000 uom)
│ ├── 85% → Worker (base reward)
│ └── 5% → Worker Pool (delegation rewards)
│
├── 5% → Protocol Fee (50,000 uom) → Foundation Treasury
│
└── 5% → Challenge Pool (50,000 uom)
├── Used for challenge deposits
└── Distributed to successful challengers
7.4 争议费用
// === X-L2-Planning=true ===
// 争议经济模型
pub struct DisputeEconomics {
/// 挑战押金比例 (相对于 task reward)
pub challenge_deposit_percent: u64, // 10%
/// Worker 回应押金比例
pub response_deposit_percent: u64, // 5%
/// 仲裁费用 (固定值 uom)
pub arbitration_fee: Uint128,
/// 挑战者奖励比例 (从 slashed bond)
pub challenger_reward_percent: u64, // 70%
/// DAO 罚没收入比例
pub dao_slash_percent: u64, // 30%
}
/// 争议结果资金分配
pub fn distribute_dispute_funds(
task_reward: Uint128,
worker_bond: Uint128,
challenge_deposit: Uint128,
verdict: Verdict,
) -> Distribution {
match verdict {
Verdict::WorkerValid => {
// Worker 获得奖励 + 返还挑战押金
// 挑战者损失押金 -> 部分补偿 Worker
Distribution {
worker: task_reward + challenge_deposit * 70 / 100,
challenger: challenge_deposit * 30 / 100,
treasury: Uint128::zero(),
dao: Uint128::zero(),
}
}
Verdict::ChallengerValid => {
// Worker 被 Slash
// 挑战者获得奖励
Distribution {
worker: Uint128::zero(),
challenger: worker_bond * 70 / 100 + challenge_deposit,
treasury: Uint128::zero(),
dao: worker_bond * 30 / 100,
}
}
Verdict::Split => {
// 按比例分配
Distribution {
worker: task_reward * 50 / 100,
challenger: challenge_deposit,
treasury: task_reward * 5 / 100,
dao: worker_bond * 30 / 100,
}
}
}
}
8. 前端
8.1 React Dashboard
// === X-L2-Planning=true ===
// 文件: frontend/src/App.tsx
import React, { useState, useEffect, useCallback } from "react";
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
import { TaskSubmissionForm } from "./components/TaskSubmissionForm";
import { TaskStatusTracker } from "./components/TaskStatusTracker";
import { WorkerStats } from "./components/WorkerStats";
import { DisputeManager } from "./components/DisputeManager";
// === 主应用 ===
function App() {
return (
<BrowserRouter>
<div className="app-container">
<nav className="sidebar">
<h1>AI Task L2</h1>
<ul>
<li><Link to="/">Dashboard</Link></li>
<li><Link to="/submit">Submit Task</Link></li>
<li><Link to="/tasks">Task Status</Link></li>
<li><Link to="/workers">Workers</Link></li>
<li><Link to="/disputes">Disputes</Link></li>
</ul>
</nav>
<main className="content">
<Routes>
<Route path="/" element={<Dashboard />} />
<Route path="/submit" element={<TaskSubmissionForm />} />
<Route path="/tasks" element={<TaskStatusTracker />} />
<Route path="/workers" element={<WorkerStats />} />
<Route path="/disputes" element={<DisputeManager />} />
</Routes>
</main>
</div>
</BrowserRouter>
);
}
// === Dashboard ===
function Dashboard() {
const [stats, setStats] = useState({
totalTasks: 0,
pendingTasks: 0,
activeWorkers: 0,
totalRewards: "0",
});
useEffect(() => {
// 从 Agent API 获取统计信息
fetchStats();
const interval = setInterval(fetchStats, 10000);
return () => clearInterval(interval);
}, []);
const fetchStats = async () => {
try {
const response = await fetch("/agent/v1/work/tasks?limit=1");
const data = await response.json();
setStats((prev) => ({
...prev,
totalTasks: data.total || 0,
}));
} catch (err) {
console.error("Failed to fetch stats:", err);
}
};
return (
<div className="dashboard">
<h2>AI Task L2 Dashboard</h2>
<div className="stats-grid">
<div className="stat-card">
<h3>Total Tasks</h3>
<p>{stats.totalTasks}</p>
</div>
<div className="stat-card">
<h3>Pending</h3>
<p>{stats.pendingTasks}</p>
</div>
<div className="stat-card">
<h3>Active Workers</h3>
<p>{stats.activeWorkers}</p>
</div>
<div className="stat-card">
<h3>Total Rewards</h3>
<p>{stats.totalRewards} uom</p>
</div>
</div>
</div>
);
}
8.2 Task 提交表单
// === X-L2-Planning=true ===
// 文件: frontend/src/components/TaskSubmissionForm.tsx
import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
interface TaskFormData {
modelRef: string;
modelHash: string;
inputData: string;
reward: string;
challengeWindow: number;
proofLevel: "none" | "hash" | "tee" | "zk";
teeRequired: boolean;
maxTimeout: number;
}
export function TaskSubmissionForm() {
const navigate = useNavigate();
const [formData, setFormData] = useState<TaskFormData>({
modelRef: "",
modelHash: "",
inputData: "",
reward: "1000000",
challengeWindow: 86400,
proofLevel: "hash",
teeRequired: false,
maxTimeout: 300,
});
const [submitting, setSubmitting] = useState(false);
const [error, setError] = useState<string | null>(null);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setSubmitting(true);
setError(null);
try {
// 计算 input commitment
const inputCommitment = await sha256(formData.inputData);
const payload = {
model_ref: formData.modelRef,
model_hash: formData.modelHash || inputCommitment,
input_commitment: inputCommitment,
reward: formData.reward,
challenge_window: formData.challengeWindow,
params: {
proof_required: formData.proofLevel !== "none",
tee_required: formData.teeRequired,
max_timeout: formData.maxTimeout,
input_format: "text",
output_format: "json",
min_worker_reputation: 0,
quorum_count: 1,
},
};
// 通过 Agent API 提交
const response = await fetch("/agent/v1/work/tasks/offer", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": process.env.REACT_APP_API_KEY || "",
},
body: JSON.stringify(payload),
});
if (!response.ok) {
throw new Error(`Submission failed: ${response.statusText}`);
}
const result = await response.json();
navigate(`/tasks?taskId=${result.data.work_id}`);
} catch (err: any) {
setError(err.message);
} finally {
setSubmitting(false);
}
};
return (
<div className="task-form-container">
<h2>Submit AI Task</h2>
<form onSubmit={handleSubmit} className="task-form">
<div className="form-group">
<label>Model Reference</label>
<select
value={formData.modelRef}
onChange={(e) =>
setFormData({ ...formData, modelRef: e.target.value })
}
>
<option value="">Select AI Model...</option>
<option value="gpt4-model-v1">GPT-4 Model v1</option>
<option value="llama3-model-v1">LLaMA 3 Model v1</option>
<option value="stable-diffusion-v1">Stable Diffusion v1</option>
<option value="custom">Custom Model</option>
</select>
</div>
<div className="form-group">
<label>Model Hash (SHA3-256)</label>
<input
type="text"
value={formData.modelHash}
onChange={(e) =>
setFormData({ ...formData, modelHash: e.target.value })
}
placeholder="Optional - auto-calculated if empty"
/>
</div>
<div className="form-group">
<label>Input Data</label>
<textarea
value={formData.inputData}
onChange={(e) =>
setFormData({ ...formData, inputData: e.target.value })
}
rows={6}
placeholder="Enter task input data..."
/>
</div>
<div className="form-row">
<div className="form-group">
<label>Reward (uom)</label>
<input
type="text"
value={formData.reward}
onChange={(e) =>
setFormData({ ...formData, reward: e.target.value })
}
/>
</div>
<div className="form-group">
<label>Challenge Window (seconds)</label>
<input
type="number"
value={formData.challengeWindow}
onChange={(e) =>
setFormData({
...formData,
challengeWindow: parseInt(e.target.value),
})
}
/>
</div>
</div>
<div className="form-row">
<div className="form-group">
<label>Proof Level</label>
<select
value={formData.proofLevel}
onChange={(e) =>
setFormData({
...formData,
proofLevel: e.target.value as any,
})
}
>
<option value="none">None (No Proof)</option>
<option value="hash">Hash Commitment</option>
<option value="tee">TEE Attestation</option>
<option value="zk">ZK/SNARK Proof</option>
</select>
</div>
<div className="form-group">
<label>Max Timeout (seconds)</label>
<input
type="number"
value={formData.maxTimeout}
onChange={(e) =>
setFormData({
...formData,
maxTimeout: parseInt(e.target.value),
})
}
/>
</div>
</div>
<div className="form-group checkbox">
<label>
<input
type="checkbox"
checked={formData.teeRequired}
onChange={(e) =>
setFormData({ ...formData, teeRequired: e.target.checked })
}
/>
Require TEE Execution
</label>
</div>
{error && <div className="error-message">{error}</div>}
<button type="submit" disabled={submitting}>
{submitting ? "Submitting..." : "Submit Task"}
</button>
</form>
</div>
);
}
async function sha256(input: string): Promise<string> {
const encoder = new TextEncoder();
const data = encoder.encode(input);
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
return Array.from(new Uint8Array(hashBuffer))
.map((b) => b.toString(16).padStart(2, "0"))
.join("");
}
8.3 Task 状态追踪
// === X-L2-Planning=true ===
// 文件: frontend/src/components/TaskStatusTracker.tsx
import React, { useState, useEffect, useCallback } from "react";
import { useSearchParams } from "react-router-dom";
interface TaskStatus {
id: string;
status: string;
modelRef: string;
worker?: string;
reward: string;
createdAt: string;
updatedAt: string;
receipt?: {
outputHash: string;
proofHash: string;
submittedAt: string;
};
challenge?: {
id: string;
challenger: string;
reason: string;
status: string;
};
}
const STATUS_COLORS: Record<string, string> = {
pending: "#f59e0b",
accepted: "#3b82f6",
executing: "#8b5cf6",
completed: "#10b981",
challenged: "#ef4444",
disputed: "#f97316",
settled: "#22c55e",
cancelled: "#6b7280",
expired: "#9ca3af",
};
export function TaskStatusTracker() {
const [searchParams] = useSearchParams();
const [tasks, setTasks] = useState<TaskStatus[]>([]);
const [loading, setLoading] = useState(true);
const initialTaskId = searchParams.get("taskId");
const fetchTasks = useCallback(async () => {
try {
const url = initialTaskId
? `/agent/v1/work/tasks/${initialTaskId}`
: "/agent/v1/work/tasks";
const response = await fetch(url, {
headers: { "X-API-Key": process.env.REACT_APP_API_KEY || "" },
});
const data = await response.json();
const taskList = initialTaskId ? [data.data.work] : data.data.tasks;
setTasks(taskList || []);
} catch (err) {
console.error("Failed to fetch tasks:", err);
} finally {
setLoading(false);
}
}, [initialTaskId]);
useEffect(() => {
fetchTasks();
const interval = setInterval(fetchTasks, 5000);
return () => clearInterval(interval);
}, [fetchTasks]);
if (loading) return <div className="loading">Loading tasks...</div>;
return (
<div className="task-tracker">
<h2>Task Status</h2>
{tasks.length === 0 ? (
<p className="empty-state">No tasks found.</p>
) : (
<div className="task-list">
{tasks.map((task) => (
<div key={task.id} className="task-card">
<div className="task-header">
<span className="task-id">{task.id}</span>
<span
className="task-status"
style={{
backgroundColor:
STATUS_COLORS[task.status] || "#6b7280",
}}
>
{task.status}
</span>
</div>
<div className="task-details">
<div className="detail-row">
<span className="label">Model:</span>
<span>{task.modelRef}</span>
</div>
<div className="detail-row">
<span className="label">Worker:</span>
<span>{task.worker || "Not assigned"}</span>
</div>
<div className="detail-row">
<span className="label">Reward:</span>
<span>{task.reward} uom</span>
</div>
<div className="detail-row">
<span className="label">Created:</span>
<span>
{new Date(task.createdAt).toLocaleString()}
</span>
</div>
{task.receipt && (
<div className="receipt-info">
<h4>Receipt</h4>
<div className="detail-row">
<span className="label">Output Hash:</span>
<code>{task.receipt.outputHash.slice(0, 16)}...</code>
</div>
<div className="detail-row">
<span className="label">Proof Hash:</span>
<code>{task.receipt.proofHash.slice(0, 16)}...</code>
</div>
</div>
)}
{task.challenge && (
<div className="challenge-info">
<h4>Challenge</h4>
<div className="detail-row">
<span className="label">Challenger:</span>
<span>{task.challenge.challenger}</span>
</div>
<div className="detail-row">
<span className="label">Reason:</span>
<span>{task.challenge.reason}</span>
</div>
</div>
)}
</div>
<div className="task-actions">
{task.status === "completed" && (
<button className="btn-settle"
onClick={() => handleSettle(task.id)}>
Settle
</button>
)}
{task.status === "completed" && (
<button className="btn-challenge"
onClick={() => handleChallenge(task.id)}>
Challenge
</button>
)}
</div>
</div>
))}
</div>
)}
</div>
);
}
async function handleSettle(taskId: string) {
await fetch(`/agent/v1/work/tasks/${taskId}/settle`, {
method: "POST",
headers: { "X-API-Key": process.env.REACT_APP_API_KEY || "" },
body: JSON.stringify({
amount: "0",
settlement_hash: crypto.randomUUID(),
escrow_release_hash: crypto.randomUUID(),
}),
});
}
async function handleChallenge(taskId: string) {
const reason = prompt("Enter challenge reason:");
if (!reason) return;
await fetch(`/agent/v1/work/tasks/${taskId}/challenge`, {
method: "POST",
headers: { "X-API-Key": process.env.REACT_APP_API_KEY || "" },
body: JSON.stringify({
challenge_id: crypto.randomUUID(),
reason,
proof_hash: crypto.randomUUID(),
}),
});
}
8.4 Dispute 管理 UI
// === X-L2-Planning=true ===
// 文件: frontend/src/components/DisputeManager.tsx
import React, { useState, useEffect } from "react";
interface DisputeRecord {
id: string;
taskId: string;
challenger: string;
reason: string;
status: "open" | "responded" | "resolved" | "expired";
createdAt: string;
workerResponse?: string;
verdict?: string;
}
export function DisputeManager() {
const [disputes, setDisputes] = useState<DisputeRecord[]>([]);
useEffect(() => {
fetchDisputes();
const interval = setInterval(fetchDisputes, 10000);
return () => clearInterval(interval);
}, []);
const fetchDisputes = async () => {
try {
const response = await fetch("/agent/v1/work/disputes", {
headers: { "X-API-Key": process.env.REACT_APP_API_KEY || "" },
});
const data = await response.json();
setDisputes(data.data?.disputes || []);
} catch (err) {
console.error("Failed to fetch disputes:", err);
}
};
return (
<div className="dispute-manager">
<h2>Dispute Management</h2>
<div className="dispute-list">
{disputes.map((dispute) => (
<div key={dispute.id} className={`dispute-card status-${dispute.status}`}>
<div className="dispute-header">
<span className="dispute-id">{dispute.id}</span>
<span className="dispute-status">{dispute.status}</span>
</div>
<div className="dispute-details">
<p><strong>Task:</strong> {dispute.taskId}</p>
<p><strong>Challenger:</strong> {dispute.challenger}</p>
<p><strong>Reason:</strong> {dispute.reason}</p>
<p><strong>Created:</strong> {new Date(dispute.createdAt).toLocaleString()}</p>
{dispute.workerResponse && (
<p><strong>Worker Response:</strong> {dispute.workerResponse}</p>
)}
{dispute.verdict && (
<p className={`verdict verdict-${dispute.verdict.toLowerCase()}`}>
<strong>Verdict:</strong> {dispute.verdict}
</p>
)}
</div>
{dispute.status === "open" && (
<div className="dispute-actions">
<button className="btn-respond">Respond as Worker</button>
<button className="btn-escalate">Escalate to DAO</button>
</div>
)}
</div>
))}
</div>
</div>
);
}
9. 路线图
9.1 实施阶段
Phase 1: Task 合约部署 + 本地测试 (1-2 个月)
├── 实现 TaskManager 合约
├── 实现 ReceiptRegistry 合约
├── 单元测试 & 集成测试
├── 本地 MSG Chain 测试网部署
└── 基础 Task 生命周期验证
Phase 2: Off-chain Executor (1-2 个月)
├── 实现 Worker 节点框架
├── 实现 Task Scheduler
├── Agent API 集成 (复用现有端点)
├── Webhook 通知系统
└── Worker 注册与心跳机制
Phase 3: 证明系统 (2-3 个月)
├── Output Commitment 方案实现
├── TEE 证明验证器 (SGX/SEV)
├── ZK 证明电路设计与验证
├── 多 Worker 共识证明
└── L1 验证合约
Phase 4: 争议解决 (1 个月)
├── DisputeResolver 合约
├── 挑战窗口机制
├── 自动裁决逻辑
├── DAO 仲裁集成
└── Slashing 实现
Phase 5: 生产 L2 (2-3 个月)
├── 经济模型调优
├── 性能优化 & 基准测试
├── 安全审计
├── 主网上线
├── L1 Anchor 锚定机制
└── 跨链桥接 (IBC + 跨链结算)
9.2 里程碑
| 里程碑 | 时间 | 交付物 | 验证标准 |
|---|---|---|---|
| M1 | Month 1 | Task 合约 v1 | 可通过 CLI 提交并查询 Task |
| M2 | Month 2 | Executor v1 | 端到端 Task 提交→执行→结算 |
| M3 | Month 3 | Proof 系统 v1 | TEE/ZK 证明可验证 |
| M4 | Month 4 | Dispute 系统 | 挑战→争议→裁决全流程 |
| M5 | Month 6 | L2 生产上线 | 运行中 Worker ≥ 10, 日任务量 ≥ 1000 |
9.3 当前依赖
已完成依赖:
✅ MSG Chain L1 主链 (msg-chain-1)
✅ CosmWasm 1.5 虚拟机
✅ Agent API (agent/v1)
✅ Agent Payment (agent_payment_v1)
✅ DAO Governance (dao_governance_v1)
✅ Foundation Treasury (foundation_treasury_v2)
✅ AI Agent Constitution (ai_agent_constitution_v1)
✅ Wallet/Key Management
✅ Event System
✅ Transaction Receipt System
规划中依赖 (X-L2-Planning=true):
❌ TaskManager 合约
❌ ReceiptRegistry 合约
❌ DisputeResolver 合约
❌ Settlement 合约
❌ L1 Anchor 锚定合约
❌ Off-chain Executor
❌ Proof 验证库
❌ TEE Attestation 验证
❌ ZK 证明电路
❌ Worker Registry
9.4 技术债务与风险
| 风险 | 影响 | 缓解措施 |
|---|---|---|
| ZK 证明生成耗时 | 结算延迟 | 先实现 hash/tee 证明,ZK 作为可选项 |
| TEE 兼容性 | Worker 硬件要求高 | 支持多种 TEE (SGX/SEV/CCA) |
| 挑战窗口过长 | 资金锁定时间长 | 动态挑战窗口 (根据任务价值/风险) |
| Worker 去中心化不足 | 单点故障 | 渐进式开放 Worker 注册 |
| L2-L1 数据可用性 | 数据不可用导致争议失败 | 数据托管到 IPFS/Arweave |
9.5 配置参考
MSG Chain 配置参考:
Chain ID: msg-chain-1
Bech32 Prefix: msg
Block Time: 5s
CosmWasm Version: 1.5
IBC: 规划中 (X-L2-Planning=true)
跨链桥接: 规划中 (X-L2-Planning=true)
Agent API:
Rate Limit: 100 req/s
Burst Limit: 200 req
公开端点: /agent/v1/query/account, balance, tx, block
/agent/v1/events/history, subscribe
/agent/v1/oracle/price
保护端点: /agent/v1/wallet/, mpc/sign, payment/session
已部署合约:
dao_governance_v1: 治理提案/投票/时间锁/执行
foundation_treasury_v2: 基金会金库/多签支付
agent_payment_v1: AI Agent 里程碑支付
ai_agent_constitution_v1: AI 行为合规检查
注意: 本指南中所有标记
X-L2-Planning=true的功能均处于规划阶段,代码为示意性设计参考,尚未经过安全审计,不可直接用于生产环境。实际部署前请参考最新版本的合约代码和部署文档。
参考架构:
- Arbitrum L2 结算模型 (Optimistic Rollup + 挑战窗口)
- Akash Network 计算市场 (去中心化计算资源匹配)
