Skip to content

Commit

Permalink
Completed sudoku eth contract
Browse files Browse the repository at this point in the history
  • Loading branch information
xqft committed Sep 19, 2024
1 parent 4569fd9 commit be56c38
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 30 deletions.
33 changes: 12 additions & 21 deletions contract/src/MinaAccountValidation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ pragma solidity ^0.8.12;

import "aligned_layer/contracts/src/core/AlignedLayerServiceManager.sol";

error AccountIsNotVerified();

contract MinaAccountValidation {
/// @notice Reference to the AlignedLayerServiceManager contract.
AlignedLayerServiceManager aligned;
Expand All @@ -21,27 +19,20 @@ contract MinaAccountValidation {
bytes memory merkleProof,
uint256 verificationDataBatchIndex,
bytes calldata pubInput
) external view returns (Account memory) {
bytes calldata encodedAccount = pubInput[32 + 8:];

) external view returns (bool) {
bytes32 pubInputCommitment = keccak256(pubInput);

bool isAccountVerified = aligned.verifyBatchInclusion(
proofCommitment,
pubInputCommitment,
provingSystemAuxDataCommitment,
proofGeneratorAddr,
batchMerkleRoot,
merkleProof,
verificationDataBatchIndex,
address(0)
);

if (isAccountVerified) {
return abi.decode(encodedAccount, (Account));
} else {
revert AccountIsNotVerified();
}
return
aligned.verifyBatchInclusion(
proofCommitment,
pubInputCommitment,
provingSystemAuxDataCommitment,
proofGeneratorAddr,
batchMerkleRoot,
merkleProof,
verificationDataBatchIndex,
address(0)
);
}

struct Account {
Expand Down
22 changes: 20 additions & 2 deletions contract/src/MinaBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,33 @@ contract MinaBridge {
}

/// @notice Returns the latest verified chain state hashes.
function getChainStateHashes() external view returns (bytes32[BRIDGE_TRANSITION_FRONTIER_LEN] memory) {
function getChainStateHashes()
external
view
returns (bytes32[BRIDGE_TRANSITION_FRONTIER_LEN] memory)
{
return chainStateHashes;
}

/// @notice Returns the latest verified chain ledger hashes.
function getChainLedgerHashes() external view returns (bytes32[BRIDGE_TRANSITION_FRONTIER_LEN] memory) {
function getChainLedgerHashes()
external
view
returns (bytes32[BRIDGE_TRANSITION_FRONTIER_LEN] memory)
{
return chainLedgerHashes;
}

/// @notice Returns true if this snarked ledger hash was bridged.
function isLedgerVerified(bytes32 ledgerHash) external view returns (bool) {
for (uint256 i = BRIDGE_TRANSITION_FRONTIER_LEN - 1; i >= 0; i++) {
if (chainLedgerHashes[i] == ledgerHash) {
return true;
}
}
return false;
}

function updateChain(
bytes32 proofCommitment,
bytes32 provingSystemAuxDataCommitment,
Expand Down
61 changes: 54 additions & 7 deletions example/eth_contract/src/Sudoku.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import "mina_bridge/contract/src/MinaBridge.sol";
import "mina_bridge/contract/src/MinaAccountValidation.sol";

contract Sudoku {
error InvalidZkappAccount();
error InvalidLedger(bytes32 ledgerHash);
error IncorrectZkappAccount(uint256 verificationKeyHash);
error UnsolvedSudoku();

/// @notice The Sudoku zkApp verification key hash.
uint256 public constant ZKAPP_VERIFICATION_KEY_HASH =
19387792026269240922986233885372582803610254872042773421723960761233199555267;
Expand All @@ -14,6 +19,8 @@ contract Sudoku {
/// @notice Mina bridge contract that validates accounts
MinaAccountValidation accountValidation;

/// @notice Latest timestamp (Unix time) at which the contract determined that a
// Sudoku was solved in the Mina ZkApp.
uint64 latestSolutionValidationAt = 0;

constructor(address _stateSettlementAddr, address _accountValidationAddr) {
Expand All @@ -23,12 +30,52 @@ contract Sudoku {

/// @notice Validates a Sudoku solution by bridging from Mina, and stores
/// the last Unix time it was solved at.
function validateSolution() external {
// 1. take the zkApp account of Sudoku.
// 2. take a relatively finalized state's ledger hash from
// the stateSettlement contract.
// 3. verify the account for ledger hash (this involves calling the bridge core)
// 4. if the account is valid, extract the zkApp state it
// 5. if the isSolved bool is true, latestSolutionValidationAt = block.timestamp
function validateSolution(
bytes32 proofCommitment,
bytes32 provingSystemAuxDataCommitment,
bytes20 proofGeneratorAddr,
bytes32 batchMerkleRoot,
bytes memory merkleProof,
uint256 verificationDataBatchIndex,
bytes calldata pubInput
) external {
bytes32 ledgerHash = bytes32(pubInput[8:8 + 32]);
if (!stateSettlement.isLedgerVerified()) {
revert InvalidLedger(ledgerHash);
}

bytes32 pubInputCommitment = keccak256(pubInput);

if (
!accountValidation.validateAccount(
proofCommitment,
provingSystemAuxDataCommitment,
proofGeneratorAddr,
batchMerkleRoot,
merkleProof,
verificationDataBatchIndex,
pubInput
)
) {
revert InvalidZkappAccount();
}

bytes calldata encodedAccount = pubInput[32 + 8:];
MinaAccountValidation.Account memory account = abi.decode(
encodedAccount,
(MinaAccountValidation.Account)
);

// TODO(xqft): check verification key, it may be a poseidon hash so we should
// need to change it to a keccak hash.
// if (account.verificationKeyKash != ZKAPP_VERIFICATION_KEY_HASH) {
// revert IncorrectZkappAccount(account.verificationKeyHash);
// }

if (account.zkapp.appState[1] == 0) {
latestSolutionValidationAt = block.timestamp;
} else {
revert UnsolvedSudoku();
}
}
}

0 comments on commit be56c38

Please sign in to comment.