Orbiter Research
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
      • Invitee
    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Versions and GitHub Sync Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
Invitee
Publish Note

Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

Your note will be visible on your profile and discoverable by anyone.
Your note is now live.
This note is visible on your profile and discoverable online.
Everyone on the web can find and read all notes of this public team.
See published notes
Unpublish note
Please check the box to agree to the Community Guidelines.
View profile
Engagement control
Commenting
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
  • Everyone
Suggest edit
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
Emoji Reply
Enable
Import from Dropbox Google Drive Gist Clipboard
   owned this note    owned this note      
Published Linked with GitHub
2
Subscribed
  • Any changes
    Be notified of any changes
  • Mention me
    Be notified of mention me
  • Unsubscribe
Subscribe
# Maximizing Efficiency in Ethereum ZKPs: Comparing Groth16 and FFLONK Gas Costs and Implementing Best Practices --- Author: Kiwi from [@OrbiterResearch](https://x.com/OrbiterResearch) **TL; DR:** 1. **Gas Cost Analysis of Groth16 and FFLONK Proving Systems** On Ethereum, the gas cost formulas for Groth16 and FFLONK verifiers can be expressed as: - **Groth16 Gas Cost** $\approx 207k + 7.16k \times l$ - **FFLONK Gas Cost $\approx 200k + 0.9k \times l$** Here, $l$ represents the length of the public signals. Both systems have similar cost structures but with different constants, resulting in varying overall gas costs. 2. **Best Practice for Minimizing Gas Costs in ZKP Verification:** By integrating multiple public signals using Num2Bits and Bits2Num techniques, and applying SHA-256 hashing to use the hash result as the sole public signal, substantial reductions in gas costs are achieved while maintaining data integrity. --- ## **Introduction:** The Ethereum ZKP ecosystem has evolved from the initial focus on "how to use ZKPs" to a more advanced stage of "how to optimize ZKPs for better efficiency." When implementing ZKPs on-chain, achieving the highest gas efficiency is crucial. Snarkjs supports multiple proving systems, including Groth16, PLONK, and FFLONK—with FFLONK being an optimization over PLONK specifically designed to enhance gas efficiency. This blog provides a detailed analysis of the verification gas costs for Groth16 and FFLONK based on the on-chain verifier generated by snarkjs. Additionally, it presents a best practice inspired by [Polygon's pil-stark](https://github.com/0xPolygonHermez/pil-stark/blob/main/circuits.bn128/stark_verifier.circom.ejs). For those interested in the practical aspects, the code used for gas testing and the implementation of the best practices can be found at [here](https://github.com/kiwi202202/circom-gas-test). ## Comparative Analysis of Groth16 and FFLONK Gas Costs This section provides a detailed analysis of the gas costs associated with Groth16 verification steps. The analysis begins with a breakdown of Groth16's verification logic and its corresponding gas expenditures, validated through a testing framework. Subsequently, the gas costs for FFLONK are briefly compared. ### Initial Setup: - **Scheme**: Groth16 - **Curve**: BN254 - **Proof $\pi$**: 2 G1 points ($A, C$), 1 G2 point ($B$) - **pubSignals**: Length $l$, each being a scalar field element from $\mathbb{F}_p$, where $p$ is the prime characteristic of the scalar field used in the BN254 curve. ### Verification Steps and Gas Costs: 1. **Calldata Gas Consumption**: ```solidity function verifyProof( uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[32] calldata _pubSignals ) ``` - **Fixed Proof Size**: Total of 256 bytes (_pA: 64 bytes, _pB: 128 bytes, _pC: 64 bytes) - **PubSignals**: Proportional to the number of public inputs, 32$l$ bytes - **Gas Cost Calculation**: $$ \text{Calldata Gas Cost} = (\text{Non-zero Bytes} \times 16) + (\text{Zero Bytes} \times 4) $$ Assuming all bytes are non-zero: $$ \text{Groth16 Calldata Gas Cost} = (256 + 32l) \times 16 $$ 2. **Pre-allocate Memory Space**: $Fixed\ Gas\ Cost$ ```solidity let pMem := mload(0x40) mstore(0x40, add(pMem, pLastMem)) ``` - Allocates 896 bytes but only moves the pointer. - This memory space is used for Pairing Check later. 3. **Check pubSignals in $\mathbb{F}_p$ Range**: ```solidity checkField(calldataload(add(_pubSignals, 0))) checkField(calldataload(add(_pubSignals, 32))) ``` - Gas cost for each `checkField`: 61 gas, based on empirical data. - Total gas cost for $l$ pubSignals: $61 \times l$ 4. **Check Pairing**: $Fixed\ Gas\ Cost + 6587 \times l$ This step is more complicated. We will analyze the gas cost of each small step directly in the below code comments. The main gas overhead is MSM and Pairing Check. **MSM for $l$ public signals:** The gas cost of MSM is proportional to $l$. The measured coeffient is 6587 per pubSignal, which is similar to the estimated result through [EIP-1108](https://eips.ethereum.org/EIPS/eip-1108): 6150+, because a single operation is actually: one ECADD + one ECMUL + several times add, sub, mstore, mload and other operations. The gas cost of ECADD and ECMUL of curve BN254 is shown in the table below in [EIP-1108](https://eips.ethereum.org/EIPS/eip-1108): ![Untitled](https://hackmd.io/_uploads/SJmh2d_XR.png) **Pairing Check:** In the verifyProof process of Groth16, the last step is Pairing Check, and the gas cost is the formula in the table above, $34000 \times k \ + 45000$. According to [EIP-197](https://eips.ethereum.org/EIPS/eip-197), k = bytes / 192 = 768 / 192 = 4 (in Groth16, the data amount of the input is always the same, 768 bytes) Therefore, the gas cost of Pairing Check: 34000 * 4 + 45000 = 181000 ```solidity function checkPairing(pA, pB, pC, pubSignals, pMem) -> isOk { // Allocate memory, fixed gas let _pPairing := add(pMem, pPairing) let _pVk := add(pMem, pVk) // Load MSM initial point, fixed gas mstore(_pVk, IC0x) mstore(add(_pVk, 32), IC0y) // MSM Gas Cost: Proportional to N // g1_mulAccC performs scalar multiplication of multiple elliptic curve points // (ICx, ICy) // and the pubSignals scalar array one by one, and accumulates them into _pVk // Essentially, it's an MSM operation of the elliptic curve point array // [(ICx1, ICy1), (ICx2, ICy2) ...] // and the scalar array [pubSignal_0, pubSignal_1 ...] // Accumulated onto the initial point (ICx0, ICy0) g1_mulAccC(_pVk, IC1x, IC1y, calldataload(add(pubSignals, 0))) g1_mulAccC(_pVk, IC2x, IC2y, calldataload(add(pubSignals, 32))) ... // Load points for Pairing Check, fixed gas // -A mstore(_pPairing, calldataload(pA)) mstore(add(_pPairing, 32), mod(sub(q, calldataload(add(pA, 32))), q)) // B mstore(add(_pPairing, 64), calldataload(pB)) mstore(add(_pPairing, 96), calldataload(add(pB, 32))) mstore(add(_pPairing, 128), calldataload(add(pB, 64))) mstore(add(_pPairing, 160), calldataload(add(pB, 96))) // alpha1 mstore(add(_pPairing, 192), alphax) mstore(add(_pPairing, 224), alphay) // beta2 mstore(add(_pPairing, 256), betax1) mstore(add(_pPairing, 288), betax2) mstore(add(_pPairing, 320), betay1) mstore(add(_pPairing, 352), betay2) // vk_x mstore(add(_pPairing, 384), mload(add(pMem, pVk))) mstore(add(_pPairing, 416), mload(add(pMem, add(pVk, 32)))) // gamma2 mstore(add(_pPairing, 448), gammax1) mstore(add(_pPairing, 480), gammax2) mstore(add(_pPairing, 512), gammay1) mstore(add(_pPairing, 544), gammay2) // C mstore(add(_pPairing, 576), calldataload(pC)) mstore(add(_pPairing, 608), calldataload(add(pC, 32))) // delta2 mstore(add(_pPairing, 640), deltax1) mstore(add(_pPairing, 672), deltax2) mstore(add(_pPairing, 704), deltay1) mstore(add(_pPairing, 736), deltay2) // Pairing Check: Gas cost is fixed due to constant input data size let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20) // Return result, fixed gas isOk := and(success, mload(_pPairing)) } ``` 5. **Return Result**: Finally, we return the verifyProof result , this step has fixed gas cost. ```solidity mstore(0, isValid) return(0, 0x20) ``` ### Gas Cost Summary: The total gas cost for Groth16 verification is composed of two parts: a fixed cost (FIXED_GAS) and a variable cost proportional to the number of pubSignals (K * $l$). - **Fixed Gas Cost (FIXED_GAS)**: - Approximately 207700 gas, mainly due to the Pairing Check (181000 gas). - **Proportional Gas Cost (K)**: - The gas cost per pubSignal is approximately 7160 gas, broken down as follows: $$ 7160 = 32 \times 16 (\text{calldata cost}) + 61 (\text{bn128 checkField}) + 6587 (\text{scalar multiplication and accumulation}) $$ - Actual gas cost per pubSignal ranges from 6776 to 7160 gas due to varying calldata costs for zero and non-zero bytes. The gas cost formula of Groth16's `verifyProof` function is: $$ 207700 + 7160 \times l $$ where $l$ is the number of public signals. If we do not consider calldata overhead (for example, when another contract calls the Groth16 verifier's `verifyProof` method), the formula becomes: $$ 203600 + 6792 \times l $$ ## Testing: To validate these findings, a testing framework is used: [**circom-gas-test**](https://github.com/kiwi202202/circom-gas-test). **Steps to Test a New Circuit:** 1. **Write the Circom File**: Create a `.circom` file within the `circuits` directory to define your circuit. 2. **Set Up Input**: Add a corresponding `input.json` file in the `inputs` directory to feed data into your circuit. 3. **Modify and Run Tests**: Update the `CIRCUIT_NAME` and `INPUT_PATH` in the `e2e` script to match your new circuit and input. Optionally, you can add a new `powersOfTau` file if required. Run the test with the updated script settings, and analyze the gas consumption of your circuit. ### Testing Results for Groth16 Verification Gas Costs This section presents the testing outcomes for Groth16 verification across diverse circuits and configurations. The tests are divided into two parts: comparing circuits with different scales but the same number of pubSignals, and comparing circuits with different numbers of pubSignals. ### Part 1: Sha256 Circuit Comparison **Testing Setup:** - **Environment**: Hardhat optimizer enabled, runs: 999999 - **Circuit**: Sha256 - **Public Signals**: 32 **Test Cases and Results:** 1. **Sha256_test**: Hashing 64 bytes, powersOfTau28_hez_final_16.ptau - Gas Cost: 424660 ![Untitled 1](https://hackmd.io/_uploads/S16aj__QC.png =80%x) 1. **Sha256_test_in_1024**: Hashing 1024 bytes, powersOfTau28_hez_final_19.ptau - Gas Cost: 424660 ![Untitled 2](https://hackmd.io/_uploads/SynRjOuQR.png =80%x) 1. **Sha256_test_in_4096**: Hashing 4096 bytes, powersOfTau28_hez_final_21.ptau - Gas Cost: 424636 ![Untitled 3](https://hackmd.io/_uploads/rJ1NhdOQ0.png =80%x) Despite the significant differences in circuit scale and the powersOfTau files (16, 19, 21), the gas consumption remains consistent. This result aligns with the theoretical analysis of the verification code logic. Based on the previously derived formula, the gas cost of SHA256 circuit: $$ \text{SHA256 Gas Cost} = 207700 + 7160 \times 32 = 436820 $$ The observed results are slightly higher by about 10,000 gas. This discrepancy is due to the specific format of the pubSignals, where each pubSignal only has one effective byte, with the remaining 31 bytes being zero. Adjusting for this: $$ \text{Adjusted Gas Cost} = 207700 + 6788 \times 32 = 424916 $$ This adjusted result closely matches the observed gas cost, with only a 200 gas difference, likely due to the Hardhat optimizer. The code snippet below highlights the conversion of output bytes to bits, indicating the minimal effective bytes in each pubSignal: ```jsx component bits_to_bytes[32]; for (var i = 0; i < 32; i++) { bits_to_bytes[i] = Bits2Num(8); for (var j = 0; j < 8; j++) { bits_to_bytes[i].in[7-j] <== sha256.out[i*8+j]; } out[i] <== bits_to_bytes[i].out; } ``` ### Part 2: Comparison with Different pubSignals **Testing Setup:** - **Environment**: Hardhat optimizer enabled, runs: 999999 **Test Cases and Results:** 1. **Sha256_test**: Hashing 64 bytes, 32 pubSignals - Gas Cost: 424660 ![img_v3_02b2_b40f0748-1113-4ce6-a2e1-fde10611288g](https://hackmd.io/_uploads/S1f-S9umA.png =80%x) 2. **Sha256_test_out_64**: Hashing 64 bytes, with 64 pubSignals (hash result duplicated) - Gas Cost: 641844 ![Untitled 4](https://hackmd.io/_uploads/H1er6dOX0.png =80%x) - Difference due to additional 32 pubSignals: $641844 - 424660 = 217184 = 6787 \times 32$ - Gas per additional pubSignal calculated from the previous formula : $7160 - 31\times(16 - 4) = 6788$. This result is derived by subtracting the difference in gas costs between non-zero and zero bytes on Ethereum from the base coefficient of 7160, specifically, the cost reduction due to 31 zero bytes in each pubSignal, each saving 12 gas compared to a non-zero byte. - Note that the calculated estimate of $6788$ per additional pubSignal closely aligns with the empirically tested result of $6787$. **Base Fixed Gas Cost Calculation:** Reversing the calculation to estimate the fixed gas cost: $$ 424660 - 6787 \times 32 = 207476 \approx 207700 $$ ### Multiplier Circuit Tests **Test Cases and Results:** 1. **Multiplier_1M**: Circuit with one pubSignal and 1M multiplication gate - Gas Cost: $214635 \approx 207700 + 7160$ ![Untitled 5](https://hackmd.io/_uploads/ByrSB9OXA.png =90%x) 2. **Multiplier_10k**: Circuit with one pubSignal and 10k multiplication gate - Gas Cost: $214659 \approx 207700 + 7160$ ![Untitled 6](https://hackmd.io/_uploads/B18oaddmC.png =90%x) These results reinforce the theoretical analysis, confirming that the gas cost for Groth16 verification is largely determined by the number of pubSignals, with the fixed and proportional costs closely matching the calculated values. ## Comparative Analysis of FFLONK Gas Costs FFLONK, like Groth16, has a fixed proof size but a variable length for public signals. The increase in the number of public signals will also cause the gas cost of these steps to increase proportionally, including: calldata, computing challenges, performing inversions, evaluating the Lagrange polynomial, and calculating the public input polynomial evaluation. Similar to Groth16, we can approximate the gas cost with the following formula: $$ \text{Fflonk Gas Cost} \approx 200k + 0.9k \times \text{len(public signals)} $$ When ignoring calldata consumption: $$ \text{Fflonk Gas Cost} \approx 188k + 0.6k \times \text{len(public signals)} $$ The coefficients of these formulas are mainly obtained through testing and empirical data. The testing environment utilized Hardhat with the optimizer enabled and configured for `runs: 999999` to ensure accurate and optimized results. The primary fixed gas cost arises from the pairing check, which costs around 113000 gas. Compared with Groth16, fflonk requires fewer pairings (k = 2) when calling the precompiled contract of Pairing check. Therefore, the gas cost of Pairing check is calculated as 113000 = 34000*2 + 45000 During testing of the FFLONK's gas expenses, it was observed that enabling Hardhat's optimizer with the setting `runs: 999999` led to a significant reduction of approximately 16,000 gas compared to the scenario where the optimizer was disabled. Notably, Groth16's gas cost is less affected by compiler optimizations. However, this optimization increases the bytecode size of the FFLONK contract, restricting it to a maximum of four public signals. This limitation on the number of public signals can be addressed in the 'Best Practice for Minimizing Gas Costs' section later in this article. This breakdown highlights the linear relationship between gas cost and the number of public signals, with a fixed overhead, providing insight into optimizing gas costs in zero-knowledge proof applications on Ethereum. ## Best Practice for Minimizing Gas Costs In the quest to optimize gas costs for zero-knowledge proofs (ZKPs) on Ethereum, one effective strategy involves reducing the number of public signals in the circuit. This section will detail how to implement this strategy using Num2Bits and Bits2Num templates to merge multiple pubSignals and leverage SHA-256 hashing to condense them into a single pubSignal, inspired by Polygon's [zkEVM](https://docs.polygon.technology/zkEVM/) contract. ### Merging Multiple pubSignals with Num2Bits and Bits2Num Combining multiple public signals into a single signal can reduce the gas cost associated with ZKP verification. [Circomlib](https://github.com/iden3/circomlib) provides two useful templates, **`Num2Bits`** and **`Bit2Num`**, to facilitate this process. Both functions use little-endian order. **Num2Bits Template** ``` template Num2Bits(n) { signal input in; signal output out[n]; var lc1 = 0; var e2 = 1; for (var i = 0; i < n; i++) { out[i] <-- (in >> i) & 1; out[i] * (out[i] - 1) === 0; lc1 += out[i] * e2; e2 = e2 + e2; } lc1 === in; } ``` **Bits2Num Template** ``` template Bits2Num(n) { signal input in[n]; signal output out; var lc1 = 0; var e2 = 1; for (var i = 0; i < n; i++) { lc1 += in[i] * e2; e2 = e2 + e2; } lc1 ==> out; } ``` These templates are particularly useful because they help to reduce the number of individual signals that need to be managed, thus reducing gas costs. ### Hashing pubSignals By hashing all original pubSignals and using the hash result as the sole pubSignal, we can minimize gas costs while maintaining data integrity. This approach is inspired by the [Polygon zkEVM contract](https://github.com/0xPolygonHermez/zkevm-contracts/blob/main/contracts/PolygonZkEVM.sol). The relevant Solidity code is as follows: ```solidity // Get snark bytes bytes memory snarkHashBytes = getInputSnarkBytes( initNumBatch, finalNewBatch, newLocalExitRoot, oldStateRoot, newStateRoot ); // Calculate the snark input uint256 inputSnark = uint256(sha256(snarkHashBytes)) % _RFIELD; // Verify proof if (!rollupVerifier.verifyProof(proof, [inputSnark])) { revert InvalidProof(); } ``` This method adds only a single SHA256 hash computation onchain, which incurs a relatively low gas cost. Specifically: - keccak256: 30 gas + 6 gas for each word of input data - sha256: 60 gas + 12 gas for each word of input data It is important to evaluate the security implications of reducing the SHA256 hash output to fit the BN254 elliptic curve's scalar field. While SHA256 outputs a robust 256-bit hash, reducing this to 254 bits slightly decreases collision resistance from 128 to 127 bits, and pre-image and second pre-image resistances from 256 to 254 bits. ![Untitled](https://hackmd.io/_uploads/S1uTpddQA.jpg) However, it's crucial to note that the inherent security level of the BN254 curve is about [100 bits](https://github.com/zcash/zcash/issues/714), which contextualizes the aforementioned security reduction as acceptable. This difference in security levels indicates that while the hash reduction slightly lessens SHA256's robustness, the overall security for applications using the BN254 curve is primarily governed by the curve's characteristics rather than the hash function's reduction. This compromise in theoretical security is offset by gains in computational efficiency and gas cost savings in Ethereum ZKP applications, making it a reasonable trade-off in scenarios where cost and speed are prioritized. ### Implementing pubSignals hashing in Circom To implement this in a Circom circuit, you can use an EJS template to wrap the required steps, making it easy to integrate with various circuits. Here's an example of such an implementation, you can check out the full code and examples at [Circom Gas Test](https://github.com/kiwi202202/circom-gas-test).: ``` <% var circuitPaths = internalInfo.circuitPaths; var internalCircuitName = internalInfo.circuitName; var nPublics = internalInfo.nPublics; var publicsBits = internalInfo.publicsBits; var totalBits = publicsBits.reduce((sum, bits) => sum + bits, 0); %> pragma circom 2.0.3; <% circuitPaths.forEach(function(path) { %> include "<%- path %>"; <% }); %> template Main() { signal input in[<%- internalInfo.inputSize %>]; signal output out; component internalCircuit = <%- internalCircuitName %>(); for (var i = 0; i < <%- internalInfo.inputSize %>; i++) { internalCircuit.in[i] <== in[i]; } component hasher = Sha256(<%- totalBits %>); component bitsConverters[<%- nPublics %>]; var offset = 0; <% for (var i = 0; i < nPublics; i++) { %> bitsConverters[<%= i %>] = Num2Bits(<%= publicsBits[i] %>); bitsConverters[<%= i %>].in <== internalCircuit.out[<%= i %>]; <% for (var j = 0; j < publicsBits[i]; j++) { %> hasher.in[offset + <%= publicsBits[i] - 1 - j %>] <== bitsConverters[<%= i %>].out[<%= j %>]; <% } %> offset += <%= publicsBits[i] %>; <% } %> component resultConverter = Bits2Num(256); for (var i = 0; i < 256; i++) { resultConverter.in[i] <== hasher.out[255 - i]; } out <== resultConverter.out; } component main = Main(); ``` By merging multiple public signals using Num2Bits and Bits2Num and applying SHA-256 hashing, significant gas cost reductions are achieved in on-chain ZKP verification. This method efficiently aligns circuit signals with smart contract requirements, optimizing gas usage and streamlining the verification process. An added benefit is that reducing the number of pubic signals helps avoid issues like the "transaction reverted: trying to deploy a contract whose code is too large" error, which can occur when using FFLONK. ## **Conclusion:** In our exploration of gas costs for ZKP systems on the Ethereum, we've elucidated the distinctions between Groth16 and FFLONK proving systems. Although both systems follow a similar gas cost structure, their constants differ, which points to distinct implications for practical deployments, depending on the scenario and scale of use. Additionally, it's important to note that FFLONK has a much higher requirement for the size of the `powersOfTau` file compared to Groth16, which could influence the choice of system based on resource availability and specific application needs. Our comparative analysis has established that although Groth16 is more widely used, FFLONK offers modifications that can lead to significant cost savings, especially in scenarios involving a high volume of public signals. This insight is vital for applications that rely heavily on frequent ZKP verifications, where optimizing gas efficiency is a critical concern. Moreover, the best practice derived from the techniques employed by Polygon in their [pil-stark project](https://github.com/0xPolygonHermez/pil-stark/blob/main/circuits.bn128/stark_verifier.circom.ejs) offers a robust framework for significantly reducing gas costs. By leveraging methods such as Num2Bits and Bits2Num to consolidate multiple public signals and applying a SHA-256 hash to use a single signal, we achieve a dual benefit: lowering gas consumption and maintaining data integrity. As the Ethereum ecosystem continues to mature and more developers look to implement ZKP-based applications, these insights and methodologies will play a crucial role in shaping efficient, scalable, and cost-effective solutions. For practitioners and enthusiasts alike, the journey toward optimizing ZKPs is both challenging and rewarding. As we forge ahead, it is our collective experimentation, collaboration, and innovation that will drive the evolution of blockchain technology to new heights.

