Crates.io | boojum |
lib.rs | boojum |
version | 0.30.10 |
source | src |
created_at | 2024-07-05 07:31:05.559607 |
updated_at | 2024-11-28 13:30:50.571307 |
description | Boojum cryptographic library |
homepage | https://zksync.io/ |
repository | https://github.com/matter-labs/zksync-crypto/ |
max_upload_size | |
id | 1292434 |
size | 4,927,035 |
zkSync Era is a layer 2 rollup that uses zero-knowledge proofs to scale Ethereum without compromising on security or decentralization. Since it's EVM compatible (Solidity/Vyper), 99% of Ethereum projects can redeploy without refactoring or re-auditing a single line of code. zkSync Era also uses an LLVM-based compiler that will eventually let developers write smart contracts in C++, Rust and other popular languages.
The purpose of this library is to work with a very specific arithmetization with additional assumptions about the field size. Roughly, we expect to have a field F
with |F| ~ 64 bits (the size of a machine word) (the assumption about field size is not important for the strategy of arithmetization and gate placement, but it is asserted in gadget implementations for particular functions which rely on a specific field size).
The system has a hierarchy of logical function (gadgets) - gates (entities that can inscribe itself into trace) - and evaluators (relations between polynomials). Evaluators are written in the form of a trait that allows us to later on automatically compose functions to check satisfiability and compute proofs, as well as synthesize plain and recursive verifiers. Gates have additional tooling attached to them that allows the gates themselves to track the logic of where they should be placed in the trace. Note that we rely on Plonk's copy constraints and work on the copiable logical entities of "variables" to compose a final provable statement. The system is not intended for AIR arithmetization and doesn't allow to express constraints that span multiple rows of the trace.
In general, the trace contrains few varieties of columns. The main separation is between:
In addition, the trace allows you to add a lookup argument, which can also either use specialized columns to house the entries of the lookup tables, or just use general purpose columns. Tables are encoded as only one set of polynomials for now, so the total length of the trace must be larger than the total number of entries in the tables.
Note that every "gate" (as a Rust type) is unique, and so a gate can only be placed into either specialized or general purpose columns, but not into both. If one needs such functionality then it's possible to make a newtype wrapper.
Higher level logical functions (like boolean decompositions, range checks, zero checks, etc) are used to make a circuit internally inscribe themselves in different manners depending if some gates are allowed or not allowed in the particular instance of the CS. Instances of the CS with different sets of gates are considered a different type from the Rust perspective, and we rely on some inlining/constant prop/compiler work to reduce branching into static jumps.
|F|
and so we have to repeat arguments), but this will be changed so that we move to the extension field as fast as possible after committing to the witness to avoid a quite "large" chance of getting zeroes in denominator. The effect on computational expense in proving is quite negligibleWe use a lookup argument enforced via the relations \sum_i selector(x_i) / (witness(x_i) + beta) == \sum_i multiplicity(x_i) / (table(x_i) + beta)
where a lookup over specialized columns selector(x_i)
is just an identity. We also do not encode the tables as the polynomial of smaller degree to eliminate extra degree bound checks, and instead pad them with zeroes. Note that table entries never contain an element of (0,0,...,0)
as we use separate ID columns for table types in case of multiple tables (even in the case of only one table being used), and an ID like this starts with 1.
One nice feature of a lookup argument like this is that, due to its additive nature, if we do lookups over multiple witness
polynomials into the same table, instead of repeating the argument for every (tuple of) polynomial(s) (which would require a separate multiplicity column, as well as few a intermediate polynomials later on), we can "add up" multiplicities and transform the argument into something like \sum_i selector_0(x_i) / (witness_0(x_i) + beta) + \sum_i selector_1(x_i) / (witness_1(x_i) + beta) == \sum_i total_multiplicity(x_i) / (table(x_i) + beta)
, so that the total cost of a lookup is just 1 multiplicities column, and 2 (witness-related) + 1 (table-related) intermediate polynomials to encode the lhs and rhs relations on the roots of unity.
The correctness of this argument is clear.
For soundness, we use the original argument as in the "Cached quotients for fast lookups" paper, Lemma 2.4.
We need to show that it suffices to commit to the total_multiplicity
rather than to the multiplicities of witness_0
and witness_1
separately.
Suppose the equation \sum_i selector_0(x_i) / (witness_0(x_i) + X) + \sum_i selector_1(x_i) / (witness_1(x_i) + X) == \sum_i total_multiplicity(x_i) / (table(x_i) + X)
holds.
We need to show that witness_0
and witness_1
are contained in the table t
.
Let f = (witness_0 | witness_1)
, a concatenation of the values.
The equation above implies \sum_i selector_i / (f_i + X) == \sum_i total_multiplicity_i / (t_i + X)
(note that the interval length of i
on the LHS is double than the above).
By Lemma 2.4 we get f \subset t
: "subset" in the sense that every coordinate of the vector f
is a coordinate of t
.
In particular, witness_0, witness_1 \subset f \subset t
.
Note that the argument holds for several witness_i
as well. The rest of the soundness argument, for a chosen \beta
, follows directly as in the work above.
2^-40
chance to get 0
in denominatorsThere are benchmarks for 8kB of SHA256 using what we think is somewhat optimal configuration of gates + tables for SHA256 circuit. Note that even though the prover is kind-of fast, we didn't properly optimize the FFT and still use Poseidon (not Poseidon2) for configurations where we expect the proof to be used for recursion. Two scripts sha256_bench_recursive.sh
and sha256_bench_non_recursive.sh
allow you to run the corresponding tests (whether proof is expected to be used in recursion or not), and you should look for a line Proving is done, taken ...
to see the proving time, because the verifier that runs after it is quite verbose. These benchmarks use an LDE factor of 8, even though all our constraints are of degree 4 or less - however, it's a parameter that is used in some other public benchmarks. We also do not use PoW in those proofs because PoW for 20 bits is negligible (30ms), and we do not support PoW over algebraic hashes yet (however those are only ~2x slower, so also negligible). Security level is roughly 100
bits, but the FRI soundness can be boosted by increaseing the number of queries, and an increase in number of queries doesn't increase prover time (not to be confused with changing the FRI rate). Trace length is 2^16
and it uses 60 general purpose columns and 8 lookup arguments of width 4.
Note: benchmarks just try to compile to native arch and only AArch64 (read Apple M1) arch is normally tested end-to-end for now. x86-64 arithmetic implementations were tested for validity, but not end-to-end in full proofs. Note that max performance x86-64 requires extra compiler feature flags in addition to cpu = native
(AVX512 set is not used by Rust compiler even on native CPUs)
The Boojum prover is distributed under the terms of either
at your option.
zkSync Era has been through lots of testing and audits. Although it is live, it is still in alpha state and will go through more audits and bug bounties programs. We would love to hear our community's thoughts and suggestions about it! It is important to state that forking it now can potentially lead to missing important security updates, critical features, and performance improvements.
This software includes components from third parties. For a full list of these components and their licenses, see the THIRD PARTY NOTICES file.