Skip to content

ciphermagic/ai-oracle

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AI Oracle

一个完整的去中心化 AI 预言机
ERC-20 计费 · EIP-712 签名验证 · Agent 白名单 · 实时可视化


✨ 功能概览

  • 🔗 固定入口合约:所有请求统一经过 AIHub,地址永不变更,dApp 无缝集成
  • 💰 ERC-20 计费OracleToken 作为协议代币,支持一次性 Claim 空投,费用托管在 FeeVault
  • 🤖 Agent 白名单:链上 AgentRegistry 管理可信 AI 节点,Owner 一键启用/禁用
  • 🔐 EIP-712 签名验证:Fulfillment 结构化签名,绑定 chainId + hub address,防跨链重放
  • 链下 AI 执行器:TypeScript executor 监听链上事件,调用 OpenAI / Anthropic 接口,签名回填
  • 📊 实时可视化 Dashboard:用户面板 + 管理员控制台,覆盖请求流水、系统指标、费用统计

📸 界面展示

发起 AI 请求

我的请求记录

Agent 注册管理

系统运行指标

请求全局监控

费用结算统计


🤔 为什么做这个项目

链上智能合约调用链下 AI 是一个真实存在的工程问题,但现有方案要么强依赖中心化 API 网关,要么没有统一的请求/结算标准。

AI Oracle 尝试解决三件事:

  • 固定地址入口合约屏蔽底层 AI 服务的变化,dApp 只需对接一个稳定接口
  • EIP-712 签名验证让链上合约能核实"这条回答确实来自授权的 Agent",而不是任意地址都能提交
  • ERC-20 费用模型 + FeeVault 托管实现请求方付款、Agent 结算、协议抽成的完整经济闭环

🏗️ 系统架构

graph TB
    subgraph Frontend["前端 (Next.js 15 / React 18)"]
        UPanel[用户面板\nClaimAirdrop · RequestForm · RequestList]
        APanel[管理员控制台\nAgentTable · SystemMetrics · RequestMonitor]
        Hooks[wagmi Hooks\nuseAIHub · useAgentRegistry · useOracleToken]
        UPanel & APanel --> Hooks
    end

    subgraph Executor["链下执行器 (TypeScript / Node)"]
        Dispatcher[Dispatcher\n监听 RequestCreated 事件]
        AIRunner[Executor\n调用 OpenAI / Anthropic]
        Signer[Fulfiller\nEIP-712 签名 + fulfill 上链]
        MetricsAPI[HTTP Server\n/metrics · /requests · /agents]
        Dispatcher --> AIRunner --> Signer
    end

    subgraph Contracts["合约层 (Solidity 0.8.34 / Foundry)"]
        Hub[AIHub\n固定入口]
        Registry[AgentRegistry\n白名单管理]
        Vault[FeeVault\n费用托管]
        Token[OracleToken\nERC-20 + Claim]
    end

    Hooks -->|"request() · cancel()"| Hub
    Hooks -->|"registerAgent() · setWhitelisted()"| Registry
    Hooks -->|"claim() · approve()"| Token
    Hooks -->|"GET /metrics"| MetricsAPI

    Hub -->|"RequestCreated event"| Dispatcher
    Signer -->|"fulfill(requestId, result, sig)"| Hub
    Hub -->|"lock / settle / refund"| Vault
    Hub -->|"isWhitelisted()"| Registry
Loading

🔄 核心流程

请求 → 执行 → 回填

sequenceDiagram
    actor User
    participant AIHub
    participant FeeVault
    participant Executor
    participant AI Provider
    participant Consumer

    User->>AIHub: approve(hub, fee)
    User->>AIHub: request(agentWallet, prompt, callback, fee, timeout)
    AIHub->>FeeVault: transferFrom(user → vault) + lock(requestId, fee)
    AIHub-->>Executor: emit RequestCreated(requestId, agentWallet, prompt)

    Executor->>AI Provider: POST /v1/chat/completions (stream)
    AI Provider-->>Executor: delta chunks → 拼接 result

    Executor->>Executor: EIP-712 sign Fulfillment{requestId, resultHash, deadline, hub}
    Executor->>AIHub: fulfill(requestId, result, agentSig)
    AIHub->>AIHub: ecrecover(sig) == agentWallet ✓
    AIHub->>FeeVault: settle(requestId, agent) → 90% agent / 10% protocol
    AIHub->>Consumer: onAIResponse(requestId, result)