Import from clipboard

Paste your markdown or webpage here...

Advanced permission required

Your current role can only read. Ask the system administrator to acquire write and comment permission.

This team is disabled

Sorry, this team is disabled. You can't edit this note.

This note is locked

Sorry, only owner can edit this note.

Reach the limit

Sorry, you've reached the max length this note can be.
Please reduce the content or divide it to more notes, thank you!

Import from Gist

Import from Snippet

or

Export to Snippet

Are you sure?

Do you really want to delete this note?
All users will lose their connection.

Create a note from template

Create a note from template

Oops...
This template has been removed or transferred.
Upgrade
All
  • All
  • Team
No template.

Create a template

Upgrade

Delete template

Do you really want to delete this template?
Turn this template into a regular note and keep its content, versions, and comments.

This page need refresh

You have an incompatible client version.
Refresh to update.
New version available!
See releases notes here
Refresh to enjoy new features.
Your user state has changed.
Refresh to load new user state.

Sign in

Forgot password

or

By clicking below, you agree to our terms of service.

Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
Wallet ( )
Connect another wallet

New to HackMD? Sign up

Help

  • English
  • 中文
  • Français
  • Deutsch
  • 日本語
  • Español
  • Català
  • Ελληνικά
  • Português
  • italiano
  • Türkçe
  • Русский
  • Nederlands
  • hrvatski jezik
  • język polski
  • Українська
  • हिन्दी
  • svenska
  • Esperanto
  • dansk

