Day 6
预言机系统
中级阶段 · 预计学习时间 3-4 小时
学习目标
- 理解预言机的作用
- 注册预言机
- 查询和响应预言机
预言机概述
预言机(Oracle)是区块链与外部世界的桥梁,允许链上合约访问链外数据(如价格、天气、比赛结果)。
工作流程
| 角色 | 操作 |
|---|---|
| Oracle 运营者 | 注册预言机 → 监听查询 → 响应查询 |
| 查询者 | 发送查询(支付费用)→ 获取响应 |
注册预言机
import "strings"
// 预言机参数
querySpec := "string" // 查询格式
responseSpec := "string" // 响应格式
queryFee := big.NewInt(100) // 查询费用
// TTL 类型: 0 = 相对区块数, 1 = 绝对区块高度
oracleTTLType := uint64(0)
oracleTTLValue := uint64(500) // 500 区块后过期
abiVersion := uint16(0) // 原始数据,无 ABI
// 创建注册交易
regTx, err := transactions.NewOracleRegisterTx(
alice.Address,
querySpec,
responseSpec,
queryFee,
oracleTTLType,
oracleTTLValue,
abiVersion,
ttlnoncer,
)
if err != nil {
log.Fatal(err)
}
// 签名和广播...
// Oracle ID = ak_ 替换为 ok_
oracleID := strings.Replace(alice.Address, "ak_", "ok_", 1)
fmt.Printf("Oracle ID: %s\n", oracleID)
查询预言机
任何用户都可以向预言机发送查询,需支付查询费用。
query := "What is the price of AE?"
queryTTLType := uint64(0)
queryTTLValue := uint64(50)
responseTTLType := uint64(0)
responseTTLValue := uint64(50)
queryTx, err := transactions.NewOracleQueryTx(
bob.Address, // 查询者
oracleID, // 预言机 ID
query, // 查询内容
queryFee, // 费用
queryTTLType,
queryTTLValue,
responseTTLType,
responseTTLValue,
ttlnoncer,
)
// 签名和广播...
// 交易确认后可以获取 Query ID (oq_...)
响应查询
预言机运营者监听查询并响应。
queryID := "oq_..." // 从查询交易获取
response := "1.50 USD"
respTx, err := transactions.NewOracleRespondTx(
alice.Address, // 预言机所有者
oracleID,
queryID,
response,
responseTTLType,
responseTTLValue,
ttlnoncer,
)
// 签名和广播...
fmt.Printf("已响应查询: %s\n", response)
预言机运营流程
// 简化的预言机服务循环
func runOracleService(node *naet.Node, oracle *account.Account, oracleID string) {
fmt.Println("预言机服务启动...")
fmt.Printf("Oracle ID: %s\n", oracleID)
for {
// 1. 获取待处理查询
queries, err := node.GetOracleQueries(oracleID)
if err != nil {
log.Println("获取查询失败:", err)
continue
}
// 2. 处理每个查询
for _, q := range queries {
if q.Response == "" {
// 获取外部数据(模拟)
response := getExternalData(q.Query)
// 发送响应
respondToQuery(node, oracle, oracleID, q.ID, response)
}
}
time.Sleep(10 * time.Second)
}
}
func getExternalData(query string) string {
// 实际应用中调用外部 API
if strings.Contains(query, "AE") {
return "0.085 USD"
}
return "Unknown"
}
知识检查点