Skip to content

Commit

Permalink
feat(mimc): alex -- mimc simplification -- start
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexandreBelling committed Feb 6, 2025
1 parent 919e9af commit 184771b
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 24 deletions.
31 changes: 23 additions & 8 deletions prover/circuits/blobdecompression/v1/snark.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@ package v1
import (
"errors"

mimcGnark "github.com/consensys/gnark/std/hash/mimc"
"github.com/consensys/gnark/std/lookup/logderivlookup"

"math/big"
"math/bits"

"github.com/consensys/linea-monorepo/prover/circuits/internal"
"github.com/consensys/linea-monorepo/prover/crypto/mimc"
"github.com/consensys/linea-monorepo/prover/crypto/mimc/gkrmimc"
"github.com/consensys/linea-monorepo/prover/utils"
"github.com/consensys/linea-monorepo/prover/utils/gnarkutil"

"github.com/consensys/gnark/constraint/solver"
Expand Down Expand Up @@ -172,11 +176,21 @@ func CheckBatchesSums(api frontend.API, hasher snarkHash.FieldHasher, nbBatches
inputAt31B.Insert(nr.Next())
}

_hsh := func(a, b frontend.Variable) frontend.Variable {
hasher.Reset()
hasher.Write(a, b)
res := hasher.Sum()
return res
_hsh := func(prevState frontend.Variable, a frontend.Variable, noHash frontend.Variable) frontend.Variable {

var b frontend.Variable

switch hasherT := hasher.(type) {

case *gkrmimc.Hasher:
b = hasherT.Compress(prevState, a)
case *mimcGnark.MiMC:
b = mimc.GnarkBlockCompression(api, prevState, a)
default:
utils.Panic("unexpected hasher type %T", hasherT)
}

return api.Select(noHash, prevState, b)
}

var (
Expand Down Expand Up @@ -213,10 +227,11 @@ func CheckBatchesSums(api frontend.API, hasher snarkHash.FieldHasher, nbBatches
noHash := api.IsZero(hashLen) // or equivalently, isZero(currNbBytesRemaining)

if i != 0 {
batchSum = api.Select(
noHash,

batchSum = _hsh(
batchSum,
_hsh(batchSum, inputAt(api.Add(31*i, startR), hashLen)),
inputAt(api.Add(31*i, startR), hashLen),
noHash,
)

internal.AssertEqualIf(api, startNext, batchSum, partialSumsT.Lookup(batchI)[0]) // if we're done with the current checksum, check that the claimed one from the table is equal to it
Expand Down
8 changes: 5 additions & 3 deletions prover/crypto/mimc/gkrmimc/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func (h *Hasher) Sum() frontend.Variable {
// 1 - Call the compression function in a loop
curr := h.state
for _, stream := range h.data {
curr = h.compress(curr, stream)
curr = h.Compress(curr, stream)
}
// flush the data already hashed
h.data = nil
Expand Down Expand Up @@ -132,10 +132,12 @@ func (h *Hasher) State() []frontend.Variable {
return []frontend.Variable{h.state}
}

// compress calls returns a frontend.Variable holding the result of applying
// Compress calls returns a frontend.Variable holding the result of applying
// the compression function of MiMC over state and block. The alleged returned
// result is pushed on the stack of all the claims to verify.
func (h *Hasher) compress(state, block frontend.Variable) frontend.Variable {
//
// This function does not modify the state of the hasher.
func (h *Hasher) Compress(state, block frontend.Variable) frontend.Variable {

newState, err := h.factory.api.Compiler().NewHint(mimcHintfunc, 1, state, block)
if err != nil {
Expand Down
51 changes: 38 additions & 13 deletions prover/utils/gnarkutil/mimc_loose_packing.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package gnarkutil

import (
"bytes"
"encoding/binary"
"errors"
hashinterface "hash"
"io"
"math/big"

"github.com/consensys/gnark-crypto/hash"
Expand Down Expand Up @@ -40,25 +42,48 @@ func PartialChecksumBatchesPackedHint(maxNbBatches int) solver.Hint {

}

// partialChecksumLooselyPackedBytes hashes 'b' and sets the result in 'buf' using
// `h` as a hasher. `b` is choped in chunks of `len(buf) - 1` bytes (let's call them `c_i`). The
// hash is obtained by hashing the chunks as `... || 0x00 || c_i-1 || 0x00 || c_i || ...`
//
// Expectedly, the hasher produces hashes with the same length as `buf`, otherwise it
// will panic.
func partialChecksumLooselyPackedBytes(b []byte, buf []byte, h hashinterface.Hash) {
pack := func(b []byte, buffStartIndex int) {
for i := range buf[:buffStartIndex] {
buf[i] = 0

var (
bufShort = make([]byte, len(buf)-1)
r = bytes.NewReader(b)
)

// zeroizeSlice zeroes all the positions of the input slice.
zeroizeSlice := func(slice []byte) {
for i := range slice {
slice[i] = 0x00
}
buf := buf[buffStartIndex:]
for n := copy(buf, b); n < len(buf); n++ {
buf[n] = 0
}

for {
_, err := r.Read(bufShort)
if err != nil {
if err == io.EOF {
break
}
panic(err)
}

buf[0] = 0x00
copy(buf[1:], bufShort)
h.Write(buf[:])
zeroizeSlice(bufShort)
}

pack(b, 1)
for i := len(buf) - 1; i < len(b); i += len(buf) - 1 {
h.Reset()
h.Write(buf)
pack(b[i:], 1)
h.Write(buf)
pack(h.Sum(nil), 0)
digest := h.Sum(nil)

if len(digest) != len(buf) {
utils.Panic("digest length is %v but expected %v", len(digest), len(buf))
}

copy(buf, digest)
}

// ChecksumLooselyPackedBytes produces the results expected by CheckBatchesSums, but more generalized
Expand Down

0 comments on commit 184771b

Please sign in to comment.