or
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
 | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | ![]() |
Emoji list | |
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
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.
Do you want to remove this version name and description?
Syncing
xxxxxxxxxx
tags:
estimation
On-chain verifier
In this document we make some back-of-the-envelope computations to see how feasible it is to verify SNARKs on main-net. We have some preliminary benchmarks made by Kenneth that show how expensive each function is. The goal of this document is to use those values and estimate SNARK verification on-chain. Similarly, we will estimate how much data the script needs to process, to understand if we are within the script data budget.
We analyse two SNARKs systems, Groth16 and vanilla-Plonk.
Preliminary benchmarks
The current limit for on-chain scripts is 10,000,000,000 of the units in the file, but the basic Plutus stuff will add a lot on top of the costs of executing the builtins.
The values of interest for this analysis are the following (were x is the size of the input in bits divided by 64):
Groth16 verifier
The verifier needs to run the following check:
\[e([A]_1, [B]_2) =? e([\alpha]_1, [\beta]_2) * e\left(\sum_{i=0}^l a_i \left[\frac{\beta * u_i(x) + \alpha * v_i(x) + w_i(x)}{\alpha}\right]_1, [\gamma]_2\right) * e([C]_1, [\delta]_2)\]
Note that the above is a pairing equation, meaning that we are checking if
\(e(a,b) = e(c,d) * e(e,f) * e(g,h)\). This check can be translated to:
\[ \begin{aligned} lhs &\leftarrow ml(a,b) \\ rhs &\leftarrow ml(c,d) * ml(e,f) * ml(g,h) \\ \texttt{accept}&\iff \texttt{final_verify}(lhs, rhs) \end{aligned} \]
We can do some ZK engineering to bring the number of l to 1, with some minor effect on the verifier (in the best case, a hash function of some public values). This means that the number of operations required for a Groth16 verifier are:
bls12_381_G1_uncompress
(16511372)bls12_381_G2_uncompress
(33114723)bls12_381_G1_mul
(97392939)bls12_381_G1_add
(1046420)bls12_381_GT_millerLoop
(402099373)bls12_381_GT_mul
(2533975)bls12_381_GT_finalVerify
(388656972)This results in a total of 2,299,066,153. With the limit of 10,000,000,000, this means that a Groth16 proof uses around 23% of the execution budget. Note, however, that the basic Plutus operations add a lot on top of the costs of executing the builtins, so we shouldn't expect to reach the limit.
In terms of size, we are handling:
resulting in 608 bytes. The current limit for scripts is 16384 bytes, which means a Groth16 verifier uses less than 4% of the data limit per script.
Plonk verifier
We assume there are no public inputs, so l = 1.
The number of operations required for a vanilla plonk verifier are (the numbering refers to each step of the verifier as in the original paper as per Feb-2023):
bls12_381_G1_uncompress
(16511372)less than
checks, overInteger
type (free or failure)less than
check, overInteger
type (free or failure)blake2b_256
of at most 1KB (521475)multiplyInteger
(641924)divideInteger
(196500)multiplyInteger
(641924)multiplyInteger
(641924)addInteger
(88512)modInteger
(196500)bls12_381_G1_uncompress
(16511372)multiplyInteger
(641924)bls12_381_G1_mul
(97392939)bls12_381_G1_add
(1046420)bls12_381_G1_add
(1046420)multiplyInteger
(641924)bls12_381_G1_mul
(97392939)bls12_381_G1_add
(1046420)bls12_381_G1_uncompress
(16511372)multiplyInteger
(641924)addInteger
(88512)modInteger
(196500)bls12_381_G1_mul
(97392939)bls12_381_G2_uncompress
(33114723)bls12_381_G1_mul
(97392939)bls12_381_G1_add
(1046420)bls12_381_GT_millerLoop
(402099373)bls12_381_GT_finalVerify
(388656972)In summary, the number of operations are the following:
We can see that this is a bit more convoluted than Groth16.. But we have less miller loops. A preliminary check gets us a computation of 3,255,167,757, which is 33% of the execution budget.
For the amount of data that the verifier needs to operate with:
This results in 1280 bytes, which is around 8% of the allowed budget.