經驗證的隨機數字產生器 (vRNG)

本文件為 Proof of Play 所提供的驗證隨機數字產生器 (vRNG) 指南的概述,專為與 Kaia 整合而設計。 vRNG 系統利用 drand 隨機性信標,為 Kaia 區塊鏈上的智慧合約提供安全且可驗證的隨機數。
驗證隨機數字產生器 (vRNG) 已針對隨機數字的低延遲傳輸進行最佳化,以盡量減少應用程式的延遲。 它的設計強調可靠性和可擴展性。

註冊
在早期存取期間,所有使用驗證隨機數字產生器系統的使用者都必須手動註冊。 要使用它,您的合約地址必須獲得核准,否則任何請求都會退回。
參賽隊伍可以透過 官方表格,或是直接聯絡 Kaia 團隊來申請核准,視乎哪種方式更方便而定。
vRNG 合約地址
| 網路 | 地址 | API URL |
|---|---|---|
| Kaia Mainnet | 0xf628f7843d94064c5072704a53b9ec455bcc4abb | https://vrf.proofofplay.com/v1 |
| 啟動測試網路 | 0xd14d984603b0b7ade91be52f3fc4a917dfa77bcd | https://staging.vrf.proofofplay.com/v1 |
使用方式
要求隨機號碼
以下介面提供了一個請求隨機數的方法。
您的契約可以呼叫部署在每個鏈上的 VRFSystem。 您可以選擇提供一個 traceId,它會註解到每個事件 (如果您有一個執行許多步驟的交易,使用者可以在連鎖上追蹤他們的交易 ,這是很有用的)。 此為非必要,可保留為 0。
// SPDX-License-Identifier: MIT LICENSEpragma solidity ^0.8.26;uint256 constant ID = uint256(keccak256('com.proofofplay.vrfsystem.v1'));interface IVRFSystem { /** * Starts a VRF random number request * * @param traceId Optional ID to use when tracing the request * @return requestId for the random number, will be passed to the callback contract */ function requestRandomNumberWithTraceId(uint256 traceId) external returns (uint256); }
隨機數回呼
只要 drand 中的第一個號碼可以送出,就會送出所要求的每個隨機號碼。 這可能需要長達 3 秒鐘的時間。
您的呼叫將在您第一次提交 requestForRandomNumber 之後***送達。 這可確保在使用者要求隨機號碼之前,***不會知道該號碼。
// SPDX-License-Identifier: MIT LICENSEpragma solidity ^0.8.26;interface IVRFSystemCallback { /** * Callback for when a Random Number is delivered * * @param requestId Id of the request * @param randomNumber Random number that was generated by the Verified Random Number Generator Tool */ function randomNumberCallback(uint256 requestId, uint256 randomNumber) external; }
如果我想在同一個 3 秒視窗中使用不同的數字,該怎麼辦?
預設情況下,我們會在 drand 提供的相同 3 秒視窗內向所有請求提供相同的數字。 這很好,可以驗證,但如果您希望使用者在這段時間內都有不同的數字,我們建議您加入一個熵源。
以下是每個交易擁有唯一隨機號碼的幾個範例。
// Add the requestId (Most Gas Efficient) uint256 newRandomNumber = requestId + randomNumber;// Hash with requestId uint256 newRandomNumber = uint256(keccak256(abi.encodePacked(requestId, randomNumber)// More expensive, but more normalized, hash based on requestId in last 256 block hashes uint256 newRandomNumber = uint256(keccak256(abi.encodePacked(blockhash(block.number - (requestId % 256)), randomNumber))
這些資料不保證會規範化,但會保留上述的隨機性屬性。 我們建議依您的喜好調整,以達到或多或少的規範化(例如,將 sequenceId 加入 randomNumber 會非常偏斜,而使用 blockhash 則會非常規範化)。
如果您想在同一區塊中使用不同的號碼 ,我們建議您在同一筆交易中多次重複使用相同的號碼。
functionThatUsesNumber(randomNumber); randomNumber = uint256(keccak256(randomNumber)); functionThatUsesNumber(randomNumber);
如果我想在同一筆交易中使用不同的號碼,該怎麼辦?
預設情況下,每次交易我們只會給您一個號碼。 我們鼓勵開發者使用這個號碼,從中衍生出其他號碼,創造出新的號碼。
//Example 1: Keccak derive uint256 randomNumber = 12398012938091283113928; uint256 randomNumber2 = keccak256(randomNumber); uint256 randomNumber3 = keccak256(randomNumber2);//Example 2: Split the number and use both sides uint256 randomNumber = 234345234523452345; uint256 randomNumber2 = randomNumber >> 128; // Take upper 128 bits uint256 randomNumber3 = randomNumber & ((1 << 128) - 1); // Take lower 128 bits
區塊鏈活動
合約會發出下列事件。
/// @notice Emitted when a random number request is initiated /// @param requestId The unique identifier for the random number request /// @param callbackAddress The address to which the random number is requested /// @param traceId The trace ID used to track the request across transactions (0 if no trace ID) event RandomNumberRequested(uint256 indexed requestId, address indexed callbackAddress, uint256 indexed traceId);/// @notice Emitted when a random number is successfully delivered /// @param requestId The unique identifier of the fulfilled request /// @param callbackAddress the address was random number is requested to /// @param traceId The trace ID associated with the request /// @param number The round number that was used for the random number /// @param randomNumber The random number that was generated event RandomNumberDelivered(uint256 indexed requestId, address indexed callbackAddress, uint256 indexed traceId, uint256 roundNumber, uint256 randomNumber);
您可以在 RPC 層級查詢這些事件,看看它們是否已傳送,或使用區塊瀏覽器檢視事件串流。
使用 drand 驗證圓數/隨機數
如果您想要驗證隨機號碼,可以直接向 drand 查詢。 我們使用 drand 的 quicknet 來達到此目的。
例如,要查看圓數 11:
GET https://api.drand.sh/52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971/public/11
{ "round": 11, "randomness": "ebdcbfe855d10c56db22455fa5a18963c1f62d85f859c35c310273449b49d284", "signature": "163d14081e191a3f5d81e2f580eab591ea608402fda4f6e44b5a0bde11e368070e77d07ad3240726ea33e410c84d4b09ea0a4a0291f6c3c485d8630e1c0edf0a" }
我們可以在此看到十六進制的隨機數是 ebdcbfe855d10c56db22455fa5a18963c1f62d85f859c35c310273449b49d284 。
使用 EIP712 簽章進行手動重試
** 此功能正在預覽中**。 如果您想使用,請聯絡 Kaia 團隊。
在非常罕見的情況下,您可能會看到隨機號碼無法傳送。 在大多數情況下,這會是合約方面的問題。
在這些情 況下,您可以選擇自己交付此號碼。 首先,您應該向我們的 API 伺服器請求 EIP712 簽署,您可以使用該簽署直接將隨機數傳送至區塊鏈上的合約。
請求:
GET https://vrf.proofofplay.com/v1/vrf/{chainId}/{txHash}
回應:
{ "requestId": Number, "roundNumber": Number, "randomNumber": BigInt, "signature": String // bytes data of signature }
有了回應,您現在可以呼叫 VRFSystem 契約
vrf.deliverSignedRandomNumber(requestId, roundNumber, randomNumber, signature);
您將比賽正常的中繼流程。 如果您收到帶有 InvalidRequestId 的 tx revert,這表示已經有中繼者傳送了這個隨機號碼。 隨機號碼只能遞送一次。