Skip to content

Commit

Permalink
Complete test on opening commitment (#19)
Browse files Browse the repository at this point in the history
* WIth an opening test case

* Complete test on opening commitments
  • Loading branch information
jimmychu0807 authored Sep 11, 2024
1 parent d928c8d commit 04eb601
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 11 deletions.
38 changes: 34 additions & 4 deletions apps/contracts/contracts/GuessingGame.sol
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,25 @@ contract GuessingGame is IGuessingGame, Ownable {
return game.commitments[round][player];
}

function getPlayerOpening(
uint32 gameId,
uint8 round,
address player
) public view validGameId(gameId) returns (uint16) {
Game storage game = games[gameId];

return game.openings[round][player];
}

function getGameHost(uint32 gameId) public view validGameId(gameId) returns (address) {
Game storage game = games[gameId];
return game.players[0];
}

/**
* Internal helper functions
**/

function _updateGameState(
uint32 gameId,
GameState state
Expand Down Expand Up @@ -202,13 +216,13 @@ contract GuessingGame is IGuessingGame, Ownable {
Game storage game = games[gameId];
uint8 round = game.currentRound;

// Verify the computation and proof
// Verify the commitment
try commitmentVerifier.verifyProof(proof, pubSignals) returns (bool result) {
if (!result) {
revert GuessingGame__InvalidCommitmentProof(gameId, round, msg.sender);
}
} catch {
revert GuessingGame__CommitmentVerificationTerminated(gameId, round, msg.sender);
revert GuessingGame__InvalidCommitmentProof(gameId, round, msg.sender);
}

game.commitments[round][msg.sender] = Commitment(pubSignals[0], pubSignals[1]);
Expand Down Expand Up @@ -243,8 +257,24 @@ contract GuessingGame is IGuessingGame, Ownable {
Game storage game = games[gameId];
uint8 round = game.currentRound;

// game.revelations[round][msg.sender] = bid;
// emit BidRevealed(gameId, round, msg.sender);
// First, check the 1st two pubSignals the same as the commitment
Commitment storage pc = game.commitments[round][msg.sender];
if (pc.submission != pubSignals[0] || pc.nullifier != pubSignals[1]) {
revert GuessingGame__UnmatchedCommitment(gameId, round, msg.sender);
}

// Then, check if it pass the zk verifier
try openingVerifier.verifyProof(proof, pubSignals) returns (bool result) {
if (!result) {
revert GuessingGame__InvalidOpeningProof(gameId, round, msg.sender);
}
} catch {
revert GuessingGame__InvalidOpeningProof(gameId, round, msg.sender);
}

// Save the openings and emit an event
game.openings[round][msg.sender] = uint16(pubSignals[2]);
emit CommitmentOpened(gameId, round, msg.sender);

// If all players have submitted revelation, update game state
bool notYetOpen = false;
Expand Down
3 changes: 1 addition & 2 deletions apps/contracts/contracts/interfaces/IGuessingGame.sol
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,8 @@ interface IGuessingGame {
error GuessingGame__PlayerAlreadyJoin(address p);
error GuessingGame__NotGameHost(uint32 gameId, address addr);
error GuessingGame__InvalidCommitmentProof(uint32 gameId, uint8 round, address addr);
error GuessingGame__CommitmentVerificationTerminated(uint32 gameId, uint8 round, address addr);
error GuessingGame__UnmatchedCommitment(uint32 gameId, uint8 round, address addr);
error GuessingGame__InvalidOpeningProof(uint32 gameId, uint8 round, address addr);
error GuessingGame__OpeningVerificationTerminated(uint32 gameId, uint8 round, address addr);
error GuessingGame__NotOneOfPlayers();

// Emitted Events
Expand Down
40 changes: 35 additions & 5 deletions apps/contracts/test/GuessingGame.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ describe("GuessingGame", () => {
bob: { in: 3, rand },
charlie: { in: 5, rand },
};
// const fullProofs = await Promise.all(inputs.map((i) => prove(i, COMMITMENT_VERIFIER_BASEPATH)));

const fullProofs = {
host: await prove(inputs.host, COMMITMENT_VERIFIER_BASEPATH),
bob: await prove(inputs.bob, COMMITMENT_VERIFIER_BASEPATH),
Expand Down Expand Up @@ -229,12 +229,42 @@ describe("GuessingGame", () => {
});

describe("L After all players submitted bids (GamteState.RoundOpen)", () => {
it("should allow player to reveal their commitments", async () => {
const { contracts, players, inputs, fullProofs } = await loadFixture(
deployContractsGameRoundReveal
);
it("should allow player to open their commitments", async () => {
const { contracts, players, inputs } = await loadFixture(deployContractsGameRoundReveal);
const { gameContract } = contracts;
const { host } = players;
const GAME_ID = 0;

const { proof, publicSignals } = await prove(inputs.host, OPENING_VERIFIER_BASEPATH);
await expect(
gameContract.openCommitment(GAME_ID, toOnChainProof(proof), publicSignals)
).to.emit(gameContract, "CommitmentOpened");

const opening = await gameContract.getPlayerOpening(GAME_ID, 0, host.address);
expect(opening).to.be.equal(inputs.host.in);
});

it("shouldn't allow players to meddling with the commitment", async () => {
const { contracts, players, inputs } = await loadFixture(deployContractsGameRoundReveal);
const { gameContract } = contracts;
const { host } = players;
const GAME_ID = 0;

// meddling with the public signals
let { proof, publicSignals } = await prove(inputs.host, OPENING_VERIFIER_BASEPATH);
publicSignals[2] = publicSignals[2] + 1;
await expect(
gameContract.openCommitment(GAME_ID, toOnChainProof(proof), publicSignals)
).to.be.revertedWithCustomError(gameContract, "GuessingGame__InvalidOpeningProof");

// Using an entirely new input
({ proof, publicSignals } = await prove(
{ in: 99, rand: randomInt(281474976710655) },
OPENING_VERIFIER_BASEPATH
));
await expect(
gameContract.openCommitment(GAME_ID, toOnChainProof(proof), publicSignals)
).to.be.revertedWithCustomError(gameContract, "GuessingGame__UnmatchedCommitment");
});
});
});

0 comments on commit 04eb601

Please sign in to comment.