You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pact中如何生成伪随机数?now()/rand()为何违反其核心原则

Pact未原生提供RAND()、NOW()函数的底层原因

核心原因是确定性执行是区块链智能合约的核心共识要求,和Haskell语言本身的能力无关,开放这类非确定性函数会直接破坏全网共识基础。

确定性是合约执行的硬性约束

区块链网络中所有独立节点必须对同一笔交易的执行结果得到完全一致的输出,才能对账本状态达成共识。任何会导致不同节点执行同一段代码得到不同结果的函数,都不能作为原生函数开放:

  • 针对RAND()类随机函数:真随机函数的输出完全依赖节点本地运行环境,不同节点执行时会得到完全不同的结果,直接造成链状态分叉;哪怕是伪随机函数,如果种子取自节点本地内存、系统状态而非全局共识数据,同样会触发执行结果不一致。
  • 针对NOW()类取当前时间的函数:不同节点的本地系统时钟天然存在毫秒到秒级的偏差,如果合约直接读取节点本地时间做逻辑判断(比如骰子点数计算、活动截止判定),同一笔交易在不同节点会走入不同分支,直接导致共识失效。

Pact现有相关能力的设计逻辑

本地repl环境下chain-data时间固定为初始纪元值的表现,是刻意设计的行为,不是bug:

  • 链上运行环境中,chain-data返回的时间戳是出块节点写入区块头的固定值,该区块内所有交易在所有节点上执行时,拿到的时间值完全一致,满足确定性要求。本地repl环境固定时间值,就是为了严格模拟链上的确定性执行特征,避免本地测试时出现“本地跑通、上链逻辑不一致”的隐性问题。
  • Pact链上环境本身不内置可验证随机源,所有随机类逻辑必须通过外部传入可验证的熵值实现:可以是前端传入的用户签名随机盐、预言机提交的可验证随机数(VRF)结果,在合约内对传入值做哈希运算后取模得到最终结果。“传入唯一时间值哈希后对6取模模拟掷骰子”的方案,本质就是把非确定性的外部熵转化为所有节点可验证的确定输入,完全符合Pact的安全模型。

直接封装Haskell侧相关函数的风险

Pact解释器本身由Haskell实现,但Haskell标准库中的getCurrentTime、randomIO都属于IO范畴的非纯函数,执行结果依赖节点本地的非共识状态:

  • 如果直接把这类非纯函数封装为Pact核心函数,会直接打破Pact“执行结果仅依赖链上公共状态、交易显式传入参数”的纯函数式安全模型,等于给节点运营商留下了恶意篡改执行结果的后门:节点可以通过调整本地时钟、操控随机数生成器的方式,让合约输出对自己有利的结果,普通用户完全无法验证结果的合法性。

本地开发测试骰子类游戏时,可以直接在repl测试脚本中手动传入自定义的模拟时间戳、随机盐作为交易参数,不需要依赖原生NOW()/RAND()能力,测试逻辑和链上实际运行逻辑完全一致。

内容的提问来源于stack exchange,提问作者KDAbet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 07:30:50