Skip to content

Commit

Permalink
fix: gas optimization on verifier contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
sifnoc committed Feb 23, 2024
1 parent 6db5fb7 commit eb067b9
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 62 deletions.
48 changes: 19 additions & 29 deletions contracts/src/GrandSumVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,21 @@ contract GrandSumVerifier {

// Memory positions for the verifying key.
// The memory location starts at 0x200 due to the maximum operation on the ec_pairing function being 0x180, marking the maximum memory location used
uint256 internal constant VK_MPTR = 0x200;
uint256 internal constant VK_DIGEST_MPTR = 0x200;
uint256 internal constant K_MPTR = 0x220;
uint256 internal constant N_INV_MPTR = 0x240;
uint256 internal constant OMEGA_MPTR = 0x260;
uint256 internal constant OMEGA_INV_MPTR = 0x280;
uint256 internal constant OMEGA_INV_TO_L_MPTR = 0x2a0;
uint256 internal constant NUM_INSTANCES_MPTR = 0x2c0;
uint256 internal constant HAS_ACCUMULATOR_MPTR = 0x2e0;
uint256 internal constant ACC_OFFSET_MPTR = 0x300;
uint256 internal constant NUM_ACC_LIMBS_MPTR = 0x320;
uint256 internal constant NUM_ACC_LIMB_BITS_MPTR = 0x340;
uint256 internal constant G1_X_MPTR = 0x360;
uint256 internal constant G1_Y_MPTR = 0x380;
uint256 internal constant G2_X_1_MPTR = 0x3a0;
uint256 internal constant G2_X_2_MPTR = 0x3c0;
uint256 internal constant G2_Y_1_MPTR = 0x3e0;
uint256 internal constant G2_Y_2_MPTR = 0x400;
uint256 internal constant NEG_S_G2_X_1_MPTR = 0x420;
uint256 internal constant NEG_S_G2_X_2_MPTR = 0x440;
uint256 internal constant NEG_S_G2_Y_1_MPTR = 0x460;
uint256 internal constant NEG_S_G2_Y_2_MPTR = 0x480;

uint256 internal constant LHS_X_MPTR = 0x4a0;
uint256 internal constant LHS_Y_MPTR = 0x4c0;
uint256 internal constant N_INV_MPTR = 0x220;
uint256 internal constant LHS_X_MPTR = 0x240;
uint256 internal constant LHS_Y_MPTR = 0x260;
uint256 internal constant G1_X_MPTR = 0x280;
uint256 internal constant G1_Y_MPTR = 0x2a0;
uint256 internal constant G2_X_1_MPTR = 0x2c0;
uint256 internal constant G2_X_2_MPTR = 0x2e0;
uint256 internal constant G2_Y_1_MPTR = 0x300;
uint256 internal constant G2_Y_2_MPTR = 0x320;
uint256 internal constant NEG_S_G2_X_1_MPTR = 0x340;
uint256 internal constant NEG_S_G2_X_2_MPTR = 0x360;
uint256 internal constant NEG_S_G2_Y_1_MPTR = 0x380;
uint256 internal constant NEG_S_G2_Y_2_MPTR = 0x3a0;



function verifyProof(
address vk,
Expand Down Expand Up @@ -106,10 +96,10 @@ contract GrandSumVerifier {
// Initialize success as true
let success := true

// Copy part of the vk into memory.
// The address 0x02a0 marks the end location that `neg_s_g2` points to in the vk contract.
// This step is for verifying the opening proof; the permutation commitments in the vk contract are not needed.
extcodecopy(vk, VK_MPTR, 0x00, 0x02a0)
// Copy part of the verifying key contract into memory.
extcodecopy(vk, N_INV_MPTR, 0x40, 0x020)
// The address 0x02a0(= 0x160 + 0x140) indicates the memory location to which `neg_s_g2` points in the verifying key contract
extcodecopy(vk, G1_X_MPTR, 0x160, 0x140)

// The proof length should be divisible by `0x80` bytes, equivalent to four words.
//
Expand Down
31 changes: 15 additions & 16 deletions contracts/src/InclusionVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,18 @@ contract InclusionVerifier {

// Memory positions for the verifying key.
// The memory location starts at 0x200 due to the maximum operation on the ec_pairing function being 0x180.
uint256 internal constant VK_MPTR = 0x200;
uint256 internal constant LHS_X_MPTR = 0x2e0;
uint256 internal constant LHS_Y_MPTR = 0x300;
uint256 internal constant G1_X_MPTR = 0x360;
uint256 internal constant G1_Y_MPTR = 0x380;
uint256 internal constant G2_X_1_MPTR = 0x3a0;
uint256 internal constant G2_X_2_MPTR = 0x3c0;
uint256 internal constant G2_Y_1_MPTR = 0x3e0;
uint256 internal constant G2_Y_2_MPTR = 0x400;
uint256 internal constant NEG_S_G2_X_1_MPTR = 0x420;
uint256 internal constant NEG_S_G2_X_2_MPTR = 0x440;
uint256 internal constant NEG_S_G2_Y_1_MPTR = 0x460;
uint256 internal constant NEG_S_G2_Y_2_MPTR = 0x480;
uint256 internal constant LHS_X_MPTR = 0x200;
uint256 internal constant LHS_Y_MPTR = 0x220;
uint256 internal constant G1_X_MPTR = 0x240;
uint256 internal constant G1_Y_MPTR = 0x260;
uint256 internal constant G2_X_1_MPTR = 0x280;
uint256 internal constant G2_X_2_MPTR = 0x2a0;
uint256 internal constant G2_Y_1_MPTR = 0x2c0;
uint256 internal constant G2_Y_2_MPTR = 0x2e0;
uint256 internal constant NEG_S_G2_X_1_MPTR = 0x300;
uint256 internal constant NEG_S_G2_X_2_MPTR = 0x320;
uint256 internal constant NEG_S_G2_Y_1_MPTR = 0x340;
uint256 internal constant NEG_S_G2_Y_2_MPTR = 0x360;

function verifyProof(
address vk,
Expand Down Expand Up @@ -106,9 +105,9 @@ contract InclusionVerifier {
// Initialize success as true
let success := true

// Copy variables from the verifying key until `neg_s_g2`
extcodecopy(vk, VK_MPTR, 0x00, 0x0220)
// Copy the six variables from the verifying key up to the memory address 0x200 (= 0x160 + 0xc0), where `g2_y_2` is located.
extcodecopy(vk, G1_X_MPTR, 0x160, 0xc0)

// The proof length should be divisible by `0x80` bytes, equivalent to four words.
// The proof is structured as follows:
// 2W * n: Commitment points in the SNARK proof.
Expand Down
21 changes: 4 additions & 17 deletions contracts/src/Summa.sol
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,8 @@ contract Summa is Ownable {
* @param timestamp The timestamp at which the CEX took the snapshot of its assets and liabilities
*/
function submitCommitment(
bytes memory snarkProof,
bytes memory grandSumProof,
bytes calldata snarkProof,
bytes calldata grandSumProof,
uint256[] memory totalBalances,
uint256 timestamp
) public onlyOwner {
Expand All @@ -243,21 +243,8 @@ contract Summa is Ownable {
"Liability commitments and cryptocurrencies number mismatch"
);

// For storing first 64 bytes of snarkProof, which is corresponding to the userId
uint256 slicedSnarkProofLength = 64 + grandSumProof.length;
bytes memory slicedSnarkProof = new bytes(slicedSnarkProofLength);
for (uint256 i = 0; i < slicedSnarkProofLength; i++) {
slicedSnarkProof[i] = snarkProof[i];
}

// Concatenate the grandSumProof with snarkProof with same length
bytes memory combinedProofs = new bytes(2 * grandSumProof.length);
for (uint256 i = 0; i < grandSumProof.length; i++) {
combinedProofs[i] = grandSumProof[i];
}
for (uint256 i = 0; i < grandSumProof.length; i++) {
combinedProofs[i + grandSumProof.length] = slicedSnarkProof[i+ 64]; // Skip first 64 bytes, it's not for total balance.
}
bytes calldata slicedSnarkProof = snarkProof[0:64 + grandSumProof.length];
bytes memory combinedProofs = abi.encodePacked(grandSumProof, slicedSnarkProof[64:]);

require(grandSumVerifier.verifyProof(verifyingKey, combinedProofs, totalBalances), "Invalid grand sum proof");

Expand Down

0 comments on commit eb067b9

Please sign in to comment.