1、随机数基础:什么是真随机与伪随机,链上为什么需要随机数,常见的链上随机数应用场景
各位同学好,我是你们的老朋友。今天咱们正式开课,聊聊随机数。
说实话,我入行做区块链安全那会儿,第一个让我头疼的问题就是随机数。为什么?因为链上环境太特殊了——所有节点都在执行同一段代码,所有数据都是公开的。你想想看,在这种环境下要生成一个「别人猜不到」的数字,是不是有点反直觉?
好,咱们一步步来。
1.1 真随机 vs 伪随机:到底差在哪?
先问个问题:你手机上的「随机播放」是真的随机吗?
不是。它只是算法算出来的一个序列,看起来没有规律而已。这就是伪随机数。
伪随机数的核心特征是:只要知道种子(seed)和算法,就能复现整个序列。比如经典的线性同余生成器:
// 线性同余生成器 (LCG)
next = (a * current + c) % m
你给个初始值 current,后面每个数都是确定的。这在普通软件里够用了,但在区块链上——嗯,问题很大。
那什么是真随机数?
真随机数来源于物理世界的不可预测事件。比如:
- 放射性衰变的时间间隔
- 大气噪声的波动
- 量子力学中的测量结果
这些事件在理论上就是不可预测的。我曾在一次安全审计中见过一个项目,他们用「鼠标移动轨迹」来生成种子——这其实也算一种物理随机源,但问题是链上没法复现这个过程。
核心区别一句话总结:
伪随机 = 算法 + 种子 → 可复现
真随机 = 物理事件 → 不可复现
1.2 链上为什么需要随机数?
你可能会想:普通程序里用随机数很正常,但区块链上每一步都要验证,要随机数干嘛?
我举个例子你就明白了。
假设你做了一个链上抽奖游戏。用户买彩票,开奖时从所有买家中随机选一个中奖者。如果这个「随机」过程可以被预测,那会怎样?
——矿工可以提前算出谁中奖,然后自己买那张彩票。或者更狠一点,直接回滚交易重试。
这就是为什么链上随机数必须满足两个条件:
- 不可预测性:在生成之前,任何人都无法知道结果
- 可验证性:生成之后,任何人都能验证这个结果是公平的
说白了,链上随机数不是为了「随机」而随机,而是为了公平。
个人经验:我审计过一个DeFi项目,他们用 block.timestamp 做随机种子。结果呢?矿工可以微调时间戳来操控结果。这种漏洞我见过不下十次,每次都是血泪教训。
1.3 常见的链上随机数应用场景
好,理论讲完了,咱们看看实际中哪些地方需要随机数。
场景一:NFT 铸造
这是最典型的场景。你铸造一个NFT,它的稀有度、属性、甚至图片本身都是随机生成的。比如:
- 某NFT项目有10000个角色,其中1%是传说级
- 铸造时随机决定你拿到的是普通、稀有还是传说
如果随机数被操控,那传说级NFT就全被内部人拿走了。我见过一个项目,他们的随机数生成器用的是 keccak256(abi.encodePacked(blockhash, msg.sender))——这其实是可以被矿工预测的。
场景二:链上游戏
不管是卡牌游戏、回合制战斗还是盲盒机制,随机数都是核心。比如:
- 《Axie Infinity》中的基因遗传
- 《Dark Forest》中的星球生成
- 各种「抽卡」游戏中的掉落率
我曾经审计过一个链游,他们用 block.difficulty 做随机源。嗯,这个值在以太坊上是可以被矿工轻微影响的。结果就是——高等级装备永远被同一个地址抽到。
场景三:抽奖与竞拍
链上抽奖、盲拍、荷兰拍等场景也依赖随机数。比如:
- 彩票开奖:从所有参与者中随机选一个
- 公平分发:按随机顺序分配稀缺资源
- 治理投票:随机选取验证节点
避坑指南:我曾经接手过一个抽奖合约,它用 blockhash(block.number - 1) 作为随机种子。看起来没问题对吧?但攻击者可以写一个合约,在同一个区块内先调用抽奖函数,根据结果决定是否参与。这就是「抢跑攻击」的典型手法。
1.4 一个小总结
好了,咱们今天的内容就这些。总结一下:
| 概念 | 特点 | 链上适用性 |
|---|---|---|
| 真随机 | 物理源、不可复现 | 难以直接获取 |
| 伪随机 | 算法驱动、可复现 | 需要小心设计 |
| 链上随机需求 | 不可预测 + 可验证 | 必须满足两者 |
下一章,我会带你深入分析「为什么简单的随机数方案在链上都不安全」,以及攻击者到底是怎么钻空子的。到时候我会拿几个真实漏洞案例来讲,保证让你印象深刻。
今天就到这儿。记住:链上随机数不是技术问题,是博弈问题。