主页 > imtoken钱包手机app > 以太坊中生成随机数的几种方法(含代码)

以太坊中生成随机数的几种方法(含代码)

imtoken钱包手机app 2023-02-20 07:24:59

以太坊上使用的随机数主要有两个来源:链上和链下。 链上生成的核心是解决随机数生成种子的不可预测性。

1.什么是随机数

随机数是由随机数发生器(Random Number Generator)产生的。 随机数分为“真随机数”和“伪随机数”。

1.真随机数

真正的随机数是利用物理现象产生的:如投掷硬币、骰子、轮子、利用电子元件产生噪声、核裂变等。这样的随机数发生器称为物理随机数发生器。 他们的缺点是对技术的要求比较高。 ----百度百科

根据维基百科上的定义,我们可以看出真正的随机数依赖于物理随机数生成器。 使用最多的是由相对先进和复杂的物理过程产生的,例如电子元件中的噪声。

2.伪随机数

真正意义上的随机数(或随机事件)是在一定的生成过程中,按照实验过程中所示的分布概率随机生成的,其结果是不可预测的、不可见的。 计算机中的随机函数是按照一定的算法模拟出来的,结果是确定的、可见的。 可以说,这个可预见的结果出现的概率是100%。 因此,计算机的随机函数产生的“随机数”并不是随机的,而是伪随机数。 ---百度百科

从定义上我们可以了解到,伪随机数其实是有规律的。 只是这个规律周期比较长,但还是可以预见的。 主要原因是伪随机数是计算机用算法模拟出来的。 这个过程不涉及物理过程,自然不可能具有真随机数的特性。

二、以太坊上的随机数 1、为什么没有随机方法?

作为区块链,以太坊是一个确定性的图灵机。 所有分布式节点需要对链上的状态变化达成共识,所有节点上交易的计算结果需要相同。 这意味着以太坊不能涉及随机性。 如果有随机操作码,所有矿工将得到不同的结果,网络将无法达成共识。

2. 两个来源

以太坊上没有随机数方法,但不代表以太坊上没有随机数的需求。 在一些业务场景中,尤其是博彩Dapps,对随机数的需求比较强烈。

比如彩票场景,在现实生活中,彩票开奖是由彩票中心使用彩票机开奖的(貌似是随机生成的号码,但一直被怀疑)。 在区块链上,我们需要中奖的彩票号码是随机生成的,以保证游戏的公平性和公信力。

在以太坊上以太坊总数量是多少,使用的随机数主要有两种来源,一种是在链上生成,另一种是在链下生成。

3.在链上生成随机数

链上生成随机数的核心是在交易被打包到区块之前,尽可能选择不可预知的种子(数)来生成随机数。

接下来几种方法的区别在于随机数生成种子的可预测性。 越不可预测,安全性越高。

1. 不安全的随机数

在一笔交易中,交易是在什么时候、由谁打包进区块的,用户是不知道的,但是一旦打包进区块,这些值就确定了,所以我们可以使用区块打包时间block.timestamp和区块打包难度 block.difficulty 作为种子生成随机数。 0-100随机数生成器代码如下:

function importSeedFromThird() public view returns (uint8) {

以太坊总数量是多少_site163.com 以太坊数量多少_以太坊官网以太坊

return uint8( uint256(keccak256(abi.encodePacked(block.timestamp, block.difficulty))) % 100 ); }

在:

block.timestamp和block.difficulty虽然对普通用户来说不可预测,但对矿工来说是可控的。 在足够利益的驱使下,矿工可以不断地挖掘和打包区块,直到计算出一个对自己有利的随机数,然后对区块进行打包。

针对这种情况以太坊总数量是多少,我们需要加强我们的随机数生成器,可以通过生成业务数据来加强。

2.使用重复哈希来增强安全性

通过对第一类生成的随机数作为数据源反复进行哈希运算,也可以大大增加矿工的攻击成本,增强安全性。