Documents

Help & Tutorial

How to use Book mode

Slide Example

API Docs

Edit in VSCode

Install browser extension

Contacts

Feedback

Discord

Send us email

Resources

Releases

Pricing

Blog

Policy

Terms

Privacy

Cheatsheet

Syntax Example Reference
# Header Header 基本排版
- Unordered List
  • Unordered List
1. Ordered List
  1. Ordered List
- [ ] Todo List
  • Todo List
> Blockquote
Blockquote
**Bold font** Bold font
*Italics font* Italics font
~~Strikethrough~~ Strikethrough
19^th^ 19th
H~2~O H2O
++Inserted text++ Inserted text
==Marked text== Marked text
[link text](https:// "title") Link
![image alt](https:// "title") Image
`Code` Code 在筆記中貼入程式碼
```javascript
var i = 0;
```
var i = 0;
:smile: :smile: Emoji list
{%youtube youtube_id %} Externals
$L^aT_eX$ LaTeX
:::info
This is a alert area.
:::

This is a alert area.

Versions and GitHub Sync
Get Full History Access

  • Edit version name
  • Delete

revision author avatar     named on  

More Less

Note content is identical to the latest version.
Compare
    Choose a version
    No search result
    Version not found
Sign in to link this note to GitHub
Learn more
This note is not linked with GitHub
 

Feedback

Submission failed, please try again

Thanks for your support.

On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

Please give us some advice and help us improve HackMD.

 

Thanks for your feedback

Remove version name

Do you want to remove this version name and description?

Transfer ownership

Transfer to
    Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

      Link with GitHub

      Please authorize HackMD on GitHub
      • Please sign in to GitHub and install the HackMD app on your GitHub repo.
      • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
      Learn more  Sign in to GitHub

      Push the note to GitHub Push to GitHub Pull a file from GitHub

        Authorize again
       

      Choose which file to push to

      Select repo
      Refresh Authorize more repos
      Select branch
      Select file
      Select branch
      Choose version(s) to push
      • Save a new version and push
      • Choose from existing versions
      Include title and tags
      Available push count

      Pull from GitHub

       
      File from GitHub
      File from HackMD

      GitHub Link Settings

      File linked

      Linked by
      File path
      Last synced branch
      Available push count

      Danger Zone

      Unlink
      You will no longer receive notification when GitHub file changes after unlink.

      Syncing

      Push failed

      Push successfully