Loading

超时取消

sequenceDiagram
    actor User
    participant AIHub
    participant FeeVault

    Note over User,FeeVault: 请求超过 timeout 仍未被 fulfill
    User->>AIHub: cancel(requestId)
    AIHub->>FeeVault: refund(requestId, requester)
    FeeVault-->>User: 全额退还锁定费用
Loading

⚙️ 核心技术实现

1. 🔐 EIP-712 Fulfillment 签名

Executor 对每条回填消息签名,链上合约通过 ecrecover 验证签名者是否为注册的 Agent 钱包,防止任意地址伪造 AI 回答。

bytes32 public constant FULFILLMENT_TYPEHASH = keccak256(
    "Fulfillment(uint256 requestId,bytes32 resultHash,uint256 deadline,address hub)"
);

// fulfill() 内部验证
bytes32 digest   = _hashTypedDataV4(structHash);   // 包含 chainId + verifyingContract
address recovered = digest.recover(agentSig);
if (recovered != req.agentWallet) revert InvalidSignature();

签名绑定 chainId(via EIP-712 domain separator)+ hub address,同一签名无法在其他链或其他合约上重放。

2. 💰 ERC-20 费用模型

// FeeVault.sol — fulfill 时按比例结算
uint256 public constant PROTOCOL_FEE_BPS = 1000; // 10%

function settle(uint256 requestId, address agent) external onlyHub {
    uint256 total       = _locked[requestId];
    uint256 protocolCut = (total * PROTOCOL_FEE_BPS) / BPS_DENOMINATOR;
    uint256 agentAmount = total - protocolCut;

    protocolFees += protocolCut;
    token.safeTransfer(agent, agentAmount);
}

费用流转:requester → FeeVault(锁定)→ 90% Agent + 10% Protocol,超时取消则全额退款。

3. 🤖 链下 AI 执行器

Executor 使用 viem watchContractEvent 订阅链上事件,事件触发后并发执行 AI 调用,结果签名后回填:

// dispatcher.ts
publicClient.watchContractEvent({
  address:   HUB_ADDRESS,
  abi:       AIHubABI,
  eventName: "RequestCreated",
  onLogs:    handleRequestCreatedLogs,
});

// executor.ts — 流式调用,兼容仅支持 stream 的代理服务
const stream = await openai.chat.completions.create({ stream: true, ... });
let result = "";
for await (const chunk of stream) {
  result += chunk.choices[0]?.delta?.content ?? "";
}

Agent 敏感信息(API Key、接口地址)存储在链下 SQLite,链上只保存钱包地址和模型元数据。

4. 📊 实时监控 API

Executor 内置 Express HTTP Server,暴露以下接口供前端轮询:

接口 说明
GET /metrics 成功率、平均延迟、Pending 数、各 Agent 统计
GET /requests 全量请求记录(含 AI 回答结果)
GET /agents 链下已注册的 Agent 配置列表
POST /agents 注册 Agent 链下配置(endpoint + apiKey)

5. 🛡️ 合约安全设计

  • ReentrancyGuardrequest / fulfill / cancel 全部加锁
  • onlyHub 修饰符:FeeVault 所有资金操作只允许 AIHub 调用
  • Callback 隔离:Consumer 回调失败不回滚 fulfillment,emit CallbackFailed 事件记录
  • 超时机制:请求超时后只有 requester 本人可调用 cancel,防止资金永久锁定

🔧 技术选型

