Skip to content

Commit

Permalink
Darkpool: Compute wallet share commitment (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
joeykraut authored Mar 1, 2025
1 parent f1a1a65 commit c1258a5
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 15 deletions.
26 changes: 19 additions & 7 deletions src/Darkpool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { VerifierCore } from "./libraries/verifier/VerifierCore.sol";
import { VerificationKeys } from "./libraries/darkpool/VerificationKeys.sol";
import { console2 } from "forge-std/console2.sol";
import { IHasher } from "./libraries/merkle/IHasher.sol";
import { IVerifier } from "./libraries/verifier/IVerifier.sol";
import { ValidWalletCreateStatement, StatementSerializer } from "./libraries/darkpool/PublicInputs.sol";

// Use the StatementSerializer for all statements
Expand All @@ -15,23 +16,34 @@ using StatementSerializer for ValidWalletCreateStatement;
contract Darkpool {
/// @notice The hasher for the darkpool
IHasher public hasher;
/// @notice The verifier for the darkpool
IVerifier public verifier;

/// @notice The constructor for the darkpool
/// @param hasher_ The hasher for the darkpool
constructor(IHasher hasher_) {
/// @param verifier_ The verifier for the darkpool
constructor(IHasher hasher_, IVerifier verifier_) {
hasher = hasher_;
verifier = verifier_;
}

/// @notice Create a wallet in the darkpool
/// @param statement The statement to verify
/// @param proof The proof of `VALID WALLET CREATE`
function createWallet(ValidWalletCreateStatement memory statement, PlonkProof memory proof) public view {
// Load the verification key from the constant
VerificationKey memory vk = abi.decode(VerificationKeys.VALID_WALLET_CREATE_VKEY, (VerificationKey));

// 1. Verify the proof
// Serialize the public inputs
BN254.ScalarField[] memory publicInputs = statement.scalarSerialize();
VerifierCore.verify(proof, publicInputs, vk);
verifier.verifyValidWalletCreate(statement, proof);

// 2. Compute a commitment to the wallet shares
uint256[] memory hashInputs = new uint256[](statement.publicShares.length + 1);
hashInputs[0] = BN254.ScalarField.unwrap(statement.privateShareCommitment);
for (uint256 i = 1; i <= statement.publicShares.length; i++) {
hashInputs[i] = BN254.ScalarField.unwrap(statement.publicShares[i - 1]);
}
uint256 walletCommitment = hasher.spongeHash(hashInputs);
console2.log("walletCommitment", walletCommitment);

// 3. Insert the wallet commitment into the Merkle tree
// TODO: Implement Merkle tree
}
}
13 changes: 8 additions & 5 deletions src/libraries/darkpool/PublicInputs.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ import { BN254 } from "solidity-bn254/BN254.sol";

// This file represents the public inputs (statements) for various proofs used by the darkpool

/// @dev The number of public shares in a wallet
uint256 constant N_WALLET_SHARES = 70;

// -------------------
// | Statement Types |
// -------------------

/// @title ValidWalletCreateStatement the statement type for the `VALID WALLET CREATE` proof
struct ValidWalletCreateStatement {
/// @dev The commitment to the wallet's private shares
BN254.ScalarField walletCommitment;
BN254.ScalarField privateShareCommitment;
/// @dev The public wallet shares of the wallet
BN254.ScalarField[] publicShares;
}
Expand All @@ -33,11 +36,11 @@ library StatementSerializer {
pure
returns (BN254.ScalarField[] memory)
{
// Create array with size = 1 (for walletCommitment) + publicShares.length
// Create array with size = 1 (for privateShareCommitment) + publicShares.length
BN254.ScalarField[] memory serialized = new BN254.ScalarField[](1 + self.publicShares.length);

// Add the wallet commitment
serialized[0] = self.walletCommitment;
serialized[0] = self.privateShareCommitment;

// Add all public shares
for (uint256 i = 0; i < self.publicShares.length; i++) {
Expand All @@ -57,8 +60,8 @@ library StatementSerializer {
{
require(serialized.length >= 1, "Invalid serialized statement length");

// Extract the wallet commitment
statement.walletCommitment = serialized[0];
// Extract the private share commitment
statement.privateShareCommitment = serialized[0];

// Extract the public shares
statement.publicShares = new BN254.ScalarField[](serialized.length - 1);
Expand Down
5 changes: 3 additions & 2 deletions src/libraries/verifier/VerifierCore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ library VerifierCore {
returns (bool)
{
plonkStep1And2(proofs);
plonkStep3(publicInputs);
plonkStep3(publicInputs, vks);
Challenges[] memory batchChallenges = plonkStep4(proofs, publicInputs, vks);

// Get the base root of unity for the circuit's evaluation domain
Expand Down Expand Up @@ -222,9 +222,10 @@ library VerifierCore {

/// @notice Step 3 of the plonk verification algorithm
/// @notice Verify that the public inputs to the proof are all in the scalar field
function plonkStep3(BN254.ScalarField[][] memory publicInputs) internal pure {
function plonkStep3(BN254.ScalarField[][] memory publicInputs, VerificationKey[] memory vks) internal pure {
// Check that the public inputs are all in the scalar field
for (uint256 i = 0; i < publicInputs.length; i++) {
require(publicInputs[i].length == vks[i].l, "Invalid public input length");
for (uint256 j = 0; j < publicInputs[i].length; j++) {
BN254.validateScalarField(publicInputs[i][j]);
}
Expand Down
13 changes: 12 additions & 1 deletion test/Darkpool.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@ import { HuffDeployer } from "foundry-huff/HuffDeployer.sol";
import { PlonkProof } from "../src/libraries/verifier/Types.sol";
import { Darkpool } from "../src/Darkpool.sol";
import { IHasher } from "../src/libraries/merkle/IHasher.sol";
import { IVerifier } from "../src/libraries/verifier/IVerifier.sol";
import { TestVerifier } from "./test-contracts/TestVerifier.sol";
import { ValidWalletCreateStatement } from "../src/libraries/darkpool/PublicInputs.sol";

contract DarkpoolTest is TestUtils {
Darkpool public darkpool;

function setUp() public {
IHasher hasher = IHasher(HuffDeployer.deploy("libraries/merkle/main"));
darkpool = new Darkpool(hasher);
IVerifier verifier = new TestVerifier();
darkpool = new Darkpool(hasher, verifier);
}

function test_createWallet() public {
Expand All @@ -34,5 +38,12 @@ contract DarkpoolTest is TestUtils {
sigma_evals: [dummyScalar, dummyScalar, dummyScalar, dummyScalar],
z_bar: dummyScalar
});

BN254.ScalarField privateShareCommitment = BN254.ScalarField.wrap(randomFelt());
BN254.ScalarField[] memory publicShares = randomWalletShares();
ValidWalletCreateStatement memory statement =
ValidWalletCreateStatement({ privateShareCommitment: privateShareCommitment, publicShares: publicShares });

darkpool.createWallet(statement, proof);
}
}
12 changes: 12 additions & 0 deletions test/utils/TestUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ pragma solidity ^0.8.0;

import { Test } from "forge-std/Test.sol";
import { BN254 } from "lib/solidity-bn254/src/BN254.sol";
import { N_WALLET_SHARES } from "src/libraries/darkpool/PublicInputs.sol";

contract TestUtils is Test {
/// @dev The BN254 field modulus from roundUtils.huff
uint256 constant PRIME = BN254.R_MOD;

// --- Fuzzing Helpers --- //

/// @dev Generates a random input modulo the PRIME
/// Note that this is not uniformly distributed over the prime field, because of the "wraparound"
/// but it suffices for fuzzing test inputs
Expand Down Expand Up @@ -40,6 +43,15 @@ contract TestUtils is Test {
return low + (vm.randomUint() % range);
}

/// @dev Generate a random set of wallet shares
function randomWalletShares() internal returns (BN254.ScalarField[] memory) {
BN254.ScalarField[] memory shares = new BN254.ScalarField[](N_WALLET_SHARES);
for (uint256 i = 0; i < N_WALLET_SHARES; i++) {
shares[i] = BN254.ScalarField.wrap(randomFelt());
}
return shares;
}

// --- FFI Helpers --- //

/// @dev Helper to compile a Rust binary
Expand Down

0 comments on commit c1258a5

Please sign in to comment.