现状
- CKB链上几乎没有预言机和VRF。
- 即使是EVM上的Chainlink,如果想每次tx都请求随机数,那也是个不小的开销。
偶然发现有人推荐了这个代码片段: 不受单个矿工控制的链上随机数生成方法
希望大佬分析一下,如果矿池的算力达到50%以上,这个算法有没有潜在的风险?
希望熟悉CKB合约的大佬,能够搬运实现一份分享出来。
核心需求的API就是通过block number获取对应的block hash。
// 原文
作者:33357
设计
既然单个矿工可以控制区块 hash,那么可以使用多个区块 hash 来生成随机数。uint256 有 256 位,可以使用最近的 256 个块的 hash 来组成随机数,并且单个区块 hash 只能决定 256 bit 中的 1 bit。
Solidity 版
pragma solidity ^0.8.20;
contract Random {
// 获取随机数,只能用在 256 个块之前的行为
function getRandomUsedBefore256() external view returns (uint256 random) {
// 遍历最近的 256 个块
for (uint256 i; i < 256; i++) {
// 获得 (block.number - i) 区块的 hash 的最后 1 位数
uint256 bit = uint256(blockhash(block.number - i)) & 1;
// 最后 1 位数依次赋值给 random
random |= (bit << i);
}
}
}
总结
在以上实现中,单个区块的 hash 值只能影响 1 个 bit 的数据。矿工只在 0 和 1 两个结果中选择,对链上随机数生成的影响降到了最小。但由于需要未来 256 个块的 hash 才能生成随机数,因此在所有的投注行为完成之后,必须等待 256 个块才能取随机数,不然随机性是不足的。
需要注意的是,以上所有理论建立在区块生成者是复数并且随机的基础上,如果是单机链,就没有讨论的必要了。