决策 选择 原因
签名验证 EIP-712 结构化签名 防重放、可读性强、与硬件钱包兼容
费用代币 自定义 ERC-20 + Claim 空投 本地测试无需外部依赖,一键领取降低使用门槛
AI 调用 流式 + 非流式自适应 兼容不同代理服务的响应格式差异
链下存储 better-sqlite3 轻量、零依赖、适合单机 executor 场景
前端合约交互 wagmi v2 + viem 类型安全、Hooks 封装、SSR 友好
编译器 Solidity 0.8.34 最新稳定版,完整自定义错误和 EIP-712 支持

📁 项目结构

ai-oracle/
├── app/                        Next.js 15 前端
│   └── src/
│       ├── app/                页面路由(dashboard)
│       ├── components/
│       │   ├── layout/         Sidebar · WalletBar · RoleSwitcher
│       │   ├── user/           ClaimAirdrop · TokenBalance · RequestForm · RequestList · ResponseViewer
│       │   └── admin/          AgentTable · AgentRegisterForm · SystemMetrics · RequestMonitor · FeeStats
│       ├── hooks/              useAIHub · useAgentRegistry · useOracleToken · useRequestEvents · useMetrics
│       ├── lib/                wagmi 配置 · 合约地址与 ABI 导入
│       └── types/              oracle.ts · agent.ts
├── contracts/                  Foundry 合约
│   ├── src/                    OracleToken · AgentRegistry · FeeVault · AIHub 及接口
│   ├── test/                   单元测试 + 集成测试
│   └── script/                 Deploy.s.sol · Seed.s.sol
├── executor/                   TypeScript 链下执行器
│   └── src/                    dispatcher · executor · fulfiller · metrics · db 层 · HTTP server
├── scripts/                    dev.sh · deploy-local.sh · sync-abis.sh
└── deployments/                addresses.json(部署后自动生成)

🚀 本地快速启动

环境要求

1. 初始化 git 并安装依赖

# forge install 依赖 git submodule,必须先初始化
git init && git add . && git commit -m "init"

# 合约依赖
cd contracts
forge install foundry-rs/forge-std
forge install OpenZeppelin/openzeppelin-contracts
cd ..

# 链下执行器
cd executor && npm install && cd ..

# 前端
cd app && npm install && cd ..

2. 配置环境变量

cp .env.example .env
# 编辑 .env,填入 AI 服务的 API Key(本地 dev 只需填 EXECUTOR_PRIVATE_KEY)

3. 一键启动

chmod +x scripts/*.sh
bash scripts/dev.sh

启动顺序:

  1. 启动 anvil --block-time 2
  2. 部署全套合约并生成 deployments/local/addresses.json
  3. Seed 测试数据(注册 Agent、空投测试 Token)
  4. 同步 ABI 到 executor 和 app
  5. 写入 app/.env.local(合约地址注入前端)
  6. 启动 executor:http://localhost:3001
  7. 启动 Next.js:http://localhost:3000

4. 注册 Agent(首次使用)

切换到 Admin 角色,点击 Register Agent,填入:

字段 说明 示例
Agent Wallet 收款钱包地址 0xf39F...
Model ID 模型标识符 gpt-4o
Provider 服务商 openai
Endpoint URL 兼容 OpenAI 格式的接口地址 http://127.0.0.1:8317/v1
API Key 服务商 API Key(存链下) sk-...

🧪 合约测试

cd contracts

# 运行所有测试
forge test -vvv

# 完整流程集成测试
forge test --match-test test_fullFlow_requestFulfillCallback -vvv

# 取消 + 退款测试
forge test --match-test test_cancel -vvv

# Gas 报告
forge test --gas-report

覆盖场景:完整 request → fulfill → callback 流程、EIP-712 签名验证、无效签名拒绝、重复 fulfill 防护、超时取消退款、Claim 空投重复领取防护。


📄 许可证

MIT

About

一个完整的去中心化 AI 预言机。ERC-20 计费 · EIP-712 签名验证 · Agent 白名单 · 实时可视化。

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors