# Oracle vs Prevrandao

## 概述

随机数是骰子游戏的核心。MemeDice 支持两种随机数生成模式：**Oracle 模式** 和 **Prevrandao 模式**。两种模式各有优劣，适用于不同的场景。

***

## 工作原理

### Oracle 模式

Oracle 模式使用 **commit-reveal（承诺-揭示）** 机制，通过链下 Oracle 服务生成随机数。

```mermaid
sequenceDiagram
    participant O as Oracle 服务
    participant P as 玩家
    participant C as 游戏合约

    Note over O: ① 生成随机数 R
    Note over O: ② 计算 commitHash = keccak256(R)
    Note over O: ③ 签名 (commitHash, deadline)
    O-->>P: 返回 commitHash + 签名
    P->>C: placeBetAsync(commitHash, 签名, 下注参数)
    Note over C: ④ 验证签名有效性
    Note over C: ⑤ 锁定 commitHash
    Note over C: ⑥ 锁定下注资金
    O->>C: fulfillRandomNumber(requestId, R)
    Note over C: ⑦ 验证 keccak256(R) == commitHash ✅
    Note over C: ⑧ 使用 R 决定结果
    Note over C: ⑨ 结算（赢则支付，输则收入资金池）
```

**关键安全点**：

* Oracle 在玩家下注 **之前** 就已经确定了随机数（通过 commitHash 锁定）
* 玩家下注时提交 commitHash，合约锁定
* Oracle 随后揭示随机数，合约验证 `keccak256(R) == commitHash`
* Oracle **无法** 在看到下注后修改随机数
* 玩家 **无法** 预测随机数

### Prevrandao 模式

Prevrandao 模式使用以太坊的 `block.prevrandao`（EIP-4399）作为随机数源，在同一笔交易中完成下注和结算。

```mermaid
sequenceDiagram
    participant P as 玩家
    participant C as 游戏合约
    participant B as 区块链

    P->>C: placeBetSync(下注参数)
    Note over C: ① 获取 block.prevrandao
    B-->>C: prevrandao 值
    Note over C: ② 使用 prevrandao 决定结果
    Note over C: ③ 立即结算
    C-->>P: 返回结果（同一笔交易）
```

**关键特点**：

* 随机数来自区块链协议层
* 下注和结算在 **同一笔交易** 中完成
* 不需要等待 Oracle 响应
* 结果即时可知

***

## 对比表

| 维度         | Oracle 模式                 | Prevrandao 模式      |
| ---------- | ------------------------- | ------------------ |
| **随机数来源**  | 链下 Oracle 服务              | 区块的 `prevrandao` 值 |
| **安全机制**   | Commit-Reveal 密码学承诺       | 区块链协议层             |
| **结算速度**   | 需要等待 Oracle 响应（通常 3-10 秒） | 即时（同一笔交易）          |
| **交易次数**   | 2 笔（下注 + 揭示）              | 1 笔（下注即结算）         |
| **Gas 费用** | 较高（Oracle 揭示需要额外 gas）     | 较低（单笔交易）           |
| **可验证性**   | ✅ 可通过 commitHash 验证       | ✅ 可通过区块浏览器验证       |
| **操纵风险**   | 🟢 极低（密码学保证）              | 🟡 中等（验证者可操纵）      |
| **支持网络**   | BSC、Base、HyperEVM         | 仅 Ethereum         |
| **合约调用**   | 允许合约调用                    | 仅限 EOA（外部账户）       |
| **批量下注**   | ✅ 支持                      | ✅ 支持               |
| **超时保护**   | ✅ 超时可取消                   | 不需要（即时结算）          |

***

## 适用场景

### 推荐使用 Oracle 模式的场景

* ✅ **BSC 网络**：BSC 不支持 prevrandao，只能使用 Oracle
* ✅ **高安全性需求**：Oracle 的 commit-reveal 机制提供密码学级别的安全保证
* ✅ **允许合约交互**：如果需要其他合约调用下注功能
* ✅ **大额下注**：更高的安全性适合大额下注场景

### 推荐使用 Prevrandao 模式的场景

* ✅ **Ethereum 主网**：原生支持 prevrandao
* ✅ **追求速度**：即时结算，无需等待
* ✅ **节省 Gas**：单笔交易完成
* ✅ **简单体验**：下注即出结果，体验更流畅

