第四个输入
关于provably fair游戏的每一个解释,包括我们的,都提到三个输入:庄家提前承诺的服务器种子,你可以自己设置的客户端种子,以及每次投注时都会增加1的nonce。将它们输入到keyed哈希中,就会产生该轮的随机数。这个描述对于掷硬币是完整的,但对于几乎所有其他情况都不完整,因为哈希只会产生一个数字,而大多数游戏需要多个。
第四个输入是cursor。在本网站,被哈希处理的消息不是
ENGINE-VERIFIED_shared/demoLocal.ts: uAt(pair, cursor) returns u64(HMAC-SHA256(serverSeed, `${clientSeed}-${nonce}-${cursor}`)), described as matching the server’s RandomUtils.generateHash(“clientSeed-nonce-cursor”). _shared/rng.ts: u64 reads the first eight bytes of the digest as hi/2^32 + lo/2^64, “the same single-rounding construction” as the server’s ULong→Double conversion. The nonce is one stream per seed pair across all games: each bet consumes the current nonce and stores nonce + 1.
所以一轮不是一个随机数,而是一个有编号的列表,只要游戏需要,列表中的每一项都在种子对和nonce确定的时刻固定。游戏不是边进行边抽取。它是读取一个已经存在的列表。
每个游戏读取什么
有趣的部分是,列表对每个游戏都不同,每个推导模块在其标题中说明其布局。这是引擎源代码中从种子对绘制的每个原始游戏的cursor流。
| 游戏 | 读取的CURSORS | 它们变成什么 |
|---|---|---|
| Limbo | 0 | 通过0.99 ÷ (1 − u)曲线的一个数字 |
| Roulette | 0 | 口袋:floor(u × 37) |
| Fukubukuro | 0 | 该物品,根据袋子的权重表 |
| 骰宝 | 0, 1, 2 | 三颗骰子 |
| 骰子摇摇(Chinchiro) | 边数 × 9 + 尝试 × 3 + 骰子 | 最多18次:庄家先手后玩家,每方最多投掷三次三颗骰子;凑成一手的投掷结束该方 |
| 硬币翻转 | 每次翻转一个 | 翻转i读取光标i;购买第一枚硬币时每个轮盘面都固定 |
| 签运抽签 | 0,然后1–3,然后4及以后 | 财运等级;赢时三个中奖格;其余填充字符 |
| 塔楼 | 每层一个 | 每层的陷阱格:floor(u × 格子数) |
| 视频扑克 | 5,加上每张替换卡牌一个 | 52张牌上的一个无放回序列;保留所有牌且不再读取光标 |
| 赌场德州扑克 | 最多9 | 玩家1、玩家2、庄家1、庄家2、翻牌1–3、转牌、河牌;转牌和河牌仅在跟注时读取 |
| 二十一点 | 每张牌一个 | 无限靴,牌 = floor(u × 52),按发牌顺序:玩家、庄家明牌、玩家、庄家暗牌,之后每次额外抽取 |
| 安达巴哈 | 0–4,之后每张比赛牌一个 | 两个加强桶、它们的大小、王牌,然后进行比赛直到花色重复 |
| 花火 | 每旋转15个 | 单元 = 转轴 × 3 + 行;免费旋转j从15 + 15j开始读取 |
| 宾果 | 0–24,之后25–62 | 该牌、每列五次抽取;然后38个球 |
Keno和Crash是例外:它们的演示轮使用每张票的哈希链而不是种子对随机数,如下所述。Mines和Plinko由庄家服务结算;mines API注明整个布局来自一个随机数。
引擎验证bingo/derive.ts中的标头注释("光标流:0..24 — 该牌 … 25..62 — 38个球"),hanabi/engine.ts("基础旋转 = 单元0..14 … 免费旋转j = 单元15+15j .. 29+15j"),blackjack/derive.ts("牌i = floor(u × 52) at光标i … 发牌顺序(光标):player1、dealer-up、player2、dealer-hole"),vpoker/derive.ts("前五张是发牌,替换继续相同序列 … 保留所有内容,不再读取光标"),holdem/derive.ts("player1、player2、dealer1、dealer2、flop1、flop2、flop3、turn、river。turn/river光标仅在跟注时消耗"),andar/derive.ts(光标0–4,然后"5.. 每张比赛牌一个光标"),koban/derive.ts("flip i读取光标i"),sicbo/derive.ts("光标0/1/2是三个骰子"),roulette/derive.ts("光标0单独决定口袋:floor(u × 37)"),fuku/derive.ts("光标0单独抽取项目"),omikuji/derive.ts(光标0等级,1..3获胜单元,4.. 填充物);demoLocal.ts rollSide(chinchiro光标 = side*9 + attempt*3 + d),trapAt(塔楼:楼层号是光标),demoLimboBet(uAt(p, 0));mines/minesApi.ts("整个矿布局来自这个随机数")。
该表中有三件事引人注目。首先,处理卡牌的游戏按固定顺序读取每张牌一个光标,这就是为什么二十一点手牌可以从其动作列表中重放:您决定加牌不会创建牌,而是翻转在发牌之前已完成列表中的下一张。其次,几个游戏提前停止读取。视频扑克手牌,如果您保留所有五张牌,永远不会触及光标5;德州扑克弃牌永远不会读取转牌或河牌。这些数字在那里;游戏不需要它们。第三,安达巴哈中的两个加强桶和大吉中的财富等级在卡牌和单元之前被抽取,在流的头部,因此轮次的特殊功能由与普通功能相同的承诺固定。
不放回抽样
0到1之间的均匀数字很容易转换成轮盘口袋:乘以37并向下舍入。甲板更难,因为第二张牌不能是第一张牌。引擎通过其注释称为池跳的方式处理这个问题:保持池中剩余卡牌的列表,使用光标的数字在其中选择一个位置,并将所选卡牌交换到列表的末尾,以便下一次抽取从一个更少的位置选择。视频扑克、赌场德州扑克、安达巴哈和宾果卡都以这种方式抽取,因此没有卡牌或数字在一轮内重复。
二十一点是有意的例外。其靴是无限的:每张牌来自其自己光标的floor(u × 52),同一张牌可以在一手牌中出现两次。这是一个经过设计的选择,具有已发布的成本,在二十一点派彩文章中讨论,它正是光标布局会告诉您但营销页面不会说的东西。
引擎验证vpoker/derive.ts:"卡牌来自52张牌甲板上的一个不放回序列(池跳,每次抽取光标)"。holdem/derive.ts:"一个不放回池跳序列(每次抽取光标)"。bingo/derive.ts:"每列五个池跳抽取"和"38个球,1..75上的池跳"。blackjack/derive.ts:"无限靴:牌i = floor(u × 52) at光标i"。
两个例外
Keno和Crash在演示引擎中完全不读取种子对随机数。Keno使用按票证方案:每张票证获得自己的随机哈希和盐值,十个球中的每一个都通过再次对前一个哈希进行哈希运算来抽取,取前导位作为数字,从不断缩小的40个数字的池中选择。公平性面板从这两个字符串而不是从种子对验证keno票证。Crash遵循bustabit惯例,一条哈希链,其中每一轮的碰撞点通过其自己的链接使用精确整数算术计算。
ENGINE-VERIFIEDdemoLocal.ts kenoDraws: “per-bet randomHash chain + salt (verifiable per ticket via the fairness modal) … Does not touch the seed-pair nonce”; the loop hashes HMAC-SHA256(salt, previous hash) ten times, reads the leading 52 bits and picks index floor(norm × remaining) from a 40-number pool with a swap to the end. rng.ts h52 and the crash comment: “bustabit crash point in hundredths: floor((n·e − h)/(e − h)), e = 2^52, n = 100 … Exact BigInt math to match the server”.
}"not touch seed-pair nonce"; 循环HMAC-SHA256(salt, 前一个哈希)十次,读取前导52位,从40数字池中选择索引floor(norm × 剩余),交换到末尾。rng.ts h52和碰撞注释:
的百分之几的碰撞点:floor((n·e − h)/(e − h)), e = 2^52, n = 100 … 精确BigInt数学以匹配服务器
- The round exists before you act. Every card, ball and reel symbol of a round is a function of the seed pair, the nonce and its cursor position. Hitting, calling or holding chooses which entries get read, not what they contain.
- Your choices cannot change the list, and neither can the house. Once the server seed is committed and the nonce is fixed, no one on either side can alter entry 7 without altering the seed, which would break the fingerprint you were shown.
- A verifier has to read the same list the same way. Recomputing a bingo round means deriving all 63 cursors in the published order; recomputing a Hold’em fold means deriving 7. The seed panel does this in your browser, and the layouts in the table above are what it follows.
- A streak is a list, not a mood. Two rounds share nothing but the seed pair; their nonces differ and so every digest differs. This is the same point the hot hand article makes from the other direction.
Three inputs decide the round. The fourth decides how long the round is.the cursor, in one line
The cursor layouts above are read from the client-side derivation modules that the browser verifier and the demo engine share. The house service is the paying authority; where a comment in the source says a module mirrors the server, that is quoted as written, not certified by us.
FAQ
三个输入决定一轮。第四个决定这一轮持续多久。游标,在一行中
上面的游标布局是从浏览器验证器和演示引擎共享的客户端派生模块中读取的。房间服务是支付权威;当源代码中的注释说模块镜像服务器时,该注释按书写形式引用,而不是由我们认证。
常见问题
在可验证公平的一轮中游标是什么?
一个轮内的计数器。使用服务器种子哈希的消息是
,游标0给出游戏需要的第一个随机数,游标1给出第二个,以此类推。需要一个数字的游戏只读取游标0。
游标与随机数有什么区别?
随机数计数轮数,每次在所有原始产品中投注时增加1。游标在一轮内计算抽取次数,每轮重新开始为0。与种子对一起,它们标识站点曾产生的每个随机数。
所有游戏都使用光标方案吗?
Keno和Crash改用哈希链:keno将每张票的随机哈希和盐进行十次哈希运算,crash则使用精确整数算术跟踪bustabit链。公平性面板从显示的字符串中验证每一个。
来源和参考
- Betkyo引擎源代码:_shared/demoLocal.ts(uAt、rollSide、trapAt、kenoDraws)、_shared/rng.ts(u64、h52、crash point)以及bingo、hanabi、blackjack、vpoker、holdem、andar、koban、sicbo、roulette、fuku和omikuji的衍生模块
- RFC 2104 — HMAC:用于消息验证的密钥哈希
- Bustabit可验证公平方案(引擎镜像的crash点构造)
本文中的游戏