feat decompression dummy proof (#290)

Co-authored-by: Arya Tabaie <15056835+Tabaie@users.noreply.github.com>
This commit is contained in:
Arya Tabaie
2024-11-19 02:13:34 -06:00
committed by GitHub
parent f462a82333
commit d9cfcef041

View File

@@ -3,7 +3,6 @@ package blobdecompression
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"os"
"path/filepath"
@@ -12,7 +11,6 @@ import (
blob_v1 "github.com/consensys/linea-monorepo/prover/lib/compressor/blob/v1"
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark-crypto/ecc/bls12-377/fr"
fr381 "github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
"github.com/consensys/linea-monorepo/prover/circuits"
"github.com/consensys/linea-monorepo/prover/circuits/blobdecompression"
@@ -25,20 +23,9 @@ import (
emPlonk "github.com/consensys/gnark/std/recursion/plonk"
)
const (
// It is just a random number. What is important is that it is not used to
// create another dummy circuit. So don't copy-paste this or at least,
// change the value if you do.
MockCircuitID = circuits.MockCircuitIDDecompression
)
// Generates a concrete proof for the decompression of the blob
func Prove(cfg *config.Config, req *Request) (*Response, error) {
if cfg.BlobDecompression.ProverMode == config.ProverModeDev {
return dummyProve(cfg, req)
}
// Parsing / validating the request
blobBytes, err := base64.StdEncoding.DecodeString(req.CompressedData)
if err != nil {
@@ -116,108 +103,82 @@ func Prove(cfg *config.Config, req *Request) (*Response, error) {
return nil, fmt.Errorf("blob checksum does not match the one computed by the assigner")
}
setup, err := circuits.LoadSetup(cfg, circuitID)
if err != nil {
return nil, fmt.Errorf("could not load the setup: %w", err)
}
maxUsableBytes, err := setup.Manifest.GetInt("maxUsableBytes")
if err != nil {
return nil, fmt.Errorf("missing maxUsableBytes in the setup manifest: %w", err)
}
maxUncompressedBytes, err := setup.Manifest.GetInt("maxUncompressedBytes")
if err != nil {
return nil, fmt.Errorf("missing maxUncompressedBytes in the setup manifest: %w", err)
}
if maxUsableBytes != expectedMaxUsableBytes {
return nil, fmt.Errorf("invalid maxUsableBytes in the setup manifest: %v, expected %v", maxUsableBytes, expectedMaxUsableBytes)
}
if maxUncompressedBytes != expectedMaxUncompressedBytes {
return nil, fmt.Errorf("invalid maxUncompressedBytes in the setup manifest: %v, expected %v", maxUncompressedBytes, expectedMaxUncompressedBytes)
}
// This section reads the public parameters. This is a time-consuming part
// of the process.
opts := []any{
emPlonk.GetNativeProverOptions(ecc.BW6_761.ScalarField(), ecc.BLS12_377.ScalarField()),
emPlonk.GetNativeVerifierOptions(ecc.BW6_761.ScalarField(), ecc.BLS12_377.ScalarField()),
}
// This actually runs the compression prover
logrus.Infof("running the decompression prover")
proof, err := circuits.ProveCheck(
&setup,
assignment,
opts...,
var (
setup circuits.Setup
proofSerialized string
)
if err != nil {
return nil, fmt.Errorf("while generating the proof: %w", err)
if cfg.BlobDecompression.ProverMode == config.ProverModeDev {
// create a dummy proof instead
srsProvider, err := circuits.NewSRSStore(cfg.PathForSRS())
if err != nil {
return nil, fmt.Errorf("could not create the SRS store: %w", err)
}
if setup, err = dummy.MakeUnsafeSetup(srsProvider, circuits.MockCircuitIDDecompression, ecc.BLS12_377.ScalarField()); err != nil {
return nil, fmt.Errorf("could not make the setup: %w", err)
}
proofSerialized = dummy.MakeProof(&setup, pubInput, circuits.MockCircuitIDDecompression)
} else {
if setup, err = circuits.LoadSetup(cfg, circuitID); err != nil {
return nil, fmt.Errorf("could not load the setup: %w", err)
}
maxUsableBytes, err := setup.Manifest.GetInt("maxUsableBytes")
if err != nil {
return nil, fmt.Errorf("missing maxUsableBytes in the setup manifest: %w", err)
}
maxUncompressedBytes, err := setup.Manifest.GetInt("maxUncompressedBytes")
if err != nil {
return nil, fmt.Errorf("missing maxUncompressedBytes in the setup manifest: %w", err)
}
if maxUsableBytes != expectedMaxUsableBytes {
return nil, fmt.Errorf("invalid maxUsableBytes in the setup manifest: %v, expected %v", maxUsableBytes, expectedMaxUsableBytes)
}
if maxUncompressedBytes != expectedMaxUncompressedBytes {
return nil, fmt.Errorf("invalid maxUncompressedBytes in the setup manifest: %v, expected %v", maxUncompressedBytes, expectedMaxUncompressedBytes)
}
// This section reads the public parameters. This is a time-consuming part
// of the process.
opts := []any{
emPlonk.GetNativeProverOptions(ecc.BW6_761.ScalarField(), ecc.BLS12_377.ScalarField()),
emPlonk.GetNativeVerifierOptions(ecc.BW6_761.ScalarField(), ecc.BLS12_377.ScalarField()),
}
// This actually runs the compression prover
logrus.Infof("running the decompression prover")
proof, err := circuits.ProveCheck(
&setup,
assignment,
opts...,
)
if err != nil {
return nil, fmt.Errorf("while generating the proof: %w", err)
}
proofSerialized = circuits.SerializeProofRaw(proof)
}
logrus.Infof("prover successful : generated proof `%++v` for public input `%v`", proof, pubInput.String())
logrus.Infof("prover successful : generated proof `%++v` for public input `%v`", proofSerialized, pubInput.String())
resp := &Response{
Request: *req,
ProverVersion: cfg.Version,
DecompressionProof: circuits.SerializeProofRaw(proof),
DecompressionProof: proofSerialized,
VerifyingKeyShaSum: setup.VerifyingKeyDigest(),
}
resp.Debug.PublicInput = "0x" + pubInput.Text(16)
return resp, nil
}
// Generates a mocked proof. Assumes the request has already been validated
func dummyProve(cfg *config.Config, req *Request) (*Response, error) {
// NB: we have not agreed on how to generate the public input with the gnark
// team yet. So as a default. We return the hash of the request and use the
// dummy circuit. That way, we get something random-looking. The circuit is
// differentiated from the dummy circuit that we use to for the light prover.
// The goal is to ensure that "compression proofs" will be accepted on the
// light prover contract and vice-versa.
buf := &bytes.Buffer{}
if err := json.NewEncoder(buf).Encode(req); err != nil {
return nil, fmt.Errorf("could not encode the request: %w", err)
}
input := utils.KeccakHash(buf.Bytes())
inputF := new(fr.Element).SetBytes(input)
// Auto-generate the setup (this will not be production settings, obviously)
// This is only practical because we use the dummy-circuit. The actual
// circuit would take extremely long time to compile and setup. Beside, we
// are using a plaintext "toxic-waste".
srsProvider, err := circuits.NewSRSStore(cfg.PathForSRS())
if err != nil {
return nil, fmt.Errorf("could not create the SRS store: %w", err)
}
setup, err := dummy.MakeUnsafeSetup(srsProvider, MockCircuitID, ecc.BLS12_377.ScalarField())
if err != nil {
return nil, fmt.Errorf("could not make the setup: %w", err)
}
proof := dummy.MakeProof(&setup, *inputF, MockCircuitID)
resp := &Response{
Request: *req,
ProverVersion: cfg.Version,
DecompressionProof: proof,
VerifyingKeyShaSum: setup.VerifyingKeyDigest(),
}
inputString := utils.HexEncodeToString(input)
resp.Debug.PublicInput = utils.ApplyModulusBls12377(inputString)
return resp, nil
}