@dust-dice/verifier 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/verify.js ADDED
@@ -0,0 +1,577 @@
1
+ #!/usr/bin/env node
2
+ // Copyright (C) Shielded Technologies
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ /**
5
+ * The settlement verifier: replay a whole game from the chain and nothing else.
6
+ *
7
+ * npm run verify -w cli -- <table-address>
8
+ *
9
+ * WHAT IT IS GIVEN: a contract address. Nothing else -- no seeds, no player secrets, no run
10
+ * state, no artefacts from the process that played the game. It talks to a public indexer.
11
+ * Anyone can run it against anyone's table.
12
+ *
13
+ * WHAT IT PROVES. Once `settle` has revealed the seed, every die of every roll is a
14
+ * deterministic function of public data, so the whole game can be recomputed and compared:
15
+ *
16
+ * 1. the revealed seed opens the commitment the table was deployed with -- which was made
17
+ * before any player existed, so the operator could not have chosen it to suit the dice;
18
+ * 2. every roll of every turn, re-derived from (tableId, seed, mixed entropy, round, roll
19
+ * index) through the same byte ladder the circuit uses, matches the dice the chain
20
+ * published -- and every REROLL is re-derived under the hold mask the player actually sent,
21
+ * merged left to right over the rerolled positions;
22
+ * 3. the ROUND DIGEST CHAIN reproduces exactly, from the genesis digest through every join and
23
+ * every round close. This is the part that makes 2 worth anything: every seat in round r
24
+ * hashes the digest as it stood when round r OPENED, so no roll can be checked without
25
+ * having replayed every earlier round in order;
26
+ * 4. every score, recomputed from the dice with api/src/rules.ts -- the contract-canonical
27
+ * rules engine, not the circuit -- matches the scorecard the chain holds, box by box,
28
+ * including the upper bonus and the Yahtzee bonuses;
29
+ * 5. the winner the tie-break selects, among SURVIVORS, is the seat the chain paid;
30
+ * 6. the settle transaction spent ZERO user inputs and created exactly the two expected
31
+ * outputs, to the addresses recorded at join and at construction.
32
+ *
33
+ * WHAT IT CANNOT PROVE, stated honestly: that each seat's published entropy really is
34
+ * `H(sk_s, tableId, round)` for the secret committed at join. That binding is what the
35
+ * `playerMove` circuit asserts in zero knowledge, and it is unverifiable from public data by
36
+ * construction -- if it were verifiable, `sk_s` would be public. The verifier confirms that the
37
+ * chain accepted a proof of it, which is the whole point of the proof existing.
38
+ *
39
+ * -------------------------------------------------------------------------------------------
40
+ * HOW IT READS A GAME THAT HAS NO CURSOR
41
+ * -------------------------------------------------------------------------------------------
42
+ *
43
+ * The indexer gives the table's whole action list -- one entry per transaction, with an entry
44
+ * point and a block height -- and the contract's public state can be read at any block. So the
45
+ * verifier walks the actions in order and reads the state each one produced.
46
+ *
47
+ * TWO THINGS ARE HARDER THAN THEY WERE, and both are solved by diffing state rather than by
48
+ * being told:
49
+ *
50
+ * - `playerMove` is ONE entry point for THREE moves. Which one it was is recovered from the
51
+ * seat's stage transition: idle -> awaitRoll1 is an open, rolled{1,2} -> awaitRoll{2,3} is a
52
+ * hold, rolled{1,2,3} -> idle is a score. The verifier also has to work out WHICH SEAT
53
+ * moved, which it does by finding the one seat whose entry changed.
54
+ * - the CATEGORY a player chose is not stored in the ledger (it is a circuit argument), so it
55
+ * is recovered by diffing the seat's scorecard across the score. That is a stronger check
56
+ * than being told: the verifier finds the box that changed AND recomputes what belongs in
57
+ * it.
58
+ *
59
+ * The HOLD MASKS, by contrast, are readable: `seatTurn.hold1` and `hold2` are ledger state, so
60
+ * the verifier reads the mask the player sent and re-derives the reroll under it. A mask that
61
+ * did not produce the published dice fails check 2.
62
+ */
63
+ import { applyScore, CATEGORY_COUNT, emptyScorecard, grandTotal, } from '@dust-dice/api';
64
+ import { emptyRoundResult, firstRollTs, genesisDigestTs, joinDigestTs, mixEntropyTs, rerollUnderMaskTs, roundDigestTs, seedCommitmentTs, } from '@dust-dice/contract';
65
+ import { setNetworkId } from '@midnight-ntwrk/midnight-js-network-id';
66
+ import { userAddressBytes } from '@dust-dice/api/node';
67
+ import { NETWORK } from "./config.js";
68
+ import { diceToArray, FINAL_ROUND, readTableLedger, ROUND_COUNT, STAGE, Table, } from "./contracts.js";
69
+ import { contractActions, sumNative, sumNativeFor, transactionByHash, } from "./indexer.js";
70
+ const hex = (b) => Buffer.from(b).toString('hex');
71
+ const same = (a, b) => hex(a) === hex(b);
72
+ const MAX_SEATS = 6;
73
+ class Checks {
74
+ failures = [];
75
+ passes = 0;
76
+ verbose;
77
+ constructor(verbose) {
78
+ this.verbose = verbose;
79
+ }
80
+ ok(what, condition, detail = '') {
81
+ if (condition) {
82
+ this.passes += 1;
83
+ if (this.verbose)
84
+ console.log(` PASS ${what}`);
85
+ }
86
+ else {
87
+ this.failures.push(`${what}${detail ? ` -- ${detail}` : ''}`);
88
+ console.log(` FAIL ${what}${detail ? ` -- ${detail}` : ''}`);
89
+ }
90
+ }
91
+ get failed() {
92
+ return this.failures;
93
+ }
94
+ get count() {
95
+ return this.passes + this.failures.length;
96
+ }
97
+ summary() {
98
+ console.log(`\n${this.failures.length === 0 ? 'VERIFIED' : 'VERIFICATION FAILED'}: ` +
99
+ `${this.passes} checks passed, ${this.failures.length} failed`);
100
+ for (const f of this.failures)
101
+ console.log(` - ${f}`);
102
+ }
103
+ }
104
+ /**
105
+ * Read the table's whole history: every action, and the state it left behind.
106
+ *
107
+ * One `queryContractState` per action, pinned to that action's block. `contractStateObservable`
108
+ * is not usable for this -- it misses rapid successive updates and its first emission may
109
+ * predate the write being read (bugs-found.md §0 #10).
110
+ */
111
+ async function readHistory(address) {
112
+ const actions = await contractActions(address);
113
+ const steps = [];
114
+ for (const action of actions) {
115
+ if (action.kind === 'ContractDeploy')
116
+ continue;
117
+ steps.push({ action, led: await readTableLedger(address, action.blockHeight) });
118
+ }
119
+ // The replay reads each step's PREVIOUS state to learn what the call was told (which seat was
120
+ // at which stage, which boxes were filled, which mask was pending). That is only sound while
121
+ // at most one call to this table lands per block: two in one block would both resolve to the
122
+ // state after both, and the second step's "before" would be wrong.
123
+ //
124
+ // A table CAN take several calls in one block -- that is the whole point of the concurrency
125
+ // work, measured at six in docs/concurrency-probe.md -- so this is a real limitation of
126
+ // per-block state replay and not a property of the contract. The demo driver is strictly
127
+ // sequential precisely so that its games stay verifiable by this method; a table played by six
128
+ // independent clients may not be. Saying so is much better than silently producing wrong
129
+ // answers.
130
+ const heights = steps.map((s) => s.action.blockHeight);
131
+ const collisions = heights.filter((h, i) => heights.indexOf(h) !== i);
132
+ if (collisions.length > 0) {
133
+ throw new Error(`two or more calls to this table share block ${[...new Set(collisions)].join(', ')}. ` +
134
+ 'The per-block state replay cannot separate them, so this table cannot be verified by ' +
135
+ 'this method. (This is a limitation of the verifier, not a fault in the game.)');
136
+ }
137
+ return steps;
138
+ }
139
+ /** The seat whose `seatTurn` entry changed between two states, or -1. */
140
+ function movedSeat(prev, led) {
141
+ for (let s = 0; s < Number(led.seatCount); s++) {
142
+ const a = prev.seatTurn.lookup(BigInt(s));
143
+ const b = led.seatTurn.lookup(BigInt(s));
144
+ if (a.stage !== b.stage)
145
+ return s;
146
+ }
147
+ // A score returns the stage to idle from a non-idle value, so it is caught above. A move that
148
+ // changed nothing at all is not a move.
149
+ return -1;
150
+ }
151
+ function seatCard(led, seat) {
152
+ const c = led.seatCard.lookup(BigInt(seat));
153
+ return {
154
+ scores: c.filled.map((f, i) => (f ? Number(c.scores[i]) : null)),
155
+ yahtzeeBonuses: Number(c.yahtzeeBonuses),
156
+ };
157
+ }
158
+ function arrayEq(a, b) {
159
+ return a.length === b.length && a.every((x, i) => x === b[i]);
160
+ }
161
+ /** All six slots' contributions to a round digest, read at the block the round closed. */
162
+ function roundResults(led) {
163
+ return Array.from({ length: MAX_SEATS }, (_, s) => {
164
+ if (s >= Number(led.seatCount))
165
+ return emptyRoundResult();
166
+ const p = led.seatProgress.lookup(BigInt(s));
167
+ return { dice: diceToArray(p.dice), out: p.eliminated };
168
+ });
169
+ }
170
+ async function verify(address, verbose) {
171
+ // `userAddressBytes` decodes bech32m, which is network-tagged; nothing here builds a wallet,
172
+ // so the network id has to be set explicitly.
173
+ setNetworkId(NETWORK.networkId);
174
+ const c = new Checks(verbose);
175
+ console.log(`Verifying table ${address}\n`);
176
+ const final = await readTableLedger(address);
177
+ const seatCount = Number(final.seatCount);
178
+ const tableId = final.tableId;
179
+ console.log('── table, as deployed ──');
180
+ console.log(` tableId ${hex(tableId)}`);
181
+ console.log(` tier ${final.tier} seats ${final.seatLimit}`);
182
+ console.log(` seedCommitment ${hex(final.seedCommitment)}`);
183
+ console.log(` phase ${Table.Phase[final.phase]}`);
184
+ // The mode changes what "verified" covers (docs/fast-turn-design.md): dice and payouts verify
185
+ // identically in both, but hold-before-reveal ORDERING is chain-proven only on an on-chain-mode
186
+ // table — a fast table's turn lands as one composed transaction, so its ordering is the
187
+ // operator's attestation.
188
+ console.log(` mode ${final.fastMode ? 'FAST (turn ordering operator-attested)' : 'on-chain (ordering chain-proven)'}`);
189
+ c.ok('the table reached settlement', final.phase === Table.Phase.settled, `phase is ${Table.Phase[final.phase]}; only a settled table reveals its seed`);
190
+ if (final.phase !== Table.Phase.settled) {
191
+ c.summary();
192
+ return 1;
193
+ }
194
+ // ---------------------------------------------------------------- 1. the seed opens the commit
195
+ console.log('\n── the revealed seed ──');
196
+ const seed = final.revealedSeed;
197
+ console.log(` seed ${hex(seed)}`);
198
+ // An all-zero `revealedSeed` on a SETTLED table is not a missing field -- it is the contract's
199
+ // marker for a game that was force-settled past the table deadline with no valid seed. The
200
+ // payout was still fully determined by public state and every roll was proven in its own
201
+ // transaction while the game was live, but the game cannot be REPLAYED offline, which is
202
+ // exactly what this tool does. Say so and stop, rather than reporting a failure that suggests
203
+ // the chain did something wrong.
204
+ if (seed.every((b) => b === 0)) {
205
+ console.log('\n This table was FORCE-SETTLED: the operator never revealed a valid seed before the\n' +
206
+ ' table deadline, so `settle` paid the winner computed from public state and left\n' +
207
+ ' `revealedSeed` at zero. The rolls cannot be re-derived offline. Nothing here is\n' +
208
+ ' wrong; this game is simply unverifiable after the fact.');
209
+ c.summary();
210
+ return 1;
211
+ }
212
+ c.ok('the revealed seed opens the commitment the table was deployed with', same(seedCommitmentTs(tableId, seed), final.seedCommitment), `H(tableId, seed) = ${hex(seedCommitmentTs(tableId, seed))}`);
213
+ // ------------------------------------------------------------------------- walk the public log
214
+ const steps = await readHistory(address);
215
+ console.log(`\n── the public log: ${steps.length} calls ──`);
216
+ let digest = genesisDigestTs(tableId);
217
+ const seats = Array.from({ length: seatCount }, () => ({
218
+ card: emptyScorecard(),
219
+ roll: [1, 1, 1, 1, 1],
220
+ rolls: 0,
221
+ eliminated: false,
222
+ finishedAtRound: Number.POSITIVE_INFINITY,
223
+ }));
224
+ let joins = 0;
225
+ let opens = 0;
226
+ let holds = 0;
227
+ let scores = 0;
228
+ let rollChecks = 0;
229
+ let closes = 0;
230
+ let eliminations = 0;
231
+ /** State immediately before the step being examined -- the previous step's, or the deploy's. */
232
+ const before = (i) => (i === 0 ? undefined : steps[i - 1].led);
233
+ for (let i = 0; i < steps.length; i++) {
234
+ const { action, led } = steps[i];
235
+ const prev = before(i);
236
+ switch (action.entryPoint) {
237
+ case 'join': {
238
+ // Seat order is join order, so the seat this call took is the one that did not exist
239
+ // before it. The digest binds the seat's payout address and its entropy commitment.
240
+ const seat = Number(led.seatCount) - 1;
241
+ const id = led.seatIdentity.lookup(BigInt(seat));
242
+ digest = joinDigestTs(digest, seat, id.addr.bytes, id.keyCommit);
243
+ joins += 1;
244
+ c.ok(`join ${seat}: digest chain`, same(led.roundDigest, digest), `chain ${hex(led.roundDigest)} vs replay ${hex(digest)}`);
245
+ c.ok(`join ${seat}: pot rose by exactly the tier`, led.pot === final.tier * BigInt(seat + 1), `pot ${led.pot}`);
246
+ break;
247
+ }
248
+ case 'playerMove': {
249
+ if (!prev)
250
+ break;
251
+ const seat = movedSeat(prev, led);
252
+ if (seat < 0) {
253
+ c.ok('playerMove changed exactly one seat', false, 'no seat changed stage');
254
+ break;
255
+ }
256
+ const round = Number(prev.openRound);
257
+ const wasStage = Number(prev.seatTurn.lookup(BigInt(seat)).stage);
258
+ const nowStage = Number(led.seatTurn.lookup(BigInt(seat)).stage);
259
+ const r = seats[seat];
260
+ if (wasStage === STAGE.idle && nowStage === STAGE.awaitRoll1) {
261
+ // OPEN. The turn's mixed entropy is not latched until roll 1, but the entropy the
262
+ // player declared is on chain now, and it is what roll 1 will hash.
263
+ opens += 1;
264
+ r.rolls = 0;
265
+ c.ok(`seat ${seat} r${round}: open records the round`, Number(led.seatTurn.lookup(BigInt(seat)).round) === round);
266
+ c.ok(`seat ${seat} r${round}: open clears both hold masks`, led.seatTurn.lookup(BigInt(seat)).hold1.bits.every((b) => !b) &&
267
+ led.seatTurn.lookup(BigInt(seat)).hold2.bits.every((b) => !b));
268
+ }
269
+ else if (nowStage === STAGE.awaitRoll2 || nowStage === STAGE.awaitRoll3) {
270
+ // HOLD. The mask is ledger state, so it is read rather than guessed -- and the reroll
271
+ // it produces is checked against it when the resolve lands.
272
+ holds += 1;
273
+ const which = nowStage === STAGE.awaitRoll2 ? 'hold1' : 'hold2';
274
+ const mask = led.seatTurn.lookup(BigInt(seat))[which].bits;
275
+ c.ok(`seat ${seat} r${round}: ${which} landed in its own cell`, mask.length === 5, `mask ${mask.map((b) => (b ? 1 : 0)).join('')}`);
276
+ }
277
+ else if (nowStage === STAGE.idle) {
278
+ // SCORE. The category is recovered by diffing the card, then recomputed.
279
+ scores += 1;
280
+ const chainBefore = seatCard(prev, seat);
281
+ const chainAfter = seatCard(led, seat);
282
+ const category = chainAfter.scores.findIndex((s, k) => s !== null && chainBefore.scores[k] === null);
283
+ c.ok(`seat ${seat} r${round}: score filled exactly one new category`, category >= 0 &&
284
+ chainAfter.scores.filter((s) => s !== null).length ===
285
+ chainBefore.scores.filter((s) => s !== null).length + 1, `category index ${category}`);
286
+ if (category >= 0) {
287
+ // The dice scored are the ones the replay derived for this turn -- NOT read from the
288
+ // chain. That is what makes this a check of the dice rather than of the bookkeeping.
289
+ const dice = r.roll;
290
+ // Recompute the placement with the CONTRACT-CANONICAL rules engine. If the chain and
291
+ // api/src/rules.ts ever disagree about a box, one of them is wrong -- and the rules
292
+ // engine is the specification.
293
+ r.card = applyScore(r.card, category, dice);
294
+ for (let k = 0; k < CATEGORY_COUNT; k++) {
295
+ c.ok(`seat ${seat} r${round}: box ${k}`, r.card.scores[k] === chainAfter.scores[k], `replay ${r.card.scores[k]} vs chain ${chainAfter.scores[k]}`);
296
+ }
297
+ c.ok(`seat ${seat} r${round}: running total`, BigInt(grandTotal(r.card)) === led.seatProgress.lookup(BigInt(seat)).total, `replay ${grandTotal(r.card)} vs chain ${led.seatProgress.lookup(BigInt(seat)).total}`);
298
+ c.ok(`seat ${seat} r${round}: the dice the chain stored are the ones replayed`, arrayEq(diceToArray(led.seatProgress.lookup(BigInt(seat)).dice), dice), `chain ${diceToArray(led.seatProgress.lookup(BigInt(seat)).dice)} vs replay ${dice}`);
299
+ }
300
+ c.ok(`seat ${seat} r${round}: score advances the seat past the round`, Number(led.seatProgress.lookup(BigInt(seat)).round) === round + 1);
301
+ if (round === FINAL_ROUND)
302
+ r.finishedAtRound = round;
303
+ }
304
+ else {
305
+ c.ok(`seat ${seat} r${round}: recognised playerMove`, false, `stage ${wasStage} -> ${nowStage}`);
306
+ }
307
+ break;
308
+ }
309
+ case 'resolveRoll1':
310
+ case 'resolveReroll': {
311
+ if (!prev)
312
+ break;
313
+ const seat = movedSeat(prev, led);
314
+ if (seat < 0) {
315
+ c.ok('a resolve changed exactly one seat', false, 'no seat changed stage');
316
+ break;
317
+ }
318
+ const round = Number(prev.openRound);
319
+ const r = seats[seat];
320
+ const turn = led.seatTurn.lookup(BigInt(seat));
321
+ const chainDice = diceToArray(turn.roll);
322
+ if (action.entryPoint === 'resolveRoll1') {
323
+ // Roll 1 hashes the seat's declared entropy against the digest FROZEN AT ROUND OPEN --
324
+ // which is the digest the replay is holding right now, because it only advances at a
325
+ // closeRound. Getting that ordering wrong is the easiest way to make an unverifiable
326
+ // game, so the latched value is checked too.
327
+ const entropy = prev.seatTurn.lookup(BigInt(seat)).entropy;
328
+ const mixed = mixEntropyTs(entropy, digest);
329
+ r.mixed = mixed;
330
+ c.ok(`seat ${seat} r${round}: mixed entropy`, same(turn.mixed, mixed), `chain ${hex(turn.mixed)} vs replay ${hex(mixed)}`);
331
+ const expected = firstRollTs(tableId, seed, mixed, round);
332
+ c.ok(`seat ${seat} r${round}: roll 1`, arrayEq(chainDice, expected), `chain ${chainDice} vs replay ${expected}`);
333
+ r.roll = expected;
334
+ r.rolls = 1;
335
+ }
336
+ else {
337
+ // WHICH reroll this is comes from the seat's stage before the call -- the same place
338
+ // the circuit reads it. There is one entry point for both rerolls, so the log does not
339
+ // say, and inferring it from the stage is both necessary and a stronger check.
340
+ const step = Number(prev.seatTurn.lookup(BigInt(seat)).stage) === STAGE.awaitRoll2 ? 1 : 2;
341
+ const mask = (step === 1
342
+ ? prev.seatTurn.lookup(BigInt(seat)).hold1
343
+ : prev.seatTurn.lookup(BigInt(seat)).hold2).bits;
344
+ if (!r.mixed) {
345
+ c.ok(`seat ${seat} r${round}: roll ${step + 1} has a latched mix`, false);
346
+ break;
347
+ }
348
+ // THE reroll check: the fresh roll is consumed LEFT TO RIGHT over the positions the
349
+ // mask does not keep. A verifier that merged positionally would agree on every mask
350
+ // whose held set is a prefix and diverge on every other one.
351
+ const expected = rerollUnderMaskTs(tableId, seed, r.mixed, round, step, mask, r.roll);
352
+ c.ok(`seat ${seat} r${round}: roll ${step + 1} under mask ${mask.map((b) => (b ? 1 : 0)).join('')}`, arrayEq(chainDice, expected), `chain ${chainDice} vs replay ${expected}`);
353
+ // A held die must be byte-identical across the reroll -- the property the mask exists
354
+ // for, checked independently of the derivation above.
355
+ for (let d = 0; d < 5; d++) {
356
+ if (mask[d] === true) {
357
+ c.ok(`seat ${seat} r${round}: held die ${d} survived roll ${step + 1}`, chainDice[d] === r.roll[d], `${r.roll[d]} -> ${chainDice[d]}`);
358
+ }
359
+ }
360
+ r.roll = expected;
361
+ r.rolls += 1;
362
+ }
363
+ c.ok(`seat ${seat} r${round}: dice are all in 1..6`, chainDice.every((d) => d >= 1 && d <= 6), chainDice.join(','));
364
+ c.ok(`seat ${seat} r${round}: no resolve moved the round digest`, same(led.roundDigest, digest), 'only closeRound advances it');
365
+ rollChecks += 1;
366
+ break;
367
+ }
368
+ case 'closeRound': {
369
+ if (!prev)
370
+ break;
371
+ const round = Number(prev.openRound);
372
+ // The ONE place the digest advances. All six slots, in SEAT ORDER, read at this block --
373
+ // which is what makes the replay independent of the order the chain saw the moves in.
374
+ digest = roundDigestTs(digest, round, seatCount, roundResults(led));
375
+ closes += 1;
376
+ c.ok(`round ${round}: digest chain`, same(led.roundDigest, digest), `chain ${hex(led.roundDigest)} vs replay ${hex(digest)}`);
377
+ c.ok(`round ${round}: openRound advanced`, Number(led.openRound) === round + 1, `chain ${led.openRound}`);
378
+ break;
379
+ }
380
+ case 'eliminate': {
381
+ if (!prev)
382
+ break;
383
+ const round = Number(prev.openRound);
384
+ let seat = -1;
385
+ for (let s = 0; s < seatCount; s++) {
386
+ if (!prev.seatProgress.lookup(BigInt(s)).eliminated &&
387
+ led.seatProgress.lookup(BigInt(s)).eliminated) {
388
+ seat = s;
389
+ }
390
+ }
391
+ if (seat < 0) {
392
+ c.ok('eliminate marked exactly one seat', false);
393
+ break;
394
+ }
395
+ eliminations += 1;
396
+ seats[seat].eliminated = true;
397
+ seats[seat].finishedAtRound = Number.POSITIVE_INFINITY;
398
+ // The penalty rule, recomputed rather than read. A timeout charges round + 1; a
399
+ // voluntary resignation is charged one round less — the open round does not count
400
+ // (`voluntary` is a public circuit argument, but the cheapest verification is the money
401
+ // itself: exactly one of the two schedules matches the redeemable delta, and which one
402
+ // tells us how the seat left).
403
+ const timeoutPenalty = (final.tier * BigInt(round + 1)) / 13n;
404
+ const resignPenalty = (final.tier * BigInt(round)) / 13n;
405
+ const delta = led.seatRedeemable.lookup(BigInt(seat)) - prev.seatRedeemable.lookup(BigInt(seat));
406
+ const penalty = delta === final.tier - resignPenalty ? resignPenalty : timeoutPenalty;
407
+ const how = penalty === resignPenalty && resignPenalty !== timeoutPenalty ? 'resigned' : 'timed out';
408
+ const refund = final.tier - penalty;
409
+ c.ok(`seat ${seat}: eliminated at round ${round} keeps tier - penalty`, delta === refund, `expected +${refund} (penalty ${penalty}, ${how})`);
410
+ c.ok(`seat ${seat}: the penalty stayed in the pot`, led.pot === prev.pot - refund, `pot ${prev.pot} -> ${led.pot}, expected -${refund}`);
411
+ c.ok(`seat ${seat}: carries the never-finished sentinel`, led.seatProgress.lookup(BigInt(seat)).finishedAtRound === 65535n);
412
+ console.log(` (seat ${seat} ${how} at round ${round}: penalty ${penalty})`);
413
+ break;
414
+ }
415
+ case 'settle':
416
+ case 'redeem':
417
+ case 'abortTable':
418
+ // Handled below, against the final state and the transaction.
419
+ break;
420
+ default:
421
+ console.log(` (unrecognised entry point '${action.entryPoint ?? '?'}' -- ignored)`);
422
+ }
423
+ // The custody invariant, at every single step: while the table holds the money, every atom
424
+ // it ever received is either in the pot or owed to a seat. The contract asserts this
425
+ // in-circuit at three points; this checks it after every transaction, from public state.
426
+ if (led.phase === Table.Phase.filling || led.phase === Table.Phase.playing) {
427
+ let owed = 0n;
428
+ let paid = 0n;
429
+ for (let s = 0; s < MAX_SEATS; s++) {
430
+ owed += led.seatRedeemable.lookup(BigInt(s));
431
+ paid += led.seatPaid.lookup(BigInt(s));
432
+ }
433
+ c.ok(`step ${i} (${action.entryPoint}): custody invariant`, led.pot + owed + paid === final.tier * led.seatCount, `pot ${led.pot} + owed ${owed} + paid ${paid} != tier x ${led.seatCount}`);
434
+ }
435
+ }
436
+ console.log(`\n── replayed ${joins} joins, ${opens} opens, ${holds} holds, ${scores} scores, ` +
437
+ `${rollChecks} rolls, ${closes} round closes, ${eliminations} eliminations ──`);
438
+ c.ok('every seat joined', joins === seatCount, `${joins} joins for ${seatCount} seats`);
439
+ // On a walkover the survivor's in-flight turn is legitimately cut off by the settle: opened,
440
+ // dice possibly delivered, never scored. At most ONE such dangling open, and only theirs.
441
+ const danglingAllowed = seats.filter((s) => !s.eliminated).length === 1 ? 1 : 0;
442
+ c.ok('every live seat scored in every round', opens - scores <= danglingAllowed && opens >= scores, `${opens} turns opened, ${scores} scored (walkover allows ${danglingAllowed} dangling)`);
443
+ // A settled table need not have closed all thirteen rounds any more: the walkover (settle's
444
+ // `activeSeats == 1` disjunct) legitimately ends a game the moment one active seat remains.
445
+ // What must still hold is that the game either ran to the end or ended as a walkover — anything
446
+ // shorter with two or more survivors is a settle the contract should have refused.
447
+ const survivors = seats.filter((s) => !s.eliminated).length;
448
+ c.ok('the game ran to completion or ended as a walkover', closes === ROUND_COUNT || survivors === 1, `${closes} rounds closed of ${ROUND_COUNT}, ${survivors} non-eliminated seat(s)`);
449
+ c.ok('the final digest matches the chain', same(final.roundDigest, digest), `chain ${hex(final.roundDigest)} vs replay ${hex(digest)}`);
450
+ // -------------------------------------------------------------------------------- the winner
451
+ console.log('\n── the winner ──');
452
+ const totals = seats.map((s) => grandTotal(s.card));
453
+ for (let seat = 0; seat < seatCount; seat++) {
454
+ const chainTotal = final.seatProgress.lookup(BigInt(seat)).total;
455
+ console.log(` seat ${seat}: replay total ${totals[seat]}, chain total ${chainTotal}` +
456
+ `${seats[seat].eliminated ? ' (eliminated)' : ''}`);
457
+ c.ok(`seat ${seat}: final total`, BigInt(totals[seat]) === chainTotal, `replay ${totals[seat]} vs chain ${chainTotal}`);
458
+ }
459
+ // ELIMINATED SEATS CANNOT WIN. They have already been handed back `tier - penalty`; paying
460
+ // one the pot as well would pay it twice. Among survivors the order is highest total, then a
461
+ // completer over a non-completer, then the lowest seat -- and since every survivor completes
462
+ // at the same round, in practice it is total then seat index.
463
+ let expectedWinner = -1;
464
+ for (let seat = 0; seat < seatCount; seat++) {
465
+ if (seats[seat].eliminated)
466
+ continue;
467
+ if (expectedWinner < 0) {
468
+ expectedWinner = seat;
469
+ continue;
470
+ }
471
+ const better = totals[seat] > totals[expectedWinner] ||
472
+ (totals[seat] === totals[expectedWinner] &&
473
+ seats[seat].finishedAtRound < seats[expectedWinner].finishedAtRound);
474
+ if (better)
475
+ expectedWinner = seat;
476
+ }
477
+ c.ok('the chain paid the seat the tie-break selects among survivors', BigInt(expectedWinner) === final.winnerSeatIndex, `replay ${expectedWinner} vs chain ${final.winnerSeatIndex}`);
478
+ // -------------------------------------------------------------------------------- the payout
479
+ console.log('\n── the payout ──');
480
+ const settleAction = steps.find((st) => st.action.entryPoint === 'settle')?.action;
481
+ if (!settleAction) {
482
+ c.ok('the settle transaction is in the log', false);
483
+ }
484
+ else {
485
+ const tx = await transactionByHash(settleAction.txHash);
486
+ const winnerAddr = final.seatIdentity.lookup(final.winnerSeatIndex).addr.bytes;
487
+ const rakeAddr = final.rakeAddress.bytes;
488
+ // `settle` pays out exactly the POT, which is the stakes minus whatever left it as an
489
+ // eliminated seat's refund. Read from the state just before the settle rather than assumed
490
+ // to be tier x seatCount, because an elimination moves money out of the pot.
491
+ const settleStep = steps.findIndex((st) => st.action.entryPoint === 'settle');
492
+ const potBefore = steps[settleStep - 1].led.pot;
493
+ const q = potBefore / 100n;
494
+ const spentByUsers = sumNative(tx.unshieldedSpentOutputs);
495
+ const created = sumNative(tx.unshieldedCreatedOutputs);
496
+ console.log(` settle tx ${tx.hash} in block ${tx.block.height}`);
497
+ for (const u of tx.unshieldedCreatedOutputs) {
498
+ console.log(` created ${u.value} to ${u.owner.slice(0, 24)}…`);
499
+ }
500
+ // THE decisive row, and the same one that made Gate 0's `payOut` conclusive: a transaction
501
+ // that spends no user inputs while creating real native NIGHT can only be paying out of the
502
+ // contract's own balance. That is custody, demonstrated rather than asserted.
503
+ c.ok('settle spent ZERO user inputs', spentByUsers === 0n, `${spentByUsers} spent by users`);
504
+ c.ok('settle created exactly the pot', created === potBefore, `created ${created}, pot ${potBefore}`);
505
+ c.ok('the winner was paid pot - q, at the address recorded at join', sumNativeFor(tx.unshieldedCreatedOutputs, addressOf(tx, winnerAddr)) === potBefore - q, `expected ${potBefore - q}`);
506
+ c.ok('the rake was paid q, at the address sealed at construction', sumNativeFor(tx.unshieldedCreatedOutputs, addressOf(tx, rakeAddr)) === q, `expected ${q}`);
507
+ c.ok('the pot is empty afterwards', final.pot === 0n, `pot field ${final.pot}`);
508
+ }
509
+ // ------------------------------------------------------------------------------- redemptions
510
+ const redeems = steps.filter((st) => st.action.entryPoint === 'redeem');
511
+ if (redeems.length > 0) {
512
+ console.log(`\n── ${redeems.length} redemption(s) ──`);
513
+ for (const st of redeems) {
514
+ const i = steps.indexOf(st);
515
+ const prev = steps[i - 1].led;
516
+ let seat = -1;
517
+ for (let s = 0; s < seatCount; s++) {
518
+ if (prev.seatRedeemable.lookup(BigInt(s)) > 0n &&
519
+ st.led.seatRedeemable.lookup(BigInt(s)) === 0n) {
520
+ seat = s;
521
+ }
522
+ }
523
+ if (seat < 0) {
524
+ c.ok('a redeem zeroed exactly one seat', false);
525
+ continue;
526
+ }
527
+ const owed = prev.seatRedeemable.lookup(BigInt(seat));
528
+ const tx = await transactionByHash(st.action.txHash);
529
+ const addr = final.seatIdentity.lookup(BigInt(seat)).addr.bytes;
530
+ console.log(` seat ${seat} redeemed ${owed}`);
531
+ c.ok(`redeem seat ${seat}: paid exactly what it was owed, to its join-time address`, sumNativeFor(tx.unshieldedCreatedOutputs, addressOf(tx, addr)) === owed, `expected ${owed}`);
532
+ // RECORDED, NOT ASSERTED, and the asymmetry with `settle` above is deliberate. The
533
+ // decisive custody claim is the amount and the recipient, which are asserted. Whether the
534
+ // CALLER also spent native inputs depends on how its wallet happened to fund the fee --
535
+ // `settle` was measured at zero in the previous E2E run while `abortTable`, called by the
536
+ // same wallet, was not. Asserting zero here would make the verifier fail for a reason that
537
+ // says nothing about the contract.
538
+ console.log(` (caller spent ${sumNative(tx.unshieldedSpentOutputs)} of its own inputs)`);
539
+ }
540
+ }
541
+ c.summary();
542
+ console.log(`\n(${c.count} checks in total)`);
543
+ return c.failed.length === 0 ? 0 : 1;
544
+ }
545
+ /**
546
+ * Match a raw 32-byte payout key against the bech32m owner strings the indexer reports.
547
+ *
548
+ * The contract stores the raw key (a circuit argument cannot be a bech32m string); the indexer
549
+ * reports the encoded address. Rather than re-implement the encoding here, the raw key is
550
+ * matched against whichever created output's owner decodes to it -- and the decoding is the
551
+ * wallet SDK's, via `@dust-dice/api/node`'s `userAddressBytes`, which is pure key math and needs
552
+ * no wallet.
553
+ */
554
+ function addressOf(tx, raw) {
555
+ const target = hex(raw);
556
+ for (const u of tx.unshieldedCreatedOutputs) {
557
+ try {
558
+ if (hex(userAddressBytes(u.owner)) === target)
559
+ return u.owner;
560
+ }
561
+ catch {
562
+ /* not an address this build can decode; skip */
563
+ }
564
+ }
565
+ return '<no created output belongs to this address>';
566
+ }
567
+ const address = process.argv[2];
568
+ if (!address) {
569
+ console.error('usage: npm run verify -w cli -- <table-address> [--verbose]\n\n' +
570
+ 'Replays a settled Yahtzee table from the chain alone: every roll re-derived under the\n' +
571
+ 'hold masks the players sent, every score recomputed, the winner and the payout\n' +
572
+ 're-confirmed.');
573
+ process.exit(2);
574
+ }
575
+ process.exitCode = await verify(address, process.argv.includes('--verbose'));
576
+ process.exit(process.exitCode);
577
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"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"}