Cheap hash functions for zkSNARK merkle-tree proofs, which can be calculated on-chain

We have implementations of:

  • MiMC + one-way-compression-function (davies-meyer, Miyaguchi–Preneel)
  • Pedersen hash with the Baby JubJub curve

Implementations:

There is also the knapsack hash function included in libsnark: https://github.com/scipr-lab/libsnark/blob/bd2a6ca07d4fb72f7b1174d478852234f45ce0b6/libsnark/gadgetlib1/gadgets/hashes/knapsack/tests/generate_knapsack_tests.py


The highly optimised Pedersen hash function, using all of the improvements discovered by the ZCash team comes out to around 1.5 constraints per bit.

The Knapsack hash from libsnark requires 1 constraint per dimension per bit, and again.

MiMC with an exponent of 7 and 91 rounds requires about 1.4 constraints per bit, however it may be acceptable to reduce it to 46 rounds which reduces it to around 0.7 constraints per bit.

However, both Pedersen hash and the Knapsack hash require you convert the input data into bits first, which if your input data is field elements will add ~254 constraints of overhead per field element of input.

MiMC works natively with field elements, so if your input data is an array of binary variables you must pack the bits into field elements - requiring only one extra constraint per ~253 bits of data.

All are currently a significant improvement over SHA2-256:

  • SHA256, 448bits of input, 27k constraints
  • MiMC/e7r91, 448bits of input, 730 constraints (targeting 256bit security level)
  • MiMC/e7r46, 448bits of input, 370 constraints (targeting 128bit security level)
  • Pedersen hash, 448bits of input, ~680 constraints (targeting 126bit security level)
  • Knapsack hash, 448bits of input, 1 dimension, 448 constraints
  • Knapsack hash, 448bits of input, 2 dimension, 896 constraints
  • Knapsack hash, 448bits of input, 3 dimension, 1344 constraints

However, Pedersen hash is very expensive to implement on EVM, while MiMC and the Knapsack hash are relatively cheap (e.g. 10s of kgas).

3 Likes