跳到主要内容

获取随机数教程

简介#

PlatON 内置合约(合约地址:lat1xqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpe9fgva)提供生成 VRF 随机数功能。该合约最多支持返回500个随机数,返回值为[]byte数组,每32个字节表示一个随机数。

入参#

  • input []byte:需要获取的随机数的个数,不得超过500。该入参表示为将一个 uint64 值,填充到32个字节。比如:0x0000000000000000000000000000000000000000000000000000000000000006 表示获取6个随机数

返回值#

  • ret []byte:每32个字节表示一个随机数

代码示例#

Python SDK 调用#

from client_sdk_python import Web3, WebsocketProvider
w3 = Web3(WebsocketProvider('ws://192.168.120.121:7789'))
txn = {    "to": 'lat1xqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpe9fgva',    "data": 0x000000000000000000000000000000000000000000000000000000000000001f4,}
crypt_hex = w3.platon.call(txn).hex()[2:]crypts = [crypt_hex[i: i + 64] for i in range(len(crypt_hex)) if i % 64 == 0]
print(len(crypts), crypts)

Solidity跨合约调用#

// SPDX-License-Identifier: MITpragma solidity ^0.8.0;
/** * 调用PlatON内置合约生成VRF随机数 */contract VRF {
  error InvalidRandomWords(uint32 numWords, uint256 returnValueLength);
  // VrfInnerContract 内置合约地址  address vrfInnerContractAddr = 0x3000000000000000000000000000000000000001;
  // 32个字节表示uint256  uint32 base = 32;
  /**   * 调用 VrfInnerContract 内置合约生成VRF随机数   * @param numWords 随机数的个数   */  function requestRandomWords(uint32 numWords) internal returns (uint256[] memory) {    bytes memory data = abi.encode(numWords);    bytes memory returnValue = assemblyCall(data, vrfInnerContractAddr);
    if (numWords * base != returnValue.length) {        revert InvalidRandomWords(            numWords,            returnValue.length        );    }
    uint256[] memory randomWords = new uint256[](numWords);    for(uint i = 0; i < numWords; i++) {        uint start = i * base;        randomWords[i] = sliceUint(returnValue, start);    }
    return randomWords;  }
  /**   * delegatecall 合约   * @param data 合约input data   * @param addr 合约地址   */    function assemblyCall(bytes memory data, address addr) internal returns (bytes memory) {        uint256 len = data.length;        uint retsize;        bytes memory resval;        assembly {            let result := delegatecall(gas(), addr, add(data, 0x20), len, 0, 0)            retsize := returndatasize()        }        resval = new bytes(retsize);        assembly {            returndatacopy(add(resval, 0x20), 0, returndatasize())        }        return resval;    }
    function sliceUint(bytes memory bs, uint start) internal pure returns (uint256) {        require(bs.length >= start + 32, "slicing out of range");        uint256 x;        assembly {            x := mload(add(bs, add(0x20, start)))        }        return x;    }}