@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/config.d.ts +5 -0
- package/dist/config.js +29 -0
- package/dist/config.js.map +1 -0
- package/dist/contracts.d.ts +105 -0
- package/dist/contracts.js +121 -0
- package/dist/contracts.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer.d.ts +89 -0
- package/dist/indexer.js +173 -0
- package/dist/indexer.js.map +1 -0
- package/dist/verify.d.ts +2 -0
- package/dist/verify.js +577 -0
- package/dist/verify.js.map +1 -0
- package/package.json +31 -6
- package/src/config.ts +15 -3
- package/src/index.ts +10 -0
- package/src/verify.ts +331 -82
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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"}
|