跳至主要内容
本页面使用机器翻译自英语,可能包含错误或不清楚的语言。如需最准确的信息,请参阅英文原文。由于更新频繁,部分内容可能与英文原文有出入。请加入我们在 Crowdin 上的努力,帮助我们改进本页面的翻译。 (Crowdin translation page, Contributing guide)

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

本文档概述了由 Proof of Play 提供的验证随机数生成器(vRNG)指南,该指南是为与 Kaia 集成而设计的。 vRNG 系统利用 drand 随机性信标为 Kaia 区块链上的智能合约提供安全、可验证的随机数。

经过验证的随机数生成器(vRNG)针对随机数的低延迟传输进行了优化,以最大限度地减少应用延迟。 其设计非常注重可靠性和可扩展性。

注册

在早期使用期间,验证随机数生成器系统的所有用户都必须手动注册。 要使用它,您的合同地址必须获得***批准,否则任何请求都将退回。

信息

参赛队可以通过官方表格 提交申请,也可以直接联系 Kaia 团队,这取决于哪种方式更方便。

vRNG 合同地址

网络地址应用程序接口 URL
Kaia Mainnet0xf628f7843d94064c5072704a53b9ec455bcc4abbhttps://vrf.proofofplay.com/v1
启明星测试网0xd14d984603b0b7ade91be52f3fc4a917dfa77bcdhttps://staging.vrf.proofofplay.com/v1

使用方法

申请随机数

以下接口提供了一种请求随机数的方法。

您的合约可以调用部署在每个链上的 VRFSystem。 您可以选择提供一个 traceId,它将被注释到每个事件中(如果您的一个事务有许多步骤,用户可以在链上跟踪他们的事务,这很有用)。 这不是必需的,可以留为 0。


// SPDX-License-Identifier: MIT LICENSE
pragma 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 LICENSE
pragma 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,这意味着中继站已经发送了这个随机数。 随机数只能发送一次。

让这个页面变得更好