经过验证的随机数生成器 (vRNG)

本文档概述了由 Proof of Play 提供的验证随机数生成器(vRNG)指南,该指南是为与 Kaia 集成而设计的。 vRNG 系统利用 drand 随机性信标为 Kaia 区块链上的智能合约提供安全、可验证的随机数。
经过验证的随机数生成器(vRNG)针对随机数的低延迟传输进行了优化,以最大限度地减少应用延迟。其设计非常注重可靠性和可扩展性。

注册
在早期使用期间,验证随机数生成器系统的所有用户都必须手动注册。要使用它,您的合同地址必须获得***批准,否则任何请求都将退回。
参赛队可以通过官方表格 提交申请,也可以直接联系 Kaia 团队,这取决于哪种方式更方便。
vRNG 合同地址
| 网络 | 地址 | 应用程序接口 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 秒钟的时间。
在您提交第一个随机号码请求后***,您的呼叫将被发送到第一个号码。这样可以确保在用户请求随机数之前,***不会知道该数字。
// 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 会非常偏斜,而使用 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,这意味着中继站已经发送了这个随机数。随机数只能发送一次。