***

## Oracle 模式详解

### Commit-Reveal 机制

Commit-Reveal 是一种经典的密码学协议，用于在不信任的环境中公平地生成随机数：

1. **Commit（承诺）阶段**：
   * Oracle 生成随机数 `R`
   * 计算哈希 `commitHash = keccak256(R)`
   * 将 `commitHash` 和签名发送给玩家
   * 玩家将 `commitHash` 提交到合约
2. **Reveal（揭示）阶段**：
   * Oracle 将原始随机数 `R` 提交到合约
   * 合约验证 `keccak256(R) == commitHash`
   * 如果验证通过，使用 `R` 决定结果

### 为什么安全？

```
                    时间线
    ─────────────────────────────────────►
    
    Oracle 生成 R     玩家下注      Oracle 揭示 R
    计算 commitHash   提交 commitHash   合约验证
         │               │               │
         ▼               ▼               ▼
    R 已确定         R 已锁定        R 被验证
    (Oracle 知道)    (无法修改)      (公开可查)
```

* **Oracle 无法作弊**：commitHash 在下注前已锁定，Oracle 无法在看到下注后修改 R
* **玩家无法作弊**：玩家不知道 R 的值，无法预测结果
* **任何人可验证**：所有人都可以验证 `keccak256(R) == commitHash`

### 超时保护

如果 Oracle 在规定时间内没有揭示随机数（例如 Oracle 服务宕机），玩家可以：

1. 等待超时期限（`BET_TIMEOUT`，通常为数分钟）
2. 调用取消函数
3. 取回下注资金

这确保了即使 Oracle 不响应，玩家的资金也不会被锁定。

### Oracle 费用

Oracle 模式需要支付额外的 Oracle 服务费，用于覆盖：

* Oracle 揭示交易的 gas 费用
* Oracle 服务的运营成本

***

## Prevrandao 模式详解

### 什么是 Prevrandao？

`prevrandao`（EIP-4399）是以太坊在合并（The Merge）后引入的一个区块级别的伪随机数。它取代了原来的 `block.difficulty` 字段。

* 每个区块都有一个唯一的 `prevrandao` 值
* 该值由上一个区块的 RANDAO 混合值决定
* 在区块被提议之前，`prevrandao` 的值是不可预测的（对普通用户而言）

### 安全限制

Prevrandao 模式有一些安全限制：

1. **验证者操纵**：区块验证者可以选择性地包含或排除交易，从而间接影响结果
2. **仅限 EOA**：合约不能调用 Prevrandao 模式的下注函数，防止闪电贷攻击
3. **网络限制**：BSC 不支持 prevrandao

详细的安全分析请参阅 [Prevrandao 安全性分析](/ji-shu-gai-lan/prevrandao-an-quan-xing-fen-xi.md)。

***

## 如何选择？

```mermaid
graph TD
    A[选择随机数模式] --> B{使用什么网络？}
    B -->|BSC| C[只能选 Oracle ✅]
    B -->|Ethereum| D{优先考虑什么？}
    D -->|安全性| E[选择 Oracle ✅]
    D -->|速度和成本| F[选择 Prevrandao ✅]
    D -->|需要合约调用| G[选择 Oracle ✅]
    
    style C fill:#4F46E5,color:#fff
    style E fill:#4F46E5,color:#fff
    style F fill:#059669,color:#fff
    style G fill:#4F46E5,color:#fff
```

**简单建议**：

* 如果你不确定，选择 **Oracle 模式**（默认选项）
* 如果你在 BSC 上，只能选择 **Oracle 模式**
* 如果你在 Ethereum 上且追求极致速度，可以选择 **Prevrandao 模式**

***

## 相关链接

* ⬅️ 返回 [技术深度概览](/ji-shu-gai-lan/ji-shu-shen-du-gai-lan.md)
* 🛡️ 深入了解 [Prevrandao 安全性](/ji-shu-gai-lan/prevrandao-an-quan-xing-fen-xi.md)
* 🔍 使用 [公平性验证工具](/pai-xing-bang-yu-ri-zhi/gong-ping-xing-yan-zheng.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.dapp.meme/ji-shu-gai-lan/oracle-vs-prevrandao.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