重复散列是多次运行散列函数的行为,使用散列函数一次运行的输出作为下一次运行的输入。 如果初始输入值稍有变化,最终的计算结果就会有很大的不同。

d7414827c4a908520f38df75f02db83b.png

3.利用业务逻辑生成相对安全的随机数

在随机数生成器中加入业务数据,可以解决矿工利用随机数生成器攻击Dapp的问题。 这里我们以彩票合约为例。 用户Tjaden Hess()在stackoverflow上提出了彩票合约更好的解决方案。 它的核心是使用玩家的地址和选择的号码作为随机数生成器的种子。

彩票合约的逻辑是:

彩票合约代码如下:

//THIS CONTRACT IS CONSUMING A LOT OF GAS
//THIS CONTRACT IS ONLY FOR DEMONSTRATING HOW RANDOM NUMBER CAN BE GENERATED
//DO NOT USE THIS FOR PRODUCTION

以太坊总数量是多少_以太坊官网以太坊_site163.com 以太坊数量多少

pragma solidity ^0.4.8; contract Lottery { mapping (uint8 => address[]) playersByNumber ; mapping (address => bytes32) playersHash; uint8[] public numbers; address owner; function Lottery() public { owner = msg.sender; state = LotteryState.FirstRound; } enum LotteryState { FirstRound, SecondRound, Finished } LotteryState state; function enterHash(bytes32 x) public payable {

以太坊官网以太坊_以太坊总数量是多少_site163.com 以太坊数量多少

require(state == LotteryState.FirstRound); require(msg.value > .001 ether); playersHash[msg.sender] = x; } function runSecondRound() public { require(msg.sender == owner); require(state == LotteryState.FirstRound); state = LotteryState.SecondRound; } function enterNumber(uint8 number) public { require(number<=250); require(state == LotteryState.SecondRound); require(keccak256(number, msg.sender) == playersHash[msg.sender]); playersByNumber[number].push(msg.sender); numbers.push(number); } function determineWinner() public { require(msg.sender == owner);

以太坊官网以太坊_site163.com 以太坊数量多少_以太坊总数量是多少

state = LotteryState.Finished; uint8 winningNumber = random(); distributeFunds(winningNumber); selfdestruct(owner); } function distributeFunds(uint8 winningNumber) private returns(uint256) { uint256 winnerCount = playersByNumber[winningNumber].length; require(winnerCount == 1); if (winnerCount > 0) { uint256 balanceToDistribute = this.balance/(2*winnerCount); for (uint i = 0; i<winnerCount; i++) { require(i==0); playersByNumber[winningNumber][i].transfer(balanceToDistribute); } } return this.balance; } function random() private view returns (uint8) {

以太坊总数量是多少_以太坊官网以太坊_site163.com 以太坊数量多少

uint8 randomNumber = numbers[0]; for (uint8 i = 1; i < numbers.length; ++i) { randomNumber ^= numbers[i]; } return randomNumber; } }

彩票合约代码来自:

4.链下生成随机数

链下产生随机数供链上使用的方式主要是通过预言机实现的,预言机分为中心化预言机和去中心化预言机。

1.中心化

使用中心化方法产生随机数的首要前提是保证随机数的可信度。 这里推荐随机。 地址:

2.权力下放

目前有很多提供随机数的oracle服务,比如

五、总结

对于以太坊合约中随机数的使用,从来没有最安全的方式,只有最适合业务场景的方式。

如果业务数据本身是随机的,可以选择使用业务数据作为随机数生成器的种子;

如果业务场景(合约)不涉及利益或者利益驱动比较小,采用区块变量+重复哈希的方式完全可以满足需求;

在一些对安全性要求非常高的场景下,可以选择oracle机提供随机数服务,但会牺牲请求效率。

本文参与登联社区写作激励计划,好文章好收益,欢迎正在阅读的你